Wikibooks
enwikibooks
https://en.wikibooks.org/wiki/Main_Page
MediaWiki 1.47.0-wmf.24
first-letter
Media
Special
Talk
User
User talk
Wikibooks
Wikibooks talk
File
File talk
MediaWiki
MediaWiki talk
Template
Template talk
Help
Help talk
Category
Category talk
Cookbook
Cookbook talk
Transwiki
Transwiki talk
Wikijunior
Wikijunior talk
Subject
Subject talk
TimedText
TimedText talk
Module
Module talk
Event
Event talk
Wikibooks:Requests for deletion
4
385
4675846
4675777
2026-10-13T14:18:16Z
Codename Noreste
3441010
/* Talmudic aramic */ Deleted. ([[:m:User:Max/MaxEdit.js|MaxEdit]])
4675846
wikitext
text/x-wiki
__NEWSECTIONLINK__
[[Category:Wikibooks deletion|{{PAGENAME}}]]
{{Discussion Rooms}}
{{TOCleft}}
{{shortcut|WB:RFD}}
{{Requests for deletion/New deletion}}
{{Requests for deletion/Deletion intro}}
<!-- New deletion nominations go at the bottom of page. -->
== [[Salute, Jonathan!]] and its translations ==
<div style="column-count: 7;">
* [[Salute, Jonathan!|Interlingue/Occidental]] ([[w:en:Occidental|w]], original)
* [[Òla, Ionatà!|Audià]]
* [[Holo, Jonathan!|Cristianés]]
* [[Terve, Jonathan!|Ekumenski]]
* [[Hej, Jonathan! (Germanisch)|Germanisch]]
* [[Salom, Jonatan!|Globasa]]
* [[Àlŏ, Jonathan!|Guosa]] ([[w:en:Guosa|w]])
* [[Salut, Jonathan!|Idiom Neutral]] ([[w:en:Idiom Neutral|w]])
* [[Saluto, Jonathan! (Ido)|Ido]] ([[w:en:Ido|w]])
* [[Hallo, Jonathan!|Interlingua]] ([[w:en:Interlingua|w]])
* [[Salut, Jonathan! (Interocidental)|Interocidental]]
* [[Bune Ğonatan!|Lingaust]]
* [[Oila, Jonatan!|Lingue Simple]]
* [[Haloo, Jonatan!|Lingwa de Planeta]] ([[w:en:Lingwa de Planeta|w]])
* [[Sin Chao, Jonathan!|Masa Tang]]
* [[Salut, ionatano!|Meteza]]
* [[Salu, Jon!|Mini]]
* [[Hay, Jonathan!|Mirad]]
* [[Hai, Jon!|Monav]]
* [[Sesan Jon!|Monkel]]
* [[Salam, Jonathan!|Mundeze]]
* [[Dag, Jonathan!|Negerhollands]] ([[w:en:Negerhollands|w]])
* [[Salut Jonathan!|Neo]] ([[w:en:Neo|w]])
* [[Hej, Jonathan!|Nordien]]
* [[Saluto, Jonathan!|Novial]] ([[w:en:Novial|w]])
* [[Salute, Jonathan! (Novlingue)|Novlingue]]
* [[Alo, Jonathan!|Numo]]
* [[Hela, Jonathan!|Proyo]]
* [[Salute, Jonathan! (Romanica)|Romanica]] ([[w:en:Romanica|w]])
* [[Simi, Jonathan!|Solresol]] ([[w:en:Solresol|w]])
* [[Toki a, jan Jonatan!|Toki Pona]] ([[w:en:Toki Pona|w]])
* [[Glidis, o Jonathan!|Volapük]] ([[w:en:Volapük|w]])
</div>
There are a couple of issues here:
# Beyond their introductions, all of these books are written in languages which are not English, making them out of scope for the English Wikibooks.
# All but one of these books are in fact written in constructed languages, most of them in recently created conlangs. In some cases (e.g. [[Sin Chao, Jonathan!]]), I can't find any reliable sources describing the target language outside of the translation itself.
# Most of the translations (i.e. other than [[Salute, Jonathan!]] itself) were abandoned within the first five or so chapters (out of 100); none of them are complete, and there seems to be little effort to complete any of them.
While I recognize that this is an unusual project, and potentially one which could have some value, it's not at all clear to me that the English Wikibooks is the right place for it. — [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:24, 29 September 2024 (UTC)
: I'm really not sure what to do about these ones. While I recognize that this approach is certainly one method of teaching a language, I'm not sure that it constitutes an educational textbook. We do require that the English Wikibooks be written in English—for language-learning books, this typically means that the instructional parts are in English while the exercises are in the language being taught. I do think that if the language doesn't have much supporting evidence outside the book itself, it can safely be deleted. — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 01:01, 29 September 2024 (UTC)
: Author of the book here. I originally wanted to put it in the Interlingue Wikibooks https://ie.wikibooks.org/wiki/Principal_p%C3%A1gine but it somehow got locked when I wasn't paying attention and so I ended up putting it here. Getting it unlocked requires going through the process of starting an Incubator and all the rest so I opted for here and then started putting some English-only content once it was done. It's sort of in the same vein as books like Lingua Latina per se Illustrata that have separate versions with teacher notes and whatnot. [[Salute, Jonathan!/Capitul 1 - with notes]] After it was done the auxlang community really took to it which was a nice surprise. I think Ido has the largest number of chapters at the moment at 15.
:If the vast content of this book could be used to justify a quick reopening of the Interlingue Wikibooks to move it there, I'd love to do that. I imagine that an incubator with 100+ book chapters would be enough to open a Wikibooks and that's what this is. — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 06:02, 29 September 2024 (UTC)
: Ah, I just realized that we do have a proposal to reopen the Interlingue Wikibooks: https://meta.wikimedia.org/wiki/Requests_for_new_languages/Wikibooks_Interlingue along with an Incubator page here. https://incubator.wikimedia.org/wiki/Wb/ie/Principal_p%C3%A1gine
: How easy would it be to migrate the entirety of Salute Jonathan to there? — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 06:30, 29 September 2024 (UTC)
:: Hi @[[User:Mithridates|Mithridates]]! I'm not sure how incubator projects work, but I fully support migrating these books there. You may want to inquire over there and link to this discussion to support your request to move the content over there. Cheers! — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 13:16, 29 September 2024 (UTC)
::: Hi! Actually I have a third idea to propose after thinking about this again today (haven't been here much since I finished the book): I noticed that there is more English content than I remember and that might make it an awkward fit for the Interlingue Wikibooks. I definitely agree that having all the auxlang translations for new auxlang projects goes well beyond the scope of this Wikibooks. Finally, there are some auxlangs that are notable with their own Wikipedias.
::: So the idea is the following:
:::# Leave the original here and I can continue the work on the version with English notes and grammar. That will make it the same as Lingua Latina per se Illustrata, English by the Nature Method, Athenaze and all the rest.
:::# The Interlingua one can move to the Interlingua Wikibooks (maybe Romanica too if they want as it is sort of a dialect of Interlingua).
:::# For Ido and Lingua Franca Nova which have a Wikipedia but not a Wikibooks, I'm a little bit unsure...technically they could have their own version like the original one but would require English explanations. I could let them know and see if they are willing to do so and see what they think (work on adding English to the books vs. move the content elsewhere).
:::# The rest can move to a Github repo, then be deleted, and the front page of this book can have a single link to the repo.
::: Any thoughts on that? Adding the extra English content will be easy as it is my book and I know it inside and out.
::: Edit: [https://en.wikibooks.org/wiki/Salute,_Jonathan!/Grammar_(pronouns) this page] I just added. — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 13:50, 29 September 2024 (UTC)
:::: Thanks for taking the time to consider this! Here are my responses/questions:
::::* Is the original [[Salute, Jonathan!]] (Occidental)? Since that one is quite fleshed out, I agree that if you edit it so the primary language of the book (e.g. headers, instructions, etc) are written in English while leaving the actual story in Occidental, it would be okay and fit in more with instructional language textbooks.
::::* For your points 2 and 3, I'm not sure how those other projects work, so I'll leave it up to them. I'm not quite sure why they would need to move, since in theory they could be revised with English as the language of instruction? Although, they have been left incomplete for a long time.
::::* For your point 4, I have no problem with that. Cheers! — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 16:51, 29 September 2024 (UTC)
::::: Hello again, it's the weekend so I have a bit more time to work on this. I've decided to merge the extra content from the following five chapters since the difference is fairly small and the original chapters should now have this English content. Could you delete these five pages now that they are no longer needed? [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:02, 5 October 2024 (UTC)
::::: [[Salute, Jonathan!/Capitul 1 - with notes]]
::::: [[Salute, Jonathan!/Capitul 2 - with notes]]
::::: [[Salute, Jonathan!/Capitul 3 - with notes]]
::::: [[Salute, Jonathan!/Capitul 4 - with notes]]
::::: [[Salute, Jonathan!/Capitul 5 - with notes]] [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:02, 5 October 2024 (UTC)
:::::: [[File:Yes_check.svg|{{#ifeq:|small|8|15}}px|link=|alt=]] {{#ifeq:|small|<small>|}}'''Done'''{{#ifeq:|small|</small>|}} — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:34, 5 October 2024 (UTC)
::::::: Hi again! No luck trying to find a home for the random language translations on other auxlang wikis, can't find one that is actively maintained.
::::::: The thought struck me that maybe I could just put those ones on a sub page of my user page, would that be permitted? If not, I think I'll just stick them somewhere in GitHub and call it a day since none of the people who started the translations seem to care enough to do anything about them. I'd rather not see them outright disappear but since they aren't mine I don't care enough about them to do much more work than copy and paste them somewhere.
::::::: (I would leave the ones in languages with an ISO-639 code and Wikipedia here, of course) — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:13, 9 November 2024 (UTC)
:::::::: Thank you for checking! I don't personally see an issue with moving them to your user space right now. Cheers — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 17:21, 9 November 2024 (UTC)
::::::::: Thanks a lot! I've started a single page where I will put them all here [[User:Mithridates/SJ]] and will proceed slowly due to lack of time and also to avoid stepping on any toes / asking you to delete too much at a time and possibly deleting the wrong content.
::::::::: For this week I have put the content for the languages Audia, Cristianès, Guosa, Lingaust, Mini, Mirad, and Monav on that page as they all have a single page of content and didn't take much time to move. Please delete those. Once they are gone I will add a note on the main page letting people know where they have gone (in addition to a thank you for their interest in the book! I do love how many people have recognized it as a good source material for teaching a language). — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 04:09, 10 November 2024 (UTC)
: {{keep}} the translations for languages that have an article on the English Wikipedia, i.e. Guosa, Idiom Neutral, Ido, Interlingua, Lingwa de Planeta, Negerhollands, Neo, Novial, Occidental, Romanica, Solresol, Toki Pona, and Volapük.
: Translations for languages that don't have an article can be kept if they have reliable sources, which I was able to find for the following languages (if you think they are not reliable, please let me know):
:* Globasa: [https://www.languagesandnumbers.com/how-to-count-in-globasa/en/globasa/] [https://greyson.conlang.org/2020/01/29/shouting-out-globasa-and-pandunia/]
:* Mini: [https://jprogr.github.io/mini] [https://www.omniglot.com/language/phrases/mini.htm] [https://www.languagesandnumbers.com/how-to-count-in-mini/en/mini/]
: {{del}} and move to [[User:Mithridates/SJ]] the rest of the translations, i.e. Audià/Audian, Cristianés, Ekumenski, Germanisch, Interocidental, Lingaust, Lingue Simple, Masa Tang, Mirad, Monav, Monkel, Mundeze, Nordien, Novlingue, Numo, Proyo, and Scuian/Meteza. If you can find reliable sources for those languages, please let me know.
: In particular, I could not find resources for Audià/Audian and Monav after searching through 15 and 17 pages on Google, respectively. It doesn't help that [[Òla, Ionatà!|their]] [[Hai, Jon!|translations]] don't explain what those languages are and where to find resources for them. This makes contributing to those translations almost impossible until @[[User:Caro de Segeda|Caro de Segeda]] can provide resources to us. It's possible that the resources may have disappared from the Internet, or that those languages were created by Caro de Segeda him/herself. If you can find resources for Audià/Audian and Monav, please let me know.
: I'm notifying the primary contributors of the translations: @[[User:Caro de Segeda|Caro de Segeda]], @[[User:Frzzl|Frzzl]], @[[User:Greatscotteh|Greatscotteh]], @[[User:IHateNumbers234|IHateNumbers234]], @[[User:Jayeless2|Jayeless2]], @[[User:Morozof|Morozof]], @[[User:Omnihom|Omnihom]], @[[User:Omoutuazn|Omoutuazn]], @[[User:PovriNaivon|PovriNaivon]], @[[User:Sir Beluga|Sir Beluga]] and @[[User:Tyoyafud|Tyoyafud]]. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 09:52, 30 June 2025 (UTC)
:: Caro de Segeda said on [https://www.reddit.com/r/conlangs/comments/1lcnz9g/comment/n0sc3wx/ Reddit] that Monav was created by him/her and that he/she didn't publish any resources about it other than [[Hai, Jon!]]. With '''zero''' other resources to rely on for contributing to the translation, and the fact that Monav is in [[User:Mithridates/SJ]], [[Hai, Jon!]] should be speedy deleted. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 01:38, 3 July 2025 (UTC)
::: I've undone the speedy deletion as Caro de Segeda posted a [https://prexins.wordpress.com/2025/07/04/monav/ resource] for Monav. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 07:18, 4 July 2025 (UTC)
:::: You can delete all the ones that I have created myself, I have already moved them to other places. — [[User:Caro de Segeda|Caro de Segeda]] ([[User talk:Caro de Segeda|discuss]] • [[Special:Contributions/Caro de Segeda|contribs]]) 12:39, 5 July 2025 (UTC)
{{outdent|::::}}I don't know if this is helpful since it wouldn't apply to most of these, but [[s:mul:]] could hold some of these. — [[User:Arlo Barnes|Arlo Barnes]] ([[User talk:Arlo Barnes|discuss]] • [[Special:Contributions/Arlo Barnes|contribs]]) 09:18, 30 November 2025 (UTC)
: I don't think that would be within the scope of that project. I'm not aware of any other situation where Wikisource publishes translations of texts created on Wikimedia projects - that's usually left up to other language editions of the same project. — [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 05:34, 1 December 2025 (UTC)
:: In this situation there isn't a separate [[s:ie:]] distinct from Multilingual Wikisource (see [[meta:Wikisource#List of Wikisources]]). In fact, there are very few multilingual wikis in the Wikimedia sphere; while this project ''could'' move to a Miraheze-hosted or similar wiki farm location, I think it would be a missed opportunity. I suppose an [[Interlingue]] book could be started in [[shelf:Constructed languages]] which would have all 100 chapters as an appendix (and likewise for the other languages), but that also seems non-ideal since it requires an English-language text that doesn't currently exist to be created. [[WB:AT]] seems to describe a similar situation to this one and prescribe Wikisource as the solution, and [[WB:SOURCE]] mentions fiction as out-of-scope for Wikibooks (even as in this case, language-educational fiction). [[s:mul:Wikisource:about Wikisource]] simply speaks of source texts and doesn't mention publication requirements, so maybe that is specific to some of the monolingual editions? — [[User:Arlo Barnes|Arlo Barnes]] ([[User talk:Arlo Barnes|discuss]] • [[Special:Contributions/Arlo Barnes|contribs]]) 22:28, 5 December 2025 (UTC)
:{{keep}} 100% keep. These books are a core part of language textbooks on Wikibooks and have been for years. Not sure why this is even being debated.--[[User:Xania|Xania]] [[Image:Flag_of_Estonia.svg|15px]] [[Image:Flag_of_Ukraine.svg|15px]] [[User talk:Xania|<sup>talk</sup>]] 17:55, 16 May 2026 (UTC)
::With all due respect, some of the books included in this nomination (like [[Sin Chao, Jonathan!]]) are written in constructed languages which are not substantially attested anywhere else. I struggle to imagine any educational purpose for such a book. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:12, 17 May 2026 (UTC)
== [[International Baccalaureate]] ==
Not actually a book in and of itself; rather, it is just a compilation of links to other books —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:24, 18 October 2024 (UTC)
: Could this be salvaged as a shelf? [[User:Pppery|Pppery]] ([[User talk:Pppery|discuss]] • [[Special:Contributions/Pppery|contribs]]) 05:23, 27 January 2025 (UTC)
::Probably, but are the linked books even useful? IB exams change from year to year - sometimes quite dramatically - so an old exam guide is of very limited value. Many of these books were written 10-15 years ago, and some of them (like [[IB French]]) even have comments indicating that they're no longer applicable. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 02:18, 8 December 2025 (UTC)
:I would be interested in a book that explains what an [[International Baccalaureate]] is. They may be books about it in the real world, but they are not free and with the online world becoming a fortress of paywalls I wonder how much longer one would be able to find such information on the web. This is what the wikipedia article says:
:* This article '''is missing information''' about the educational programs and curricula. Please expand the article to include this information. Further details may exist on the [[wikipedia:Talk:International_Baccalaureate#|talk page]]. ''(March 2025)''
:[[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 02:05, 13 October 2026 (UTC)
== [[Character List for Baxter&Sagart]] ==
Seems completely out of scope as an educational book; it's just a list of characters and outlinks —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:53, 18 October 2024 (UTC)
:Adding [[Character List for Karlgren's GSR]] and [[Character List for Schuessler's CGSR]] for the same reason —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:55, 18 October 2024 (UTC)
:These three books do make a package and I agree they should be considered together. However, I strongly object to deleting them. They are really extremely useful resources. I use them every week and I know that many people who do work on Old Chinese phonology do so. There are lots of books out there that are lists of characters, these are called dictionaries. For example Axel Schuessler's ABC Etymological Dictionary of Old Chinese, or Pulleyblank's Lexicon of Reconstructed Pronunciation in Early Middle Chinese, Late Middle Chinese, and Early Mandarin. I see it as entirely a good thing for reference works of this kind to be available free online rather than only in expensive books in university research libraries. If this is in violation of a Wikibooks policy, I would at least like that policy to be drawn to my attention and to have some constructive comment offered about which Wikiproject such a resource should fall under. I will also say on a personal note that I have put literally hundreds of hours of work into these projects and it would grieve me a lot to see this work simply vanish, in particular when I know that colleagues around the world use these books. --[[User:Tibetologist|Tibetologist]] ([[User talk:Tibetologist|discuss]] • [[Special:Contributions/Tibetologist|contribs]]) 07:27, 1 November 2024 (UTC)
::Hi @[[User:Tibetologist|Tibetologist]], and thank you for the feedback! Official Wikibooks policy does not permit standalone dictionaries (see [[WB:DICT]]), though I understand the argument that it is a useful resource. I am wondering if there might be a home for it at [[Wiktionary:Wiktionary:Welcome, newcomers|Wiktionary]] or [[Wikiversity:Wikiversity:SHARE|Wikiversity]]? Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 12:14, 1 November 2024 (UTC)
:::The policy says to use Wiktionary, but these books cannot be moved there. In fact they link there, you can understand me as having made an index to wiktionary, if you like, where the ORDER of the characters is extremely important, information that would be lost in Wiktionary.
:::Wikiversity is not a project I participate in, and in any event my books here are older than it, so this option was not available for me at the relevant moment. If you are offering to move my books to Wikiversity, that is very kind of you and I will very graciously accept. [[User:Tibetologist|Tibetologist]] ([[User talk:Tibetologist|discuss]] • [[Special:Contributions/Tibetologist|contribs]]) 14:10, 1 November 2024 (UTC)
::::I have pinged over at Wikiversity Colloquium to ask about suitability and have looped you into the conversation over there. Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 18:20, 1 November 2024 (UTC)
::I concur. I'm just an undergrad who tries to learn about Sino-Tibetan historical linguistics in his free time but I've found this wikibook to be incredibly useful, and I keep it open in one tab while I watch Professor Nathan Hill's lectures that he uploads to youtube in another tab, and another tab for taking notes. In fact if I remember correctly Professor Hill actually pointed his students to this wikibook.
::I'm not familiar with [[wikiversity:Wikiversity:SHARE|Wikiversity]] but if all the content were as accessible there as it is here then I think that could work. [[User:ChromeBones|ChromeBones]] ([[User talk:ChromeBones|discuss]] • [[Special:Contributions/ChromeBones|contribs]]) 02:43, 9 July 2025 (UTC)
:Per [[:v:Wikiversity:Colloquium#Import_Resource_From_Wikibooks?]], I recommend copying and pasting, including attribution via the edit summary and talk page, add appropriate categories and links, and then it could be deleted locally. —[[User:Koavf|Justin (<span style="color:grey">ko'''a'''vf</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 22:32, 3 November 2024 (UTC)
== [[Suomen kieli käyttöön]] ==
Multiple pages in this book are written entirely in Finnish, which is out of the enWB scope. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 00:09, 19 October 2024 (UTC)
:I was going to say whether we should ask any fiwikibooks sysop to maybe see if this could be transwikied to fiwb if it's within the scope there. But [[:fi:Toiminnot:Käyttäjät/sysop]] indicates that there are only 3 sysops, and only {{u|Anr}} and {{u|Zache}} have made edits this ''year''. If they deem it to be salvageable, then transwiki + delete, otherwise straight-up delete. --[[User:SHB2000|SHB2000]] ([[User talk:SHB2000|discuss]] • [[Special:Contributions/SHB2000|contribs]]) 11:24, 14 November 2024 (UTC)
::It seems that the idea behind the book was for the pages to be bilingual, as it’s a language learning book. That’s why there are Finnish texts included intentionally even on the pages that are complete. There are similar books in dewikibooks and ruwikibooks as well. For the English version, I think the easiest way to proceed would be to clean up and adjust the page layout to fit enwikibooks better, and then translate the missing parts. By the way, if anyone wants to update the book’s name in English, it can be titled ''"Using the Finnish Language"'' or ''"Put Finnish Language into Use"'' for a direct translation. [[User:Zache|Zache]] ([[User talk:Zache|discuss]] • [[Special:Contributions/Zache|contribs]]) 11:57, 14 November 2024 (UTC)
== [[AT&T Mobility FAQ]] ==
* [[AT&T Mobility FAQ]]
* [[AT&T Mobility FAQ/MEdia Net Configuration]]
* [[AT&T Mobility FAQ/Data Connect Configuration]]
An ''extremely'' outdated FAQ on AT&T's cell phone services. Most of this document was written 20+ years ago as a Usenet FAQ; very little of it is accurate or useful anymore (particularly the two subpages, which have to do with obsolete configurations for "tethering" a computer to a cell phone). No objection if someone wants to update it, but there's clearly been no appetite to do that. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 22:20, 30 December 2024 (UTC)
:I'm wondering if it might make sense for us to develop some kind of policy on archiving books here. There are many like this one that have a good deal of content but are extremely out of date and just not useful as originally intended. ——[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 22:34, 30 December 2024 (UTC)
::@[[User:Kittycataclysm|Kittycataclysm]]: See the newly developed [[Wikibooks:Outdated books]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 00:16, 31 December 2024 (UTC)
:::Ooh, thanks - something like that seems like it could be an appropriate way to handle this book. A lot of the other outdated books I've tagged have been so incomplete that they wouldn't have been particularly useful even as historical references; this one might at least have some interest.
:::Any chance we can get a separate namespace (maybe "Archive:") set up for archived book content? That'd make it possible to do things like exclude them from on-site search by default. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:07, 31 December 2024 (UTC)
::::I think this might be a more extended discussion, so I'll bump it over to the [[Wikibooks talk:Outdated books|talk page of the draft policy]]! —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 21:54, 31 December 2024 (UTC)
== Algebra/Chapter 10/Symmetric Polynomials ==
I personally believe that [[Algebra/Chapter 10/Symmetric Polynomials|this]], and all of the sections should be deleted for the fact that this goes WAY beyond the scope of what was intended for the Chapter (Algebra II level polynomials). [[User:GoreyCat|GoreyCat]] ([[User talk:GoreyCat|discuss]] • [[Special:Contributions/GoreyCat|contribs]]) 15:07, 6 February 2025 (UTC)
:'''Split''': Deletion here is not the best solution (see [[w:WP:ATD]]). Instead, this page and its subpages should be moved to another book, most likely [[Abstract Algebra]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 17:35, 6 February 2025 (UTC)
:{{keep}} since there is a good amount of content. If [[Abstract Algebra]] is appropriate, it seems like a fine idea to move there. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 22:59, 7 February 2025 (UTC)
::Eh, yeah, I supposed moving it is better. I just don't think it's suitable for where it appears. [[User:GoreyCat|GoreyCat]] ([[User talk:GoreyCat|discuss]] • [[Special:Contributions/GoreyCat|contribs]]) 01:40, 8 February 2025 (UTC)
== [[Puredyne]] ==
Development of Puredyne Linux was discontinued in 2012, and the software no longer appears to be available for download anywhere. (An archive of the web site is still up - with a bunch of embedded spam links - but the download links are all dead.) Is this a suitable candidate for archival (cf. [[Wikibooks:Outdated books]]), or should it just be deleted? [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 04:35, 5 March 2025 (UTC)
:I'd just archive stuff like this. Looks like a decent bit of work went into it, and you never know when someone might need to use Puredyne for some obscure project. I'd be willing to bet mirrors exist of it somewhere, or someone has it on a drive. If you want to find some stuff worth deleting, comb through [[:Category:Allbooks categories]]. [[User:MediaKyle|MediaKyle]] ([[User talk:MediaKyle|discuss]] • [[Special:Contributions/MediaKyle|contribs]]) 11:30, 5 March 2025 (UTC)
== [[Template:Qr-twwp]] ==
This isn't exactly a request to delete the template, but rather to merge it with {{tlx|Copypaste}}. The {{tlx|Qr-twwp}} template serves the same purpose as {{tlx|Copypaste}}, but without the seven-day period after which the page is deleted. This leads to confusion, as well as a perpetually full [[:Category:Queried pages]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 17:37, 30 March 2025 (UTC)
== [[Ghouls of the Miskatonic]] ==
I don't think that a plot summary of a book is in-scope here. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 18:43, 20 August 2025 (UTC)
:{{vd}} - at least, not a summary of ''this'' book. A summary and/or study guide to a notable work of literature might be in scope, but this is certainly not one. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:23, 25 August 2025 (UTC)
::Hi. I am the creator of the pages of this book. If I understand correctly, it has to be a summary of a notable work of literature? So what exactly is defined as such? I only started this as I thought it would be fun, interesting and encouraging to others who read the Arkham Horror novels, and I thought it was permitted as I've seen other summaries of books on wikibooks. [[User:Dayne90|Dayne90]] ([[User talk:Dayne90|discuss]] • [[Special:Contributions/Dayne90|contribs]]) 13:27, 26 August 2025 (UTC)
:::Your problem is it is just the plot... it needs to include an educational textual analysis to be in scope [[User:MarcGarver|MarcGarver]] ([[User talk:MarcGarver|discuss]] • [[Special:Contributions/MarcGarver|contribs]]) 12:47, 28 August 2025 (UTC)
::::And ideally it'd be a text which has ''already'' been the subject of literary analysis, such that the analysis on Wikibooks isn't original research. A notable work of literature like ''Frankenstein'' or ''Moby-Dick'' would easily meet that requirement; a tie-in novel for a tabletop RPG probably does not. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 22:08, 29 August 2025 (UTC)
== [[A-level Computing AQA Paper 1 Skeleton program 2027]] ==
This was proposed for speedy deletion by [[User:Omphalographer]] as 'not being a book'. However, I think this page's future requires further discussion from the community. Maybe some input would be appreciated?[[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 23:51, 21 September 2026 (UTC)
:As best I can tell, this is a page students are using to collaborate on solutions for a standardized test. There are a number of similar pages for other years linked from [[A-level Computing/AQA/Paper 1/Skeleton program]].
:This is not a good fit for Wikibooks. If these students are interested in this kind of collaboration, it should take place elsewhere. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:14, 22 September 2026 (UTC)
::The project can be moved to Wikiversity, I think. If the students can contribute it and make sure it complies with Wikibooks' guidelines, it can stay here. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 00:17, 22 September 2026 (UTC)
:::@[[User:Omphalographer|Omphalographer]] @[[User:TechVindicator|TechVindicator]]
:::There's been a Wikibook on this every single year, as I mentioned in my comment on the deletion notice. That doesn't mean that this shouldn't be on Wikiversity, just that there is ample precedent of it being a Wikibook. Dunno if this matter to those kind of editorial decisions, though. [[Special:Contributions/~2026-51010-27|~2026-51010-27]] ([[User talk:~2026-51010-27|talk]]) 13:39, 22 September 2026 (UTC)
::::@[[User:~2026-51010-27|~2026-51010-27]]: How would the page comply with [[WB:What is Wikibooks?|Wikibooks' mission]]?. Could you provide an explanation of what the project is? If it's a collaborative project to work on solutions for a standardized test (like @[[User:Omphalographer|Omphalographer]] said), it would be more suitable for Wikiversity. If it's a textbook about A-level computing, then it would be suitable here. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 13:58, 22 September 2026 (UTC)
:::::Hi,
:::::This is definitely the former, not the latter. As I said, I don't particularly think this should be on Wikibooks, it just happens the previous years had been, and clearly they weren't subject to this degree of scrutiny 😅
:::::I have created https://en.wikiversity.org/wiki/A-level_Computer_Science_AQA_Paper_1_Skeleton_program_2027 - I'll delete the content of the page and put the link at the top. If there is a more appropriate banner to indicate the migration, please make it look how it should :D [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 10:23, 29 September 2026 (UTC)
::::::I can't seem to put a link without the edit being deemed destructive, so I'll let you trusted people do what's needed. [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 10:27, 29 September 2026 (UTC)
== [[Talmudic aramic]] ==
{{closed|Deleted per consensus below. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:18, 13 October 2026 (UTC)}}
Per the user's other mass-created pages, I concur with the AI flagging that Kittycataclysm placed on the page. I believe this to be LLM-generated, and it should thus be deleted. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 03:29, 30 September 2026 (UTC)
:{{vd}}, LLM spam. [[User:Ternera|Ternera]] ([[User talk:Ternera|discuss]] • [[Special:Contributions/Ternera|contribs]]) 13:22, 30 September 2026 (UTC)
:{{vd}} - like most LLM-generated books, this is heavy on structure and light on substance. Most of the content amounts to a poorly organized glossary, and there are a lot of pieces missing. (For instance, there is no discussion of the grammar of the language beyond a couple of fixed expressions.) [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:11, 1 October 2026 (UTC)
:{{vd}} per stated reasoning. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 14:43, 12 October 2026 (UTC)
{{end closed}}
== [[Job Search]] ==
* as well as [[Job Search Automation for College Students]].
Neither of these books contains any useful information. The first book seems to be written primarily to funnel users to the second, and the second to funnel users to [[PlanoTse Handbook for Job Search Automation]], which was deleted last year. (The deletion request doesn't seem to have been archived.)
The sum total of information in these two books is, essentially, "you can search for jobs online", which is insultingly trivial. The second book's suggestion that users automate the job search process is of no practical value; most web search engines and job search sites nowadays will detect and block automated access.
[[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:36, 1 October 2026 (UTC)
: {{vd}} and redirect to [[Find Employment]]. ‑‑[[User:Kai Burghardt|Kai Burghardt]] ([[User talk:Kai Burghardt|discuss]] • [[Special:Contributions/Kai Burghardt|contribs]]) 05:14, 2 October 2026 (UTC)
== [[Wikipage]] ==
Like a few other books created by this user, the purpose of this book appears to have been to promote a piece of software written by the author ([[User:Planotse]]). The software is no longer available, and there is no actual content in the book.
[[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:40, 1 October 2026 (UTC)
:{{Vd}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
== [[Becoming a Linguistic Mastermind]] ==
Old book (created 2007) with no substantial content. The intent of this book appears to have been to create a single textbook encompassing ''all'' languages, with sub-courses for each language at [[Becoming a Linguistic Mastermind/The courses]], but no such courses were ever created. An analogous project on dewikibooks [[:b:de:Wikibooks:Löschkandidaten/ 2011-04#Der einfache Weg zum Sprachgenie|was deleted in 2011 for similar reasons]]. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:20, 7 October 2026 (UTC)
:{{Vd}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
== [[The Permanent Advantage]] ==
Probably LLM-generated, given broken templates, references to Claude, and section identifiers. This could probably be speedied, but not 100% sure so throwing it to RfD. Even regardless of whether it's LLM-generated or not, I can't see any way it's really suitable for the project. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 07:49, 10 October 2026 (UTC)
:{{vd}} - a book ''about'' chess problems isn't necessarily out of scope, but there needs to be some written content to accompany the problems. And I'm not sure these are even meaningful problems - the few problems with viewable Lichess links appear to be in the early game, so there aren't necessarily objective "solutions" to them. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:51, 10 October 2026 (UTC)
:{{vd}}, the Claude references throughout the book support that it's LLM-generated. [[User:Ternera|Ternera]] ([[User talk:Ternera|discuss]] • [[Special:Contributions/Ternera|contribs]]) 14:55, 11 October 2026 (UTC)
== [[Digital Synthora]] ==
Not within WB scope since it seems to be entirely fabricated by the editor. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 14:20, 12 October 2026 (UTC)
:{{vd}} While some amount of original research is allowed here, completely fabricated topics aren't. This is just fiction writing, which is nice, but not within our scope. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
:{{vd}} - per my initial tag, this appears to be an invention of the page creator; I can't find anything relevant online beyond the empty https://synthoraactstuff.fandom.com/. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 01:32, 13 October 2026 (UTC)
nz523lfi95gukpbe0layxjttyk504ym
4675850
4675846
2026-10-13T14:24:10Z
Codename Noreste
3441010
/* Job Search */ Deleted and redirected. ([[:m:User:Max/MaxEdit.js|MaxEdit]])
4675850
wikitext
text/x-wiki
__NEWSECTIONLINK__
[[Category:Wikibooks deletion|{{PAGENAME}}]]
{{Discussion Rooms}}
{{TOCleft}}
{{shortcut|WB:RFD}}
{{Requests for deletion/New deletion}}
{{Requests for deletion/Deletion intro}}
<!-- New deletion nominations go at the bottom of page. -->
== [[Salute, Jonathan!]] and its translations ==
<div style="column-count: 7;">
* [[Salute, Jonathan!|Interlingue/Occidental]] ([[w:en:Occidental|w]], original)
* [[Òla, Ionatà!|Audià]]
* [[Holo, Jonathan!|Cristianés]]
* [[Terve, Jonathan!|Ekumenski]]
* [[Hej, Jonathan! (Germanisch)|Germanisch]]
* [[Salom, Jonatan!|Globasa]]
* [[Àlŏ, Jonathan!|Guosa]] ([[w:en:Guosa|w]])
* [[Salut, Jonathan!|Idiom Neutral]] ([[w:en:Idiom Neutral|w]])
* [[Saluto, Jonathan! (Ido)|Ido]] ([[w:en:Ido|w]])
* [[Hallo, Jonathan!|Interlingua]] ([[w:en:Interlingua|w]])
* [[Salut, Jonathan! (Interocidental)|Interocidental]]
* [[Bune Ğonatan!|Lingaust]]
* [[Oila, Jonatan!|Lingue Simple]]
* [[Haloo, Jonatan!|Lingwa de Planeta]] ([[w:en:Lingwa de Planeta|w]])
* [[Sin Chao, Jonathan!|Masa Tang]]
* [[Salut, ionatano!|Meteza]]
* [[Salu, Jon!|Mini]]
* [[Hay, Jonathan!|Mirad]]
* [[Hai, Jon!|Monav]]
* [[Sesan Jon!|Monkel]]
* [[Salam, Jonathan!|Mundeze]]
* [[Dag, Jonathan!|Negerhollands]] ([[w:en:Negerhollands|w]])
* [[Salut Jonathan!|Neo]] ([[w:en:Neo|w]])
* [[Hej, Jonathan!|Nordien]]
* [[Saluto, Jonathan!|Novial]] ([[w:en:Novial|w]])
* [[Salute, Jonathan! (Novlingue)|Novlingue]]
* [[Alo, Jonathan!|Numo]]
* [[Hela, Jonathan!|Proyo]]
* [[Salute, Jonathan! (Romanica)|Romanica]] ([[w:en:Romanica|w]])
* [[Simi, Jonathan!|Solresol]] ([[w:en:Solresol|w]])
* [[Toki a, jan Jonatan!|Toki Pona]] ([[w:en:Toki Pona|w]])
* [[Glidis, o Jonathan!|Volapük]] ([[w:en:Volapük|w]])
</div>
There are a couple of issues here:
# Beyond their introductions, all of these books are written in languages which are not English, making them out of scope for the English Wikibooks.
# All but one of these books are in fact written in constructed languages, most of them in recently created conlangs. In some cases (e.g. [[Sin Chao, Jonathan!]]), I can't find any reliable sources describing the target language outside of the translation itself.
# Most of the translations (i.e. other than [[Salute, Jonathan!]] itself) were abandoned within the first five or so chapters (out of 100); none of them are complete, and there seems to be little effort to complete any of them.
While I recognize that this is an unusual project, and potentially one which could have some value, it's not at all clear to me that the English Wikibooks is the right place for it. — [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:24, 29 September 2024 (UTC)
: I'm really not sure what to do about these ones. While I recognize that this approach is certainly one method of teaching a language, I'm not sure that it constitutes an educational textbook. We do require that the English Wikibooks be written in English—for language-learning books, this typically means that the instructional parts are in English while the exercises are in the language being taught. I do think that if the language doesn't have much supporting evidence outside the book itself, it can safely be deleted. — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 01:01, 29 September 2024 (UTC)
: Author of the book here. I originally wanted to put it in the Interlingue Wikibooks https://ie.wikibooks.org/wiki/Principal_p%C3%A1gine but it somehow got locked when I wasn't paying attention and so I ended up putting it here. Getting it unlocked requires going through the process of starting an Incubator and all the rest so I opted for here and then started putting some English-only content once it was done. It's sort of in the same vein as books like Lingua Latina per se Illustrata that have separate versions with teacher notes and whatnot. [[Salute, Jonathan!/Capitul 1 - with notes]] After it was done the auxlang community really took to it which was a nice surprise. I think Ido has the largest number of chapters at the moment at 15.
:If the vast content of this book could be used to justify a quick reopening of the Interlingue Wikibooks to move it there, I'd love to do that. I imagine that an incubator with 100+ book chapters would be enough to open a Wikibooks and that's what this is. — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 06:02, 29 September 2024 (UTC)
: Ah, I just realized that we do have a proposal to reopen the Interlingue Wikibooks: https://meta.wikimedia.org/wiki/Requests_for_new_languages/Wikibooks_Interlingue along with an Incubator page here. https://incubator.wikimedia.org/wiki/Wb/ie/Principal_p%C3%A1gine
: How easy would it be to migrate the entirety of Salute Jonathan to there? — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 06:30, 29 September 2024 (UTC)
:: Hi @[[User:Mithridates|Mithridates]]! I'm not sure how incubator projects work, but I fully support migrating these books there. You may want to inquire over there and link to this discussion to support your request to move the content over there. Cheers! — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 13:16, 29 September 2024 (UTC)
::: Hi! Actually I have a third idea to propose after thinking about this again today (haven't been here much since I finished the book): I noticed that there is more English content than I remember and that might make it an awkward fit for the Interlingue Wikibooks. I definitely agree that having all the auxlang translations for new auxlang projects goes well beyond the scope of this Wikibooks. Finally, there are some auxlangs that are notable with their own Wikipedias.
::: So the idea is the following:
:::# Leave the original here and I can continue the work on the version with English notes and grammar. That will make it the same as Lingua Latina per se Illustrata, English by the Nature Method, Athenaze and all the rest.
:::# The Interlingua one can move to the Interlingua Wikibooks (maybe Romanica too if they want as it is sort of a dialect of Interlingua).
:::# For Ido and Lingua Franca Nova which have a Wikipedia but not a Wikibooks, I'm a little bit unsure...technically they could have their own version like the original one but would require English explanations. I could let them know and see if they are willing to do so and see what they think (work on adding English to the books vs. move the content elsewhere).
:::# The rest can move to a Github repo, then be deleted, and the front page of this book can have a single link to the repo.
::: Any thoughts on that? Adding the extra English content will be easy as it is my book and I know it inside and out.
::: Edit: [https://en.wikibooks.org/wiki/Salute,_Jonathan!/Grammar_(pronouns) this page] I just added. — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 13:50, 29 September 2024 (UTC)
:::: Thanks for taking the time to consider this! Here are my responses/questions:
::::* Is the original [[Salute, Jonathan!]] (Occidental)? Since that one is quite fleshed out, I agree that if you edit it so the primary language of the book (e.g. headers, instructions, etc) are written in English while leaving the actual story in Occidental, it would be okay and fit in more with instructional language textbooks.
::::* For your points 2 and 3, I'm not sure how those other projects work, so I'll leave it up to them. I'm not quite sure why they would need to move, since in theory they could be revised with English as the language of instruction? Although, they have been left incomplete for a long time.
::::* For your point 4, I have no problem with that. Cheers! — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 16:51, 29 September 2024 (UTC)
::::: Hello again, it's the weekend so I have a bit more time to work on this. I've decided to merge the extra content from the following five chapters since the difference is fairly small and the original chapters should now have this English content. Could you delete these five pages now that they are no longer needed? [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:02, 5 October 2024 (UTC)
::::: [[Salute, Jonathan!/Capitul 1 - with notes]]
::::: [[Salute, Jonathan!/Capitul 2 - with notes]]
::::: [[Salute, Jonathan!/Capitul 3 - with notes]]
::::: [[Salute, Jonathan!/Capitul 4 - with notes]]
::::: [[Salute, Jonathan!/Capitul 5 - with notes]] [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:02, 5 October 2024 (UTC)
:::::: [[File:Yes_check.svg|{{#ifeq:|small|8|15}}px|link=|alt=]] {{#ifeq:|small|<small>|}}'''Done'''{{#ifeq:|small|</small>|}} — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:34, 5 October 2024 (UTC)
::::::: Hi again! No luck trying to find a home for the random language translations on other auxlang wikis, can't find one that is actively maintained.
::::::: The thought struck me that maybe I could just put those ones on a sub page of my user page, would that be permitted? If not, I think I'll just stick them somewhere in GitHub and call it a day since none of the people who started the translations seem to care enough to do anything about them. I'd rather not see them outright disappear but since they aren't mine I don't care enough about them to do much more work than copy and paste them somewhere.
::::::: (I would leave the ones in languages with an ISO-639 code and Wikipedia here, of course) — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:13, 9 November 2024 (UTC)
:::::::: Thank you for checking! I don't personally see an issue with moving them to your user space right now. Cheers — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 17:21, 9 November 2024 (UTC)
::::::::: Thanks a lot! I've started a single page where I will put them all here [[User:Mithridates/SJ]] and will proceed slowly due to lack of time and also to avoid stepping on any toes / asking you to delete too much at a time and possibly deleting the wrong content.
::::::::: For this week I have put the content for the languages Audia, Cristianès, Guosa, Lingaust, Mini, Mirad, and Monav on that page as they all have a single page of content and didn't take much time to move. Please delete those. Once they are gone I will add a note on the main page letting people know where they have gone (in addition to a thank you for their interest in the book! I do love how many people have recognized it as a good source material for teaching a language). — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 04:09, 10 November 2024 (UTC)
: {{keep}} the translations for languages that have an article on the English Wikipedia, i.e. Guosa, Idiom Neutral, Ido, Interlingua, Lingwa de Planeta, Negerhollands, Neo, Novial, Occidental, Romanica, Solresol, Toki Pona, and Volapük.
: Translations for languages that don't have an article can be kept if they have reliable sources, which I was able to find for the following languages (if you think they are not reliable, please let me know):
:* Globasa: [https://www.languagesandnumbers.com/how-to-count-in-globasa/en/globasa/] [https://greyson.conlang.org/2020/01/29/shouting-out-globasa-and-pandunia/]
:* Mini: [https://jprogr.github.io/mini] [https://www.omniglot.com/language/phrases/mini.htm] [https://www.languagesandnumbers.com/how-to-count-in-mini/en/mini/]
: {{del}} and move to [[User:Mithridates/SJ]] the rest of the translations, i.e. Audià/Audian, Cristianés, Ekumenski, Germanisch, Interocidental, Lingaust, Lingue Simple, Masa Tang, Mirad, Monav, Monkel, Mundeze, Nordien, Novlingue, Numo, Proyo, and Scuian/Meteza. If you can find reliable sources for those languages, please let me know.
: In particular, I could not find resources for Audià/Audian and Monav after searching through 15 and 17 pages on Google, respectively. It doesn't help that [[Òla, Ionatà!|their]] [[Hai, Jon!|translations]] don't explain what those languages are and where to find resources for them. This makes contributing to those translations almost impossible until @[[User:Caro de Segeda|Caro de Segeda]] can provide resources to us. It's possible that the resources may have disappared from the Internet, or that those languages were created by Caro de Segeda him/herself. If you can find resources for Audià/Audian and Monav, please let me know.
: I'm notifying the primary contributors of the translations: @[[User:Caro de Segeda|Caro de Segeda]], @[[User:Frzzl|Frzzl]], @[[User:Greatscotteh|Greatscotteh]], @[[User:IHateNumbers234|IHateNumbers234]], @[[User:Jayeless2|Jayeless2]], @[[User:Morozof|Morozof]], @[[User:Omnihom|Omnihom]], @[[User:Omoutuazn|Omoutuazn]], @[[User:PovriNaivon|PovriNaivon]], @[[User:Sir Beluga|Sir Beluga]] and @[[User:Tyoyafud|Tyoyafud]]. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 09:52, 30 June 2025 (UTC)
:: Caro de Segeda said on [https://www.reddit.com/r/conlangs/comments/1lcnz9g/comment/n0sc3wx/ Reddit] that Monav was created by him/her and that he/she didn't publish any resources about it other than [[Hai, Jon!]]. With '''zero''' other resources to rely on for contributing to the translation, and the fact that Monav is in [[User:Mithridates/SJ]], [[Hai, Jon!]] should be speedy deleted. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 01:38, 3 July 2025 (UTC)
::: I've undone the speedy deletion as Caro de Segeda posted a [https://prexins.wordpress.com/2025/07/04/monav/ resource] for Monav. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 07:18, 4 July 2025 (UTC)
:::: You can delete all the ones that I have created myself, I have already moved them to other places. — [[User:Caro de Segeda|Caro de Segeda]] ([[User talk:Caro de Segeda|discuss]] • [[Special:Contributions/Caro de Segeda|contribs]]) 12:39, 5 July 2025 (UTC)
{{outdent|::::}}I don't know if this is helpful since it wouldn't apply to most of these, but [[s:mul:]] could hold some of these. — [[User:Arlo Barnes|Arlo Barnes]] ([[User talk:Arlo Barnes|discuss]] • [[Special:Contributions/Arlo Barnes|contribs]]) 09:18, 30 November 2025 (UTC)
: I don't think that would be within the scope of that project. I'm not aware of any other situation where Wikisource publishes translations of texts created on Wikimedia projects - that's usually left up to other language editions of the same project. — [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 05:34, 1 December 2025 (UTC)
:: In this situation there isn't a separate [[s:ie:]] distinct from Multilingual Wikisource (see [[meta:Wikisource#List of Wikisources]]). In fact, there are very few multilingual wikis in the Wikimedia sphere; while this project ''could'' move to a Miraheze-hosted or similar wiki farm location, I think it would be a missed opportunity. I suppose an [[Interlingue]] book could be started in [[shelf:Constructed languages]] which would have all 100 chapters as an appendix (and likewise for the other languages), but that also seems non-ideal since it requires an English-language text that doesn't currently exist to be created. [[WB:AT]] seems to describe a similar situation to this one and prescribe Wikisource as the solution, and [[WB:SOURCE]] mentions fiction as out-of-scope for Wikibooks (even as in this case, language-educational fiction). [[s:mul:Wikisource:about Wikisource]] simply speaks of source texts and doesn't mention publication requirements, so maybe that is specific to some of the monolingual editions? — [[User:Arlo Barnes|Arlo Barnes]] ([[User talk:Arlo Barnes|discuss]] • [[Special:Contributions/Arlo Barnes|contribs]]) 22:28, 5 December 2025 (UTC)
:{{keep}} 100% keep. These books are a core part of language textbooks on Wikibooks and have been for years. Not sure why this is even being debated.--[[User:Xania|Xania]] [[Image:Flag_of_Estonia.svg|15px]] [[Image:Flag_of_Ukraine.svg|15px]] [[User talk:Xania|<sup>talk</sup>]] 17:55, 16 May 2026 (UTC)
::With all due respect, some of the books included in this nomination (like [[Sin Chao, Jonathan!]]) are written in constructed languages which are not substantially attested anywhere else. I struggle to imagine any educational purpose for such a book. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:12, 17 May 2026 (UTC)
== [[International Baccalaureate]] ==
Not actually a book in and of itself; rather, it is just a compilation of links to other books —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:24, 18 October 2024 (UTC)
: Could this be salvaged as a shelf? [[User:Pppery|Pppery]] ([[User talk:Pppery|discuss]] • [[Special:Contributions/Pppery|contribs]]) 05:23, 27 January 2025 (UTC)
::Probably, but are the linked books even useful? IB exams change from year to year - sometimes quite dramatically - so an old exam guide is of very limited value. Many of these books were written 10-15 years ago, and some of them (like [[IB French]]) even have comments indicating that they're no longer applicable. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 02:18, 8 December 2025 (UTC)
:I would be interested in a book that explains what an [[International Baccalaureate]] is. They may be books about it in the real world, but they are not free and with the online world becoming a fortress of paywalls I wonder how much longer one would be able to find such information on the web. This is what the wikipedia article says:
:* This article '''is missing information''' about the educational programs and curricula. Please expand the article to include this information. Further details may exist on the [[wikipedia:Talk:International_Baccalaureate#|talk page]]. ''(March 2025)''
:[[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 02:05, 13 October 2026 (UTC)
== [[Character List for Baxter&Sagart]] ==
Seems completely out of scope as an educational book; it's just a list of characters and outlinks —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:53, 18 October 2024 (UTC)
:Adding [[Character List for Karlgren's GSR]] and [[Character List for Schuessler's CGSR]] for the same reason —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:55, 18 October 2024 (UTC)
:These three books do make a package and I agree they should be considered together. However, I strongly object to deleting them. They are really extremely useful resources. I use them every week and I know that many people who do work on Old Chinese phonology do so. There are lots of books out there that are lists of characters, these are called dictionaries. For example Axel Schuessler's ABC Etymological Dictionary of Old Chinese, or Pulleyblank's Lexicon of Reconstructed Pronunciation in Early Middle Chinese, Late Middle Chinese, and Early Mandarin. I see it as entirely a good thing for reference works of this kind to be available free online rather than only in expensive books in university research libraries. If this is in violation of a Wikibooks policy, I would at least like that policy to be drawn to my attention and to have some constructive comment offered about which Wikiproject such a resource should fall under. I will also say on a personal note that I have put literally hundreds of hours of work into these projects and it would grieve me a lot to see this work simply vanish, in particular when I know that colleagues around the world use these books. --[[User:Tibetologist|Tibetologist]] ([[User talk:Tibetologist|discuss]] • [[Special:Contributions/Tibetologist|contribs]]) 07:27, 1 November 2024 (UTC)
::Hi @[[User:Tibetologist|Tibetologist]], and thank you for the feedback! Official Wikibooks policy does not permit standalone dictionaries (see [[WB:DICT]]), though I understand the argument that it is a useful resource. I am wondering if there might be a home for it at [[Wiktionary:Wiktionary:Welcome, newcomers|Wiktionary]] or [[Wikiversity:Wikiversity:SHARE|Wikiversity]]? Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 12:14, 1 November 2024 (UTC)
:::The policy says to use Wiktionary, but these books cannot be moved there. In fact they link there, you can understand me as having made an index to wiktionary, if you like, where the ORDER of the characters is extremely important, information that would be lost in Wiktionary.
:::Wikiversity is not a project I participate in, and in any event my books here are older than it, so this option was not available for me at the relevant moment. If you are offering to move my books to Wikiversity, that is very kind of you and I will very graciously accept. [[User:Tibetologist|Tibetologist]] ([[User talk:Tibetologist|discuss]] • [[Special:Contributions/Tibetologist|contribs]]) 14:10, 1 November 2024 (UTC)
::::I have pinged over at Wikiversity Colloquium to ask about suitability and have looped you into the conversation over there. Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 18:20, 1 November 2024 (UTC)
::I concur. I'm just an undergrad who tries to learn about Sino-Tibetan historical linguistics in his free time but I've found this wikibook to be incredibly useful, and I keep it open in one tab while I watch Professor Nathan Hill's lectures that he uploads to youtube in another tab, and another tab for taking notes. In fact if I remember correctly Professor Hill actually pointed his students to this wikibook.
::I'm not familiar with [[wikiversity:Wikiversity:SHARE|Wikiversity]] but if all the content were as accessible there as it is here then I think that could work. [[User:ChromeBones|ChromeBones]] ([[User talk:ChromeBones|discuss]] • [[Special:Contributions/ChromeBones|contribs]]) 02:43, 9 July 2025 (UTC)
:Per [[:v:Wikiversity:Colloquium#Import_Resource_From_Wikibooks?]], I recommend copying and pasting, including attribution via the edit summary and talk page, add appropriate categories and links, and then it could be deleted locally. —[[User:Koavf|Justin (<span style="color:grey">ko'''a'''vf</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 22:32, 3 November 2024 (UTC)
== [[Suomen kieli käyttöön]] ==
Multiple pages in this book are written entirely in Finnish, which is out of the enWB scope. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 00:09, 19 October 2024 (UTC)
:I was going to say whether we should ask any fiwikibooks sysop to maybe see if this could be transwikied to fiwb if it's within the scope there. But [[:fi:Toiminnot:Käyttäjät/sysop]] indicates that there are only 3 sysops, and only {{u|Anr}} and {{u|Zache}} have made edits this ''year''. If they deem it to be salvageable, then transwiki + delete, otherwise straight-up delete. --[[User:SHB2000|SHB2000]] ([[User talk:SHB2000|discuss]] • [[Special:Contributions/SHB2000|contribs]]) 11:24, 14 November 2024 (UTC)
::It seems that the idea behind the book was for the pages to be bilingual, as it’s a language learning book. That’s why there are Finnish texts included intentionally even on the pages that are complete. There are similar books in dewikibooks and ruwikibooks as well. For the English version, I think the easiest way to proceed would be to clean up and adjust the page layout to fit enwikibooks better, and then translate the missing parts. By the way, if anyone wants to update the book’s name in English, it can be titled ''"Using the Finnish Language"'' or ''"Put Finnish Language into Use"'' for a direct translation. [[User:Zache|Zache]] ([[User talk:Zache|discuss]] • [[Special:Contributions/Zache|contribs]]) 11:57, 14 November 2024 (UTC)
== [[AT&T Mobility FAQ]] ==
* [[AT&T Mobility FAQ]]
* [[AT&T Mobility FAQ/MEdia Net Configuration]]
* [[AT&T Mobility FAQ/Data Connect Configuration]]
An ''extremely'' outdated FAQ on AT&T's cell phone services. Most of this document was written 20+ years ago as a Usenet FAQ; very little of it is accurate or useful anymore (particularly the two subpages, which have to do with obsolete configurations for "tethering" a computer to a cell phone). No objection if someone wants to update it, but there's clearly been no appetite to do that. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 22:20, 30 December 2024 (UTC)
:I'm wondering if it might make sense for us to develop some kind of policy on archiving books here. There are many like this one that have a good deal of content but are extremely out of date and just not useful as originally intended. ——[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 22:34, 30 December 2024 (UTC)
::@[[User:Kittycataclysm|Kittycataclysm]]: See the newly developed [[Wikibooks:Outdated books]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 00:16, 31 December 2024 (UTC)
:::Ooh, thanks - something like that seems like it could be an appropriate way to handle this book. A lot of the other outdated books I've tagged have been so incomplete that they wouldn't have been particularly useful even as historical references; this one might at least have some interest.
:::Any chance we can get a separate namespace (maybe "Archive:") set up for archived book content? That'd make it possible to do things like exclude them from on-site search by default. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:07, 31 December 2024 (UTC)
::::I think this might be a more extended discussion, so I'll bump it over to the [[Wikibooks talk:Outdated books|talk page of the draft policy]]! —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 21:54, 31 December 2024 (UTC)
== Algebra/Chapter 10/Symmetric Polynomials ==
I personally believe that [[Algebra/Chapter 10/Symmetric Polynomials|this]], and all of the sections should be deleted for the fact that this goes WAY beyond the scope of what was intended for the Chapter (Algebra II level polynomials). [[User:GoreyCat|GoreyCat]] ([[User talk:GoreyCat|discuss]] • [[Special:Contributions/GoreyCat|contribs]]) 15:07, 6 February 2025 (UTC)
:'''Split''': Deletion here is not the best solution (see [[w:WP:ATD]]). Instead, this page and its subpages should be moved to another book, most likely [[Abstract Algebra]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 17:35, 6 February 2025 (UTC)
:{{keep}} since there is a good amount of content. If [[Abstract Algebra]] is appropriate, it seems like a fine idea to move there. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 22:59, 7 February 2025 (UTC)
::Eh, yeah, I supposed moving it is better. I just don't think it's suitable for where it appears. [[User:GoreyCat|GoreyCat]] ([[User talk:GoreyCat|discuss]] • [[Special:Contributions/GoreyCat|contribs]]) 01:40, 8 February 2025 (UTC)
== [[Puredyne]] ==
Development of Puredyne Linux was discontinued in 2012, and the software no longer appears to be available for download anywhere. (An archive of the web site is still up - with a bunch of embedded spam links - but the download links are all dead.) Is this a suitable candidate for archival (cf. [[Wikibooks:Outdated books]]), or should it just be deleted? [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 04:35, 5 March 2025 (UTC)
:I'd just archive stuff like this. Looks like a decent bit of work went into it, and you never know when someone might need to use Puredyne for some obscure project. I'd be willing to bet mirrors exist of it somewhere, or someone has it on a drive. If you want to find some stuff worth deleting, comb through [[:Category:Allbooks categories]]. [[User:MediaKyle|MediaKyle]] ([[User talk:MediaKyle|discuss]] • [[Special:Contributions/MediaKyle|contribs]]) 11:30, 5 March 2025 (UTC)
== [[Template:Qr-twwp]] ==
This isn't exactly a request to delete the template, but rather to merge it with {{tlx|Copypaste}}. The {{tlx|Qr-twwp}} template serves the same purpose as {{tlx|Copypaste}}, but without the seven-day period after which the page is deleted. This leads to confusion, as well as a perpetually full [[:Category:Queried pages]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 17:37, 30 March 2025 (UTC)
== [[Ghouls of the Miskatonic]] ==
I don't think that a plot summary of a book is in-scope here. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 18:43, 20 August 2025 (UTC)
:{{vd}} - at least, not a summary of ''this'' book. A summary and/or study guide to a notable work of literature might be in scope, but this is certainly not one. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:23, 25 August 2025 (UTC)
::Hi. I am the creator of the pages of this book. If I understand correctly, it has to be a summary of a notable work of literature? So what exactly is defined as such? I only started this as I thought it would be fun, interesting and encouraging to others who read the Arkham Horror novels, and I thought it was permitted as I've seen other summaries of books on wikibooks. [[User:Dayne90|Dayne90]] ([[User talk:Dayne90|discuss]] • [[Special:Contributions/Dayne90|contribs]]) 13:27, 26 August 2025 (UTC)
:::Your problem is it is just the plot... it needs to include an educational textual analysis to be in scope [[User:MarcGarver|MarcGarver]] ([[User talk:MarcGarver|discuss]] • [[Special:Contributions/MarcGarver|contribs]]) 12:47, 28 August 2025 (UTC)
::::And ideally it'd be a text which has ''already'' been the subject of literary analysis, such that the analysis on Wikibooks isn't original research. A notable work of literature like ''Frankenstein'' or ''Moby-Dick'' would easily meet that requirement; a tie-in novel for a tabletop RPG probably does not. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 22:08, 29 August 2025 (UTC)
== [[A-level Computing AQA Paper 1 Skeleton program 2027]] ==
This was proposed for speedy deletion by [[User:Omphalographer]] as 'not being a book'. However, I think this page's future requires further discussion from the community. Maybe some input would be appreciated?[[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 23:51, 21 September 2026 (UTC)
:As best I can tell, this is a page students are using to collaborate on solutions for a standardized test. There are a number of similar pages for other years linked from [[A-level Computing/AQA/Paper 1/Skeleton program]].
:This is not a good fit for Wikibooks. If these students are interested in this kind of collaboration, it should take place elsewhere. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:14, 22 September 2026 (UTC)
::The project can be moved to Wikiversity, I think. If the students can contribute it and make sure it complies with Wikibooks' guidelines, it can stay here. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 00:17, 22 September 2026 (UTC)
:::@[[User:Omphalographer|Omphalographer]] @[[User:TechVindicator|TechVindicator]]
:::There's been a Wikibook on this every single year, as I mentioned in my comment on the deletion notice. That doesn't mean that this shouldn't be on Wikiversity, just that there is ample precedent of it being a Wikibook. Dunno if this matter to those kind of editorial decisions, though. [[Special:Contributions/~2026-51010-27|~2026-51010-27]] ([[User talk:~2026-51010-27|talk]]) 13:39, 22 September 2026 (UTC)
::::@[[User:~2026-51010-27|~2026-51010-27]]: How would the page comply with [[WB:What is Wikibooks?|Wikibooks' mission]]?. Could you provide an explanation of what the project is? If it's a collaborative project to work on solutions for a standardized test (like @[[User:Omphalographer|Omphalographer]] said), it would be more suitable for Wikiversity. If it's a textbook about A-level computing, then it would be suitable here. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 13:58, 22 September 2026 (UTC)
:::::Hi,
:::::This is definitely the former, not the latter. As I said, I don't particularly think this should be on Wikibooks, it just happens the previous years had been, and clearly they weren't subject to this degree of scrutiny 😅
:::::I have created https://en.wikiversity.org/wiki/A-level_Computer_Science_AQA_Paper_1_Skeleton_program_2027 - I'll delete the content of the page and put the link at the top. If there is a more appropriate banner to indicate the migration, please make it look how it should :D [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 10:23, 29 September 2026 (UTC)
::::::I can't seem to put a link without the edit being deemed destructive, so I'll let you trusted people do what's needed. [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 10:27, 29 September 2026 (UTC)
== [[Talmudic aramic]] ==
{{closed|Deleted per consensus below. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:18, 13 October 2026 (UTC)}}
Per the user's other mass-created pages, I concur with the AI flagging that Kittycataclysm placed on the page. I believe this to be LLM-generated, and it should thus be deleted. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 03:29, 30 September 2026 (UTC)
:{{vd}}, LLM spam. [[User:Ternera|Ternera]] ([[User talk:Ternera|discuss]] • [[Special:Contributions/Ternera|contribs]]) 13:22, 30 September 2026 (UTC)
:{{vd}} - like most LLM-generated books, this is heavy on structure and light on substance. Most of the content amounts to a poorly organized glossary, and there are a lot of pieces missing. (For instance, there is no discussion of the grammar of the language beyond a couple of fixed expressions.) [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:11, 1 October 2026 (UTC)
:{{vd}} per stated reasoning. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 14:43, 12 October 2026 (UTC)
{{end closed}}
== [[Job Search]] ==
{{closed|Per minimal consensus, I deleted these books, but I only kept the main pages of these books by creating them as redirects for [[Find Employment]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:24, 13 October 2026 (UTC)}}
* as well as [[Job Search Automation for College Students]].
Neither of these books contains any useful information. The first book seems to be written primarily to funnel users to the second, and the second to funnel users to [[PlanoTse Handbook for Job Search Automation]], which was deleted last year. (The deletion request doesn't seem to have been archived.)
The sum total of information in these two books is, essentially, "you can search for jobs online", which is insultingly trivial. The second book's suggestion that users automate the job search process is of no practical value; most web search engines and job search sites nowadays will detect and block automated access.
[[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:36, 1 October 2026 (UTC)
: {{vd}} and redirect to [[Find Employment]]. ‑‑[[User:Kai Burghardt|Kai Burghardt]] ([[User talk:Kai Burghardt|discuss]] • [[Special:Contributions/Kai Burghardt|contribs]]) 05:14, 2 October 2026 (UTC)
{{end closed}}
== [[Wikipage]] ==
Like a few other books created by this user, the purpose of this book appears to have been to promote a piece of software written by the author ([[User:Planotse]]). The software is no longer available, and there is no actual content in the book.
[[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:40, 1 October 2026 (UTC)
:{{Vd}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
== [[Becoming a Linguistic Mastermind]] ==
Old book (created 2007) with no substantial content. The intent of this book appears to have been to create a single textbook encompassing ''all'' languages, with sub-courses for each language at [[Becoming a Linguistic Mastermind/The courses]], but no such courses were ever created. An analogous project on dewikibooks [[:b:de:Wikibooks:Löschkandidaten/ 2011-04#Der einfache Weg zum Sprachgenie|was deleted in 2011 for similar reasons]]. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:20, 7 October 2026 (UTC)
:{{Vd}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
== [[The Permanent Advantage]] ==
Probably LLM-generated, given broken templates, references to Claude, and section identifiers. This could probably be speedied, but not 100% sure so throwing it to RfD. Even regardless of whether it's LLM-generated or not, I can't see any way it's really suitable for the project. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 07:49, 10 October 2026 (UTC)
:{{vd}} - a book ''about'' chess problems isn't necessarily out of scope, but there needs to be some written content to accompany the problems. And I'm not sure these are even meaningful problems - the few problems with viewable Lichess links appear to be in the early game, so there aren't necessarily objective "solutions" to them. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:51, 10 October 2026 (UTC)
:{{vd}}, the Claude references throughout the book support that it's LLM-generated. [[User:Ternera|Ternera]] ([[User talk:Ternera|discuss]] • [[Special:Contributions/Ternera|contribs]]) 14:55, 11 October 2026 (UTC)
== [[Digital Synthora]] ==
Not within WB scope since it seems to be entirely fabricated by the editor. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 14:20, 12 October 2026 (UTC)
:{{vd}} While some amount of original research is allowed here, completely fabricated topics aren't. This is just fiction writing, which is nice, but not within our scope. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
:{{vd}} - per my initial tag, this appears to be an invention of the page creator; I can't find anything relevant online beyond the empty https://synthoraactstuff.fandom.com/. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 01:32, 13 October 2026 (UTC)
2nkadfp0riwu9l2m3cbnbrck59047hb
4675851
4675850
2026-10-13T14:26:34Z
Codename Noreste
3441010
/* Wikipage */ Deleted. ([[:m:User:Max/MaxEdit.js|MaxEdit]])
4675851
wikitext
text/x-wiki
__NEWSECTIONLINK__
[[Category:Wikibooks deletion|{{PAGENAME}}]]
{{Discussion Rooms}}
{{TOCleft}}
{{shortcut|WB:RFD}}
{{Requests for deletion/New deletion}}
{{Requests for deletion/Deletion intro}}
<!-- New deletion nominations go at the bottom of page. -->
== [[Salute, Jonathan!]] and its translations ==
<div style="column-count: 7;">
* [[Salute, Jonathan!|Interlingue/Occidental]] ([[w:en:Occidental|w]], original)
* [[Òla, Ionatà!|Audià]]
* [[Holo, Jonathan!|Cristianés]]
* [[Terve, Jonathan!|Ekumenski]]
* [[Hej, Jonathan! (Germanisch)|Germanisch]]
* [[Salom, Jonatan!|Globasa]]
* [[Àlŏ, Jonathan!|Guosa]] ([[w:en:Guosa|w]])
* [[Salut, Jonathan!|Idiom Neutral]] ([[w:en:Idiom Neutral|w]])
* [[Saluto, Jonathan! (Ido)|Ido]] ([[w:en:Ido|w]])
* [[Hallo, Jonathan!|Interlingua]] ([[w:en:Interlingua|w]])
* [[Salut, Jonathan! (Interocidental)|Interocidental]]
* [[Bune Ğonatan!|Lingaust]]
* [[Oila, Jonatan!|Lingue Simple]]
* [[Haloo, Jonatan!|Lingwa de Planeta]] ([[w:en:Lingwa de Planeta|w]])
* [[Sin Chao, Jonathan!|Masa Tang]]
* [[Salut, ionatano!|Meteza]]
* [[Salu, Jon!|Mini]]
* [[Hay, Jonathan!|Mirad]]
* [[Hai, Jon!|Monav]]
* [[Sesan Jon!|Monkel]]
* [[Salam, Jonathan!|Mundeze]]
* [[Dag, Jonathan!|Negerhollands]] ([[w:en:Negerhollands|w]])
* [[Salut Jonathan!|Neo]] ([[w:en:Neo|w]])
* [[Hej, Jonathan!|Nordien]]
* [[Saluto, Jonathan!|Novial]] ([[w:en:Novial|w]])
* [[Salute, Jonathan! (Novlingue)|Novlingue]]
* [[Alo, Jonathan!|Numo]]
* [[Hela, Jonathan!|Proyo]]
* [[Salute, Jonathan! (Romanica)|Romanica]] ([[w:en:Romanica|w]])
* [[Simi, Jonathan!|Solresol]] ([[w:en:Solresol|w]])
* [[Toki a, jan Jonatan!|Toki Pona]] ([[w:en:Toki Pona|w]])
* [[Glidis, o Jonathan!|Volapük]] ([[w:en:Volapük|w]])
</div>
There are a couple of issues here:
# Beyond their introductions, all of these books are written in languages which are not English, making them out of scope for the English Wikibooks.
# All but one of these books are in fact written in constructed languages, most of them in recently created conlangs. In some cases (e.g. [[Sin Chao, Jonathan!]]), I can't find any reliable sources describing the target language outside of the translation itself.
# Most of the translations (i.e. other than [[Salute, Jonathan!]] itself) were abandoned within the first five or so chapters (out of 100); none of them are complete, and there seems to be little effort to complete any of them.
While I recognize that this is an unusual project, and potentially one which could have some value, it's not at all clear to me that the English Wikibooks is the right place for it. — [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:24, 29 September 2024 (UTC)
: I'm really not sure what to do about these ones. While I recognize that this approach is certainly one method of teaching a language, I'm not sure that it constitutes an educational textbook. We do require that the English Wikibooks be written in English—for language-learning books, this typically means that the instructional parts are in English while the exercises are in the language being taught. I do think that if the language doesn't have much supporting evidence outside the book itself, it can safely be deleted. — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 01:01, 29 September 2024 (UTC)
: Author of the book here. I originally wanted to put it in the Interlingue Wikibooks https://ie.wikibooks.org/wiki/Principal_p%C3%A1gine but it somehow got locked when I wasn't paying attention and so I ended up putting it here. Getting it unlocked requires going through the process of starting an Incubator and all the rest so I opted for here and then started putting some English-only content once it was done. It's sort of in the same vein as books like Lingua Latina per se Illustrata that have separate versions with teacher notes and whatnot. [[Salute, Jonathan!/Capitul 1 - with notes]] After it was done the auxlang community really took to it which was a nice surprise. I think Ido has the largest number of chapters at the moment at 15.
:If the vast content of this book could be used to justify a quick reopening of the Interlingue Wikibooks to move it there, I'd love to do that. I imagine that an incubator with 100+ book chapters would be enough to open a Wikibooks and that's what this is. — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 06:02, 29 September 2024 (UTC)
: Ah, I just realized that we do have a proposal to reopen the Interlingue Wikibooks: https://meta.wikimedia.org/wiki/Requests_for_new_languages/Wikibooks_Interlingue along with an Incubator page here. https://incubator.wikimedia.org/wiki/Wb/ie/Principal_p%C3%A1gine
: How easy would it be to migrate the entirety of Salute Jonathan to there? — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 06:30, 29 September 2024 (UTC)
:: Hi @[[User:Mithridates|Mithridates]]! I'm not sure how incubator projects work, but I fully support migrating these books there. You may want to inquire over there and link to this discussion to support your request to move the content over there. Cheers! — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 13:16, 29 September 2024 (UTC)
::: Hi! Actually I have a third idea to propose after thinking about this again today (haven't been here much since I finished the book): I noticed that there is more English content than I remember and that might make it an awkward fit for the Interlingue Wikibooks. I definitely agree that having all the auxlang translations for new auxlang projects goes well beyond the scope of this Wikibooks. Finally, there are some auxlangs that are notable with their own Wikipedias.
::: So the idea is the following:
:::# Leave the original here and I can continue the work on the version with English notes and grammar. That will make it the same as Lingua Latina per se Illustrata, English by the Nature Method, Athenaze and all the rest.
:::# The Interlingua one can move to the Interlingua Wikibooks (maybe Romanica too if they want as it is sort of a dialect of Interlingua).
:::# For Ido and Lingua Franca Nova which have a Wikipedia but not a Wikibooks, I'm a little bit unsure...technically they could have their own version like the original one but would require English explanations. I could let them know and see if they are willing to do so and see what they think (work on adding English to the books vs. move the content elsewhere).
:::# The rest can move to a Github repo, then be deleted, and the front page of this book can have a single link to the repo.
::: Any thoughts on that? Adding the extra English content will be easy as it is my book and I know it inside and out.
::: Edit: [https://en.wikibooks.org/wiki/Salute,_Jonathan!/Grammar_(pronouns) this page] I just added. — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 13:50, 29 September 2024 (UTC)
:::: Thanks for taking the time to consider this! Here are my responses/questions:
::::* Is the original [[Salute, Jonathan!]] (Occidental)? Since that one is quite fleshed out, I agree that if you edit it so the primary language of the book (e.g. headers, instructions, etc) are written in English while leaving the actual story in Occidental, it would be okay and fit in more with instructional language textbooks.
::::* For your points 2 and 3, I'm not sure how those other projects work, so I'll leave it up to them. I'm not quite sure why they would need to move, since in theory they could be revised with English as the language of instruction? Although, they have been left incomplete for a long time.
::::* For your point 4, I have no problem with that. Cheers! — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 16:51, 29 September 2024 (UTC)
::::: Hello again, it's the weekend so I have a bit more time to work on this. I've decided to merge the extra content from the following five chapters since the difference is fairly small and the original chapters should now have this English content. Could you delete these five pages now that they are no longer needed? [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:02, 5 October 2024 (UTC)
::::: [[Salute, Jonathan!/Capitul 1 - with notes]]
::::: [[Salute, Jonathan!/Capitul 2 - with notes]]
::::: [[Salute, Jonathan!/Capitul 3 - with notes]]
::::: [[Salute, Jonathan!/Capitul 4 - with notes]]
::::: [[Salute, Jonathan!/Capitul 5 - with notes]] [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:02, 5 October 2024 (UTC)
:::::: [[File:Yes_check.svg|{{#ifeq:|small|8|15}}px|link=|alt=]] {{#ifeq:|small|<small>|}}'''Done'''{{#ifeq:|small|</small>|}} — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:34, 5 October 2024 (UTC)
::::::: Hi again! No luck trying to find a home for the random language translations on other auxlang wikis, can't find one that is actively maintained.
::::::: The thought struck me that maybe I could just put those ones on a sub page of my user page, would that be permitted? If not, I think I'll just stick them somewhere in GitHub and call it a day since none of the people who started the translations seem to care enough to do anything about them. I'd rather not see them outright disappear but since they aren't mine I don't care enough about them to do much more work than copy and paste them somewhere.
::::::: (I would leave the ones in languages with an ISO-639 code and Wikipedia here, of course) — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:13, 9 November 2024 (UTC)
:::::::: Thank you for checking! I don't personally see an issue with moving them to your user space right now. Cheers — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 17:21, 9 November 2024 (UTC)
::::::::: Thanks a lot! I've started a single page where I will put them all here [[User:Mithridates/SJ]] and will proceed slowly due to lack of time and also to avoid stepping on any toes / asking you to delete too much at a time and possibly deleting the wrong content.
::::::::: For this week I have put the content for the languages Audia, Cristianès, Guosa, Lingaust, Mini, Mirad, and Monav on that page as they all have a single page of content and didn't take much time to move. Please delete those. Once they are gone I will add a note on the main page letting people know where they have gone (in addition to a thank you for their interest in the book! I do love how many people have recognized it as a good source material for teaching a language). — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 04:09, 10 November 2024 (UTC)
: {{keep}} the translations for languages that have an article on the English Wikipedia, i.e. Guosa, Idiom Neutral, Ido, Interlingua, Lingwa de Planeta, Negerhollands, Neo, Novial, Occidental, Romanica, Solresol, Toki Pona, and Volapük.
: Translations for languages that don't have an article can be kept if they have reliable sources, which I was able to find for the following languages (if you think they are not reliable, please let me know):
:* Globasa: [https://www.languagesandnumbers.com/how-to-count-in-globasa/en/globasa/] [https://greyson.conlang.org/2020/01/29/shouting-out-globasa-and-pandunia/]
:* Mini: [https://jprogr.github.io/mini] [https://www.omniglot.com/language/phrases/mini.htm] [https://www.languagesandnumbers.com/how-to-count-in-mini/en/mini/]
: {{del}} and move to [[User:Mithridates/SJ]] the rest of the translations, i.e. Audià/Audian, Cristianés, Ekumenski, Germanisch, Interocidental, Lingaust, Lingue Simple, Masa Tang, Mirad, Monav, Monkel, Mundeze, Nordien, Novlingue, Numo, Proyo, and Scuian/Meteza. If you can find reliable sources for those languages, please let me know.
: In particular, I could not find resources for Audià/Audian and Monav after searching through 15 and 17 pages on Google, respectively. It doesn't help that [[Òla, Ionatà!|their]] [[Hai, Jon!|translations]] don't explain what those languages are and where to find resources for them. This makes contributing to those translations almost impossible until @[[User:Caro de Segeda|Caro de Segeda]] can provide resources to us. It's possible that the resources may have disappared from the Internet, or that those languages were created by Caro de Segeda him/herself. If you can find resources for Audià/Audian and Monav, please let me know.
: I'm notifying the primary contributors of the translations: @[[User:Caro de Segeda|Caro de Segeda]], @[[User:Frzzl|Frzzl]], @[[User:Greatscotteh|Greatscotteh]], @[[User:IHateNumbers234|IHateNumbers234]], @[[User:Jayeless2|Jayeless2]], @[[User:Morozof|Morozof]], @[[User:Omnihom|Omnihom]], @[[User:Omoutuazn|Omoutuazn]], @[[User:PovriNaivon|PovriNaivon]], @[[User:Sir Beluga|Sir Beluga]] and @[[User:Tyoyafud|Tyoyafud]]. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 09:52, 30 June 2025 (UTC)
:: Caro de Segeda said on [https://www.reddit.com/r/conlangs/comments/1lcnz9g/comment/n0sc3wx/ Reddit] that Monav was created by him/her and that he/she didn't publish any resources about it other than [[Hai, Jon!]]. With '''zero''' other resources to rely on for contributing to the translation, and the fact that Monav is in [[User:Mithridates/SJ]], [[Hai, Jon!]] should be speedy deleted. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 01:38, 3 July 2025 (UTC)
::: I've undone the speedy deletion as Caro de Segeda posted a [https://prexins.wordpress.com/2025/07/04/monav/ resource] for Monav. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 07:18, 4 July 2025 (UTC)
:::: You can delete all the ones that I have created myself, I have already moved them to other places. — [[User:Caro de Segeda|Caro de Segeda]] ([[User talk:Caro de Segeda|discuss]] • [[Special:Contributions/Caro de Segeda|contribs]]) 12:39, 5 July 2025 (UTC)
{{outdent|::::}}I don't know if this is helpful since it wouldn't apply to most of these, but [[s:mul:]] could hold some of these. — [[User:Arlo Barnes|Arlo Barnes]] ([[User talk:Arlo Barnes|discuss]] • [[Special:Contributions/Arlo Barnes|contribs]]) 09:18, 30 November 2025 (UTC)
: I don't think that would be within the scope of that project. I'm not aware of any other situation where Wikisource publishes translations of texts created on Wikimedia projects - that's usually left up to other language editions of the same project. — [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 05:34, 1 December 2025 (UTC)
:: In this situation there isn't a separate [[s:ie:]] distinct from Multilingual Wikisource (see [[meta:Wikisource#List of Wikisources]]). In fact, there are very few multilingual wikis in the Wikimedia sphere; while this project ''could'' move to a Miraheze-hosted or similar wiki farm location, I think it would be a missed opportunity. I suppose an [[Interlingue]] book could be started in [[shelf:Constructed languages]] which would have all 100 chapters as an appendix (and likewise for the other languages), but that also seems non-ideal since it requires an English-language text that doesn't currently exist to be created. [[WB:AT]] seems to describe a similar situation to this one and prescribe Wikisource as the solution, and [[WB:SOURCE]] mentions fiction as out-of-scope for Wikibooks (even as in this case, language-educational fiction). [[s:mul:Wikisource:about Wikisource]] simply speaks of source texts and doesn't mention publication requirements, so maybe that is specific to some of the monolingual editions? — [[User:Arlo Barnes|Arlo Barnes]] ([[User talk:Arlo Barnes|discuss]] • [[Special:Contributions/Arlo Barnes|contribs]]) 22:28, 5 December 2025 (UTC)
:{{keep}} 100% keep. These books are a core part of language textbooks on Wikibooks and have been for years. Not sure why this is even being debated.--[[User:Xania|Xania]] [[Image:Flag_of_Estonia.svg|15px]] [[Image:Flag_of_Ukraine.svg|15px]] [[User talk:Xania|<sup>talk</sup>]] 17:55, 16 May 2026 (UTC)
::With all due respect, some of the books included in this nomination (like [[Sin Chao, Jonathan!]]) are written in constructed languages which are not substantially attested anywhere else. I struggle to imagine any educational purpose for such a book. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:12, 17 May 2026 (UTC)
== [[International Baccalaureate]] ==
Not actually a book in and of itself; rather, it is just a compilation of links to other books —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:24, 18 October 2024 (UTC)
: Could this be salvaged as a shelf? [[User:Pppery|Pppery]] ([[User talk:Pppery|discuss]] • [[Special:Contributions/Pppery|contribs]]) 05:23, 27 January 2025 (UTC)
::Probably, but are the linked books even useful? IB exams change from year to year - sometimes quite dramatically - so an old exam guide is of very limited value. Many of these books were written 10-15 years ago, and some of them (like [[IB French]]) even have comments indicating that they're no longer applicable. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 02:18, 8 December 2025 (UTC)
:I would be interested in a book that explains what an [[International Baccalaureate]] is. They may be books about it in the real world, but they are not free and with the online world becoming a fortress of paywalls I wonder how much longer one would be able to find such information on the web. This is what the wikipedia article says:
:* This article '''is missing information''' about the educational programs and curricula. Please expand the article to include this information. Further details may exist on the [[wikipedia:Talk:International_Baccalaureate#|talk page]]. ''(March 2025)''
:[[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 02:05, 13 October 2026 (UTC)
== [[Character List for Baxter&Sagart]] ==
Seems completely out of scope as an educational book; it's just a list of characters and outlinks —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:53, 18 October 2024 (UTC)
:Adding [[Character List for Karlgren's GSR]] and [[Character List for Schuessler's CGSR]] for the same reason —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:55, 18 October 2024 (UTC)
:These three books do make a package and I agree they should be considered together. However, I strongly object to deleting them. They are really extremely useful resources. I use them every week and I know that many people who do work on Old Chinese phonology do so. There are lots of books out there that are lists of characters, these are called dictionaries. For example Axel Schuessler's ABC Etymological Dictionary of Old Chinese, or Pulleyblank's Lexicon of Reconstructed Pronunciation in Early Middle Chinese, Late Middle Chinese, and Early Mandarin. I see it as entirely a good thing for reference works of this kind to be available free online rather than only in expensive books in university research libraries. If this is in violation of a Wikibooks policy, I would at least like that policy to be drawn to my attention and to have some constructive comment offered about which Wikiproject such a resource should fall under. I will also say on a personal note that I have put literally hundreds of hours of work into these projects and it would grieve me a lot to see this work simply vanish, in particular when I know that colleagues around the world use these books. --[[User:Tibetologist|Tibetologist]] ([[User talk:Tibetologist|discuss]] • [[Special:Contributions/Tibetologist|contribs]]) 07:27, 1 November 2024 (UTC)
::Hi @[[User:Tibetologist|Tibetologist]], and thank you for the feedback! Official Wikibooks policy does not permit standalone dictionaries (see [[WB:DICT]]), though I understand the argument that it is a useful resource. I am wondering if there might be a home for it at [[Wiktionary:Wiktionary:Welcome, newcomers|Wiktionary]] or [[Wikiversity:Wikiversity:SHARE|Wikiversity]]? Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 12:14, 1 November 2024 (UTC)
:::The policy says to use Wiktionary, but these books cannot be moved there. In fact they link there, you can understand me as having made an index to wiktionary, if you like, where the ORDER of the characters is extremely important, information that would be lost in Wiktionary.
:::Wikiversity is not a project I participate in, and in any event my books here are older than it, so this option was not available for me at the relevant moment. If you are offering to move my books to Wikiversity, that is very kind of you and I will very graciously accept. [[User:Tibetologist|Tibetologist]] ([[User talk:Tibetologist|discuss]] • [[Special:Contributions/Tibetologist|contribs]]) 14:10, 1 November 2024 (UTC)
::::I have pinged over at Wikiversity Colloquium to ask about suitability and have looped you into the conversation over there. Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 18:20, 1 November 2024 (UTC)
::I concur. I'm just an undergrad who tries to learn about Sino-Tibetan historical linguistics in his free time but I've found this wikibook to be incredibly useful, and I keep it open in one tab while I watch Professor Nathan Hill's lectures that he uploads to youtube in another tab, and another tab for taking notes. In fact if I remember correctly Professor Hill actually pointed his students to this wikibook.
::I'm not familiar with [[wikiversity:Wikiversity:SHARE|Wikiversity]] but if all the content were as accessible there as it is here then I think that could work. [[User:ChromeBones|ChromeBones]] ([[User talk:ChromeBones|discuss]] • [[Special:Contributions/ChromeBones|contribs]]) 02:43, 9 July 2025 (UTC)
:Per [[:v:Wikiversity:Colloquium#Import_Resource_From_Wikibooks?]], I recommend copying and pasting, including attribution via the edit summary and talk page, add appropriate categories and links, and then it could be deleted locally. —[[User:Koavf|Justin (<span style="color:grey">ko'''a'''vf</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 22:32, 3 November 2024 (UTC)
== [[Suomen kieli käyttöön]] ==
Multiple pages in this book are written entirely in Finnish, which is out of the enWB scope. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 00:09, 19 October 2024 (UTC)
:I was going to say whether we should ask any fiwikibooks sysop to maybe see if this could be transwikied to fiwb if it's within the scope there. But [[:fi:Toiminnot:Käyttäjät/sysop]] indicates that there are only 3 sysops, and only {{u|Anr}} and {{u|Zache}} have made edits this ''year''. If they deem it to be salvageable, then transwiki + delete, otherwise straight-up delete. --[[User:SHB2000|SHB2000]] ([[User talk:SHB2000|discuss]] • [[Special:Contributions/SHB2000|contribs]]) 11:24, 14 November 2024 (UTC)
::It seems that the idea behind the book was for the pages to be bilingual, as it’s a language learning book. That’s why there are Finnish texts included intentionally even on the pages that are complete. There are similar books in dewikibooks and ruwikibooks as well. For the English version, I think the easiest way to proceed would be to clean up and adjust the page layout to fit enwikibooks better, and then translate the missing parts. By the way, if anyone wants to update the book’s name in English, it can be titled ''"Using the Finnish Language"'' or ''"Put Finnish Language into Use"'' for a direct translation. [[User:Zache|Zache]] ([[User talk:Zache|discuss]] • [[Special:Contributions/Zache|contribs]]) 11:57, 14 November 2024 (UTC)
== [[AT&T Mobility FAQ]] ==
* [[AT&T Mobility FAQ]]
* [[AT&T Mobility FAQ/MEdia Net Configuration]]
* [[AT&T Mobility FAQ/Data Connect Configuration]]
An ''extremely'' outdated FAQ on AT&T's cell phone services. Most of this document was written 20+ years ago as a Usenet FAQ; very little of it is accurate or useful anymore (particularly the two subpages, which have to do with obsolete configurations for "tethering" a computer to a cell phone). No objection if someone wants to update it, but there's clearly been no appetite to do that. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 22:20, 30 December 2024 (UTC)
:I'm wondering if it might make sense for us to develop some kind of policy on archiving books here. There are many like this one that have a good deal of content but are extremely out of date and just not useful as originally intended. ——[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 22:34, 30 December 2024 (UTC)
::@[[User:Kittycataclysm|Kittycataclysm]]: See the newly developed [[Wikibooks:Outdated books]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 00:16, 31 December 2024 (UTC)
:::Ooh, thanks - something like that seems like it could be an appropriate way to handle this book. A lot of the other outdated books I've tagged have been so incomplete that they wouldn't have been particularly useful even as historical references; this one might at least have some interest.
:::Any chance we can get a separate namespace (maybe "Archive:") set up for archived book content? That'd make it possible to do things like exclude them from on-site search by default. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:07, 31 December 2024 (UTC)
::::I think this might be a more extended discussion, so I'll bump it over to the [[Wikibooks talk:Outdated books|talk page of the draft policy]]! —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 21:54, 31 December 2024 (UTC)
== Algebra/Chapter 10/Symmetric Polynomials ==
I personally believe that [[Algebra/Chapter 10/Symmetric Polynomials|this]], and all of the sections should be deleted for the fact that this goes WAY beyond the scope of what was intended for the Chapter (Algebra II level polynomials). [[User:GoreyCat|GoreyCat]] ([[User talk:GoreyCat|discuss]] • [[Special:Contributions/GoreyCat|contribs]]) 15:07, 6 February 2025 (UTC)
:'''Split''': Deletion here is not the best solution (see [[w:WP:ATD]]). Instead, this page and its subpages should be moved to another book, most likely [[Abstract Algebra]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 17:35, 6 February 2025 (UTC)
:{{keep}} since there is a good amount of content. If [[Abstract Algebra]] is appropriate, it seems like a fine idea to move there. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 22:59, 7 February 2025 (UTC)
::Eh, yeah, I supposed moving it is better. I just don't think it's suitable for where it appears. [[User:GoreyCat|GoreyCat]] ([[User talk:GoreyCat|discuss]] • [[Special:Contributions/GoreyCat|contribs]]) 01:40, 8 February 2025 (UTC)
== [[Puredyne]] ==
Development of Puredyne Linux was discontinued in 2012, and the software no longer appears to be available for download anywhere. (An archive of the web site is still up - with a bunch of embedded spam links - but the download links are all dead.) Is this a suitable candidate for archival (cf. [[Wikibooks:Outdated books]]), or should it just be deleted? [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 04:35, 5 March 2025 (UTC)
:I'd just archive stuff like this. Looks like a decent bit of work went into it, and you never know when someone might need to use Puredyne for some obscure project. I'd be willing to bet mirrors exist of it somewhere, or someone has it on a drive. If you want to find some stuff worth deleting, comb through [[:Category:Allbooks categories]]. [[User:MediaKyle|MediaKyle]] ([[User talk:MediaKyle|discuss]] • [[Special:Contributions/MediaKyle|contribs]]) 11:30, 5 March 2025 (UTC)
== [[Template:Qr-twwp]] ==
This isn't exactly a request to delete the template, but rather to merge it with {{tlx|Copypaste}}. The {{tlx|Qr-twwp}} template serves the same purpose as {{tlx|Copypaste}}, but without the seven-day period after which the page is deleted. This leads to confusion, as well as a perpetually full [[:Category:Queried pages]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 17:37, 30 March 2025 (UTC)
== [[Ghouls of the Miskatonic]] ==
I don't think that a plot summary of a book is in-scope here. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 18:43, 20 August 2025 (UTC)
:{{vd}} - at least, not a summary of ''this'' book. A summary and/or study guide to a notable work of literature might be in scope, but this is certainly not one. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:23, 25 August 2025 (UTC)
::Hi. I am the creator of the pages of this book. If I understand correctly, it has to be a summary of a notable work of literature? So what exactly is defined as such? I only started this as I thought it would be fun, interesting and encouraging to others who read the Arkham Horror novels, and I thought it was permitted as I've seen other summaries of books on wikibooks. [[User:Dayne90|Dayne90]] ([[User talk:Dayne90|discuss]] • [[Special:Contributions/Dayne90|contribs]]) 13:27, 26 August 2025 (UTC)
:::Your problem is it is just the plot... it needs to include an educational textual analysis to be in scope [[User:MarcGarver|MarcGarver]] ([[User talk:MarcGarver|discuss]] • [[Special:Contributions/MarcGarver|contribs]]) 12:47, 28 August 2025 (UTC)
::::And ideally it'd be a text which has ''already'' been the subject of literary analysis, such that the analysis on Wikibooks isn't original research. A notable work of literature like ''Frankenstein'' or ''Moby-Dick'' would easily meet that requirement; a tie-in novel for a tabletop RPG probably does not. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 22:08, 29 August 2025 (UTC)
== [[A-level Computing AQA Paper 1 Skeleton program 2027]] ==
This was proposed for speedy deletion by [[User:Omphalographer]] as 'not being a book'. However, I think this page's future requires further discussion from the community. Maybe some input would be appreciated?[[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 23:51, 21 September 2026 (UTC)
:As best I can tell, this is a page students are using to collaborate on solutions for a standardized test. There are a number of similar pages for other years linked from [[A-level Computing/AQA/Paper 1/Skeleton program]].
:This is not a good fit for Wikibooks. If these students are interested in this kind of collaboration, it should take place elsewhere. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:14, 22 September 2026 (UTC)
::The project can be moved to Wikiversity, I think. If the students can contribute it and make sure it complies with Wikibooks' guidelines, it can stay here. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 00:17, 22 September 2026 (UTC)
:::@[[User:Omphalographer|Omphalographer]] @[[User:TechVindicator|TechVindicator]]
:::There's been a Wikibook on this every single year, as I mentioned in my comment on the deletion notice. That doesn't mean that this shouldn't be on Wikiversity, just that there is ample precedent of it being a Wikibook. Dunno if this matter to those kind of editorial decisions, though. [[Special:Contributions/~2026-51010-27|~2026-51010-27]] ([[User talk:~2026-51010-27|talk]]) 13:39, 22 September 2026 (UTC)
::::@[[User:~2026-51010-27|~2026-51010-27]]: How would the page comply with [[WB:What is Wikibooks?|Wikibooks' mission]]?. Could you provide an explanation of what the project is? If it's a collaborative project to work on solutions for a standardized test (like @[[User:Omphalographer|Omphalographer]] said), it would be more suitable for Wikiversity. If it's a textbook about A-level computing, then it would be suitable here. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 13:58, 22 September 2026 (UTC)
:::::Hi,
:::::This is definitely the former, not the latter. As I said, I don't particularly think this should be on Wikibooks, it just happens the previous years had been, and clearly they weren't subject to this degree of scrutiny 😅
:::::I have created https://en.wikiversity.org/wiki/A-level_Computer_Science_AQA_Paper_1_Skeleton_program_2027 - I'll delete the content of the page and put the link at the top. If there is a more appropriate banner to indicate the migration, please make it look how it should :D [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 10:23, 29 September 2026 (UTC)
::::::I can't seem to put a link without the edit being deemed destructive, so I'll let you trusted people do what's needed. [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 10:27, 29 September 2026 (UTC)
== [[Talmudic aramic]] ==
{{closed|Deleted per consensus below. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:18, 13 October 2026 (UTC)}}
Per the user's other mass-created pages, I concur with the AI flagging that Kittycataclysm placed on the page. I believe this to be LLM-generated, and it should thus be deleted. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 03:29, 30 September 2026 (UTC)
:{{vd}}, LLM spam. [[User:Ternera|Ternera]] ([[User talk:Ternera|discuss]] • [[Special:Contributions/Ternera|contribs]]) 13:22, 30 September 2026 (UTC)
:{{vd}} - like most LLM-generated books, this is heavy on structure and light on substance. Most of the content amounts to a poorly organized glossary, and there are a lot of pieces missing. (For instance, there is no discussion of the grammar of the language beyond a couple of fixed expressions.) [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:11, 1 October 2026 (UTC)
:{{vd}} per stated reasoning. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 14:43, 12 October 2026 (UTC)
{{end closed}}
== [[Job Search]] ==
{{closed|Per minimal consensus, I deleted these books, but I only kept the main pages of these books by creating them as redirects for [[Find Employment]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:24, 13 October 2026 (UTC)}}
* as well as [[Job Search Automation for College Students]].
Neither of these books contains any useful information. The first book seems to be written primarily to funnel users to the second, and the second to funnel users to [[PlanoTse Handbook for Job Search Automation]], which was deleted last year. (The deletion request doesn't seem to have been archived.)
The sum total of information in these two books is, essentially, "you can search for jobs online", which is insultingly trivial. The second book's suggestion that users automate the job search process is of no practical value; most web search engines and job search sites nowadays will detect and block automated access.
[[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:36, 1 October 2026 (UTC)
: {{vd}} and redirect to [[Find Employment]]. ‑‑[[User:Kai Burghardt|Kai Burghardt]] ([[User talk:Kai Burghardt|discuss]] • [[Special:Contributions/Kai Burghardt|contribs]]) 05:14, 2 October 2026 (UTC)
{{end closed}}
== [[Wikipage]] ==
{{closed|Deleted per minimal consensus below. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:26, 13 October 2026 (UTC)}}
Like a few other books created by this user, the purpose of this book appears to have been to promote a piece of software written by the author ([[User:Planotse]]). The software is no longer available, and there is no actual content in the book.
[[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:40, 1 October 2026 (UTC)
:{{Vd}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
{{end closed}}
== [[Becoming a Linguistic Mastermind]] ==
Old book (created 2007) with no substantial content. The intent of this book appears to have been to create a single textbook encompassing ''all'' languages, with sub-courses for each language at [[Becoming a Linguistic Mastermind/The courses]], but no such courses were ever created. An analogous project on dewikibooks [[:b:de:Wikibooks:Löschkandidaten/ 2011-04#Der einfache Weg zum Sprachgenie|was deleted in 2011 for similar reasons]]. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:20, 7 October 2026 (UTC)
:{{Vd}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
== [[The Permanent Advantage]] ==
Probably LLM-generated, given broken templates, references to Claude, and section identifiers. This could probably be speedied, but not 100% sure so throwing it to RfD. Even regardless of whether it's LLM-generated or not, I can't see any way it's really suitable for the project. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 07:49, 10 October 2026 (UTC)
:{{vd}} - a book ''about'' chess problems isn't necessarily out of scope, but there needs to be some written content to accompany the problems. And I'm not sure these are even meaningful problems - the few problems with viewable Lichess links appear to be in the early game, so there aren't necessarily objective "solutions" to them. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:51, 10 October 2026 (UTC)
:{{vd}}, the Claude references throughout the book support that it's LLM-generated. [[User:Ternera|Ternera]] ([[User talk:Ternera|discuss]] • [[Special:Contributions/Ternera|contribs]]) 14:55, 11 October 2026 (UTC)
== [[Digital Synthora]] ==
Not within WB scope since it seems to be entirely fabricated by the editor. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 14:20, 12 October 2026 (UTC)
:{{vd}} While some amount of original research is allowed here, completely fabricated topics aren't. This is just fiction writing, which is nice, but not within our scope. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
:{{vd}} - per my initial tag, this appears to be an invention of the page creator; I can't find anything relevant online beyond the empty https://synthoraactstuff.fandom.com/. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 01:32, 13 October 2026 (UTC)
f4854hhj3derpnvfe46h82iyhag5x7x
4675853
4675851
2026-10-13T14:28:48Z
Codename Noreste
3441010
/* A-level Computing AQA Paper 1 Skeleton program 2027 */ reply ([[mw:c:Special:MyLanguage/User:JWBTH/CD|CD]])
4675853
wikitext
text/x-wiki
__NEWSECTIONLINK__
[[Category:Wikibooks deletion|{{PAGENAME}}]]
{{Discussion Rooms}}
{{TOCleft}}
{{shortcut|WB:RFD}}
{{Requests for deletion/New deletion}}
{{Requests for deletion/Deletion intro}}
<!-- New deletion nominations go at the bottom of page. -->
== [[Salute, Jonathan!]] and its translations ==
<div style="column-count: 7;">
* [[Salute, Jonathan!|Interlingue/Occidental]] ([[w:en:Occidental|w]], original)
* [[Òla, Ionatà!|Audià]]
* [[Holo, Jonathan!|Cristianés]]
* [[Terve, Jonathan!|Ekumenski]]
* [[Hej, Jonathan! (Germanisch)|Germanisch]]
* [[Salom, Jonatan!|Globasa]]
* [[Àlŏ, Jonathan!|Guosa]] ([[w:en:Guosa|w]])
* [[Salut, Jonathan!|Idiom Neutral]] ([[w:en:Idiom Neutral|w]])
* [[Saluto, Jonathan! (Ido)|Ido]] ([[w:en:Ido|w]])
* [[Hallo, Jonathan!|Interlingua]] ([[w:en:Interlingua|w]])
* [[Salut, Jonathan! (Interocidental)|Interocidental]]
* [[Bune Ğonatan!|Lingaust]]
* [[Oila, Jonatan!|Lingue Simple]]
* [[Haloo, Jonatan!|Lingwa de Planeta]] ([[w:en:Lingwa de Planeta|w]])
* [[Sin Chao, Jonathan!|Masa Tang]]
* [[Salut, ionatano!|Meteza]]
* [[Salu, Jon!|Mini]]
* [[Hay, Jonathan!|Mirad]]
* [[Hai, Jon!|Monav]]
* [[Sesan Jon!|Monkel]]
* [[Salam, Jonathan!|Mundeze]]
* [[Dag, Jonathan!|Negerhollands]] ([[w:en:Negerhollands|w]])
* [[Salut Jonathan!|Neo]] ([[w:en:Neo|w]])
* [[Hej, Jonathan!|Nordien]]
* [[Saluto, Jonathan!|Novial]] ([[w:en:Novial|w]])
* [[Salute, Jonathan! (Novlingue)|Novlingue]]
* [[Alo, Jonathan!|Numo]]
* [[Hela, Jonathan!|Proyo]]
* [[Salute, Jonathan! (Romanica)|Romanica]] ([[w:en:Romanica|w]])
* [[Simi, Jonathan!|Solresol]] ([[w:en:Solresol|w]])
* [[Toki a, jan Jonatan!|Toki Pona]] ([[w:en:Toki Pona|w]])
* [[Glidis, o Jonathan!|Volapük]] ([[w:en:Volapük|w]])
</div>
There are a couple of issues here:
# Beyond their introductions, all of these books are written in languages which are not English, making them out of scope for the English Wikibooks.
# All but one of these books are in fact written in constructed languages, most of them in recently created conlangs. In some cases (e.g. [[Sin Chao, Jonathan!]]), I can't find any reliable sources describing the target language outside of the translation itself.
# Most of the translations (i.e. other than [[Salute, Jonathan!]] itself) were abandoned within the first five or so chapters (out of 100); none of them are complete, and there seems to be little effort to complete any of them.
While I recognize that this is an unusual project, and potentially one which could have some value, it's not at all clear to me that the English Wikibooks is the right place for it. — [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:24, 29 September 2024 (UTC)
: I'm really not sure what to do about these ones. While I recognize that this approach is certainly one method of teaching a language, I'm not sure that it constitutes an educational textbook. We do require that the English Wikibooks be written in English—for language-learning books, this typically means that the instructional parts are in English while the exercises are in the language being taught. I do think that if the language doesn't have much supporting evidence outside the book itself, it can safely be deleted. — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 01:01, 29 September 2024 (UTC)
: Author of the book here. I originally wanted to put it in the Interlingue Wikibooks https://ie.wikibooks.org/wiki/Principal_p%C3%A1gine but it somehow got locked when I wasn't paying attention and so I ended up putting it here. Getting it unlocked requires going through the process of starting an Incubator and all the rest so I opted for here and then started putting some English-only content once it was done. It's sort of in the same vein as books like Lingua Latina per se Illustrata that have separate versions with teacher notes and whatnot. [[Salute, Jonathan!/Capitul 1 - with notes]] After it was done the auxlang community really took to it which was a nice surprise. I think Ido has the largest number of chapters at the moment at 15.
:If the vast content of this book could be used to justify a quick reopening of the Interlingue Wikibooks to move it there, I'd love to do that. I imagine that an incubator with 100+ book chapters would be enough to open a Wikibooks and that's what this is. — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 06:02, 29 September 2024 (UTC)
: Ah, I just realized that we do have a proposal to reopen the Interlingue Wikibooks: https://meta.wikimedia.org/wiki/Requests_for_new_languages/Wikibooks_Interlingue along with an Incubator page here. https://incubator.wikimedia.org/wiki/Wb/ie/Principal_p%C3%A1gine
: How easy would it be to migrate the entirety of Salute Jonathan to there? — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 06:30, 29 September 2024 (UTC)
:: Hi @[[User:Mithridates|Mithridates]]! I'm not sure how incubator projects work, but I fully support migrating these books there. You may want to inquire over there and link to this discussion to support your request to move the content over there. Cheers! — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 13:16, 29 September 2024 (UTC)
::: Hi! Actually I have a third idea to propose after thinking about this again today (haven't been here much since I finished the book): I noticed that there is more English content than I remember and that might make it an awkward fit for the Interlingue Wikibooks. I definitely agree that having all the auxlang translations for new auxlang projects goes well beyond the scope of this Wikibooks. Finally, there are some auxlangs that are notable with their own Wikipedias.
::: So the idea is the following:
:::# Leave the original here and I can continue the work on the version with English notes and grammar. That will make it the same as Lingua Latina per se Illustrata, English by the Nature Method, Athenaze and all the rest.
:::# The Interlingua one can move to the Interlingua Wikibooks (maybe Romanica too if they want as it is sort of a dialect of Interlingua).
:::# For Ido and Lingua Franca Nova which have a Wikipedia but not a Wikibooks, I'm a little bit unsure...technically they could have their own version like the original one but would require English explanations. I could let them know and see if they are willing to do so and see what they think (work on adding English to the books vs. move the content elsewhere).
:::# The rest can move to a Github repo, then be deleted, and the front page of this book can have a single link to the repo.
::: Any thoughts on that? Adding the extra English content will be easy as it is my book and I know it inside and out.
::: Edit: [https://en.wikibooks.org/wiki/Salute,_Jonathan!/Grammar_(pronouns) this page] I just added. — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 13:50, 29 September 2024 (UTC)
:::: Thanks for taking the time to consider this! Here are my responses/questions:
::::* Is the original [[Salute, Jonathan!]] (Occidental)? Since that one is quite fleshed out, I agree that if you edit it so the primary language of the book (e.g. headers, instructions, etc) are written in English while leaving the actual story in Occidental, it would be okay and fit in more with instructional language textbooks.
::::* For your points 2 and 3, I'm not sure how those other projects work, so I'll leave it up to them. I'm not quite sure why they would need to move, since in theory they could be revised with English as the language of instruction? Although, they have been left incomplete for a long time.
::::* For your point 4, I have no problem with that. Cheers! — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 16:51, 29 September 2024 (UTC)
::::: Hello again, it's the weekend so I have a bit more time to work on this. I've decided to merge the extra content from the following five chapters since the difference is fairly small and the original chapters should now have this English content. Could you delete these five pages now that they are no longer needed? [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:02, 5 October 2024 (UTC)
::::: [[Salute, Jonathan!/Capitul 1 - with notes]]
::::: [[Salute, Jonathan!/Capitul 2 - with notes]]
::::: [[Salute, Jonathan!/Capitul 3 - with notes]]
::::: [[Salute, Jonathan!/Capitul 4 - with notes]]
::::: [[Salute, Jonathan!/Capitul 5 - with notes]] [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:02, 5 October 2024 (UTC)
:::::: [[File:Yes_check.svg|{{#ifeq:|small|8|15}}px|link=|alt=]] {{#ifeq:|small|<small>|}}'''Done'''{{#ifeq:|small|</small>|}} — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:34, 5 October 2024 (UTC)
::::::: Hi again! No luck trying to find a home for the random language translations on other auxlang wikis, can't find one that is actively maintained.
::::::: The thought struck me that maybe I could just put those ones on a sub page of my user page, would that be permitted? If not, I think I'll just stick them somewhere in GitHub and call it a day since none of the people who started the translations seem to care enough to do anything about them. I'd rather not see them outright disappear but since they aren't mine I don't care enough about them to do much more work than copy and paste them somewhere.
::::::: (I would leave the ones in languages with an ISO-639 code and Wikipedia here, of course) — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:13, 9 November 2024 (UTC)
:::::::: Thank you for checking! I don't personally see an issue with moving them to your user space right now. Cheers — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 17:21, 9 November 2024 (UTC)
::::::::: Thanks a lot! I've started a single page where I will put them all here [[User:Mithridates/SJ]] and will proceed slowly due to lack of time and also to avoid stepping on any toes / asking you to delete too much at a time and possibly deleting the wrong content.
::::::::: For this week I have put the content for the languages Audia, Cristianès, Guosa, Lingaust, Mini, Mirad, and Monav on that page as they all have a single page of content and didn't take much time to move. Please delete those. Once they are gone I will add a note on the main page letting people know where they have gone (in addition to a thank you for their interest in the book! I do love how many people have recognized it as a good source material for teaching a language). — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 04:09, 10 November 2024 (UTC)
: {{keep}} the translations for languages that have an article on the English Wikipedia, i.e. Guosa, Idiom Neutral, Ido, Interlingua, Lingwa de Planeta, Negerhollands, Neo, Novial, Occidental, Romanica, Solresol, Toki Pona, and Volapük.
: Translations for languages that don't have an article can be kept if they have reliable sources, which I was able to find for the following languages (if you think they are not reliable, please let me know):
:* Globasa: [https://www.languagesandnumbers.com/how-to-count-in-globasa/en/globasa/] [https://greyson.conlang.org/2020/01/29/shouting-out-globasa-and-pandunia/]
:* Mini: [https://jprogr.github.io/mini] [https://www.omniglot.com/language/phrases/mini.htm] [https://www.languagesandnumbers.com/how-to-count-in-mini/en/mini/]
: {{del}} and move to [[User:Mithridates/SJ]] the rest of the translations, i.e. Audià/Audian, Cristianés, Ekumenski, Germanisch, Interocidental, Lingaust, Lingue Simple, Masa Tang, Mirad, Monav, Monkel, Mundeze, Nordien, Novlingue, Numo, Proyo, and Scuian/Meteza. If you can find reliable sources for those languages, please let me know.
: In particular, I could not find resources for Audià/Audian and Monav after searching through 15 and 17 pages on Google, respectively. It doesn't help that [[Òla, Ionatà!|their]] [[Hai, Jon!|translations]] don't explain what those languages are and where to find resources for them. This makes contributing to those translations almost impossible until @[[User:Caro de Segeda|Caro de Segeda]] can provide resources to us. It's possible that the resources may have disappared from the Internet, or that those languages were created by Caro de Segeda him/herself. If you can find resources for Audià/Audian and Monav, please let me know.
: I'm notifying the primary contributors of the translations: @[[User:Caro de Segeda|Caro de Segeda]], @[[User:Frzzl|Frzzl]], @[[User:Greatscotteh|Greatscotteh]], @[[User:IHateNumbers234|IHateNumbers234]], @[[User:Jayeless2|Jayeless2]], @[[User:Morozof|Morozof]], @[[User:Omnihom|Omnihom]], @[[User:Omoutuazn|Omoutuazn]], @[[User:PovriNaivon|PovriNaivon]], @[[User:Sir Beluga|Sir Beluga]] and @[[User:Tyoyafud|Tyoyafud]]. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 09:52, 30 June 2025 (UTC)
:: Caro de Segeda said on [https://www.reddit.com/r/conlangs/comments/1lcnz9g/comment/n0sc3wx/ Reddit] that Monav was created by him/her and that he/she didn't publish any resources about it other than [[Hai, Jon!]]. With '''zero''' other resources to rely on for contributing to the translation, and the fact that Monav is in [[User:Mithridates/SJ]], [[Hai, Jon!]] should be speedy deleted. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 01:38, 3 July 2025 (UTC)
::: I've undone the speedy deletion as Caro de Segeda posted a [https://prexins.wordpress.com/2025/07/04/monav/ resource] for Monav. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 07:18, 4 July 2025 (UTC)
:::: You can delete all the ones that I have created myself, I have already moved them to other places. — [[User:Caro de Segeda|Caro de Segeda]] ([[User talk:Caro de Segeda|discuss]] • [[Special:Contributions/Caro de Segeda|contribs]]) 12:39, 5 July 2025 (UTC)
{{outdent|::::}}I don't know if this is helpful since it wouldn't apply to most of these, but [[s:mul:]] could hold some of these. — [[User:Arlo Barnes|Arlo Barnes]] ([[User talk:Arlo Barnes|discuss]] • [[Special:Contributions/Arlo Barnes|contribs]]) 09:18, 30 November 2025 (UTC)
: I don't think that would be within the scope of that project. I'm not aware of any other situation where Wikisource publishes translations of texts created on Wikimedia projects - that's usually left up to other language editions of the same project. — [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 05:34, 1 December 2025 (UTC)
:: In this situation there isn't a separate [[s:ie:]] distinct from Multilingual Wikisource (see [[meta:Wikisource#List of Wikisources]]). In fact, there are very few multilingual wikis in the Wikimedia sphere; while this project ''could'' move to a Miraheze-hosted or similar wiki farm location, I think it would be a missed opportunity. I suppose an [[Interlingue]] book could be started in [[shelf:Constructed languages]] which would have all 100 chapters as an appendix (and likewise for the other languages), but that also seems non-ideal since it requires an English-language text that doesn't currently exist to be created. [[WB:AT]] seems to describe a similar situation to this one and prescribe Wikisource as the solution, and [[WB:SOURCE]] mentions fiction as out-of-scope for Wikibooks (even as in this case, language-educational fiction). [[s:mul:Wikisource:about Wikisource]] simply speaks of source texts and doesn't mention publication requirements, so maybe that is specific to some of the monolingual editions? — [[User:Arlo Barnes|Arlo Barnes]] ([[User talk:Arlo Barnes|discuss]] • [[Special:Contributions/Arlo Barnes|contribs]]) 22:28, 5 December 2025 (UTC)
:{{keep}} 100% keep. These books are a core part of language textbooks on Wikibooks and have been for years. Not sure why this is even being debated.--[[User:Xania|Xania]] [[Image:Flag_of_Estonia.svg|15px]] [[Image:Flag_of_Ukraine.svg|15px]] [[User talk:Xania|<sup>talk</sup>]] 17:55, 16 May 2026 (UTC)
::With all due respect, some of the books included in this nomination (like [[Sin Chao, Jonathan!]]) are written in constructed languages which are not substantially attested anywhere else. I struggle to imagine any educational purpose for such a book. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:12, 17 May 2026 (UTC)
== [[International Baccalaureate]] ==
Not actually a book in and of itself; rather, it is just a compilation of links to other books —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:24, 18 October 2024 (UTC)
: Could this be salvaged as a shelf? [[User:Pppery|Pppery]] ([[User talk:Pppery|discuss]] • [[Special:Contributions/Pppery|contribs]]) 05:23, 27 January 2025 (UTC)
::Probably, but are the linked books even useful? IB exams change from year to year - sometimes quite dramatically - so an old exam guide is of very limited value. Many of these books were written 10-15 years ago, and some of them (like [[IB French]]) even have comments indicating that they're no longer applicable. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 02:18, 8 December 2025 (UTC)
:I would be interested in a book that explains what an [[International Baccalaureate]] is. They may be books about it in the real world, but they are not free and with the online world becoming a fortress of paywalls I wonder how much longer one would be able to find such information on the web. This is what the wikipedia article says:
:* This article '''is missing information''' about the educational programs and curricula. Please expand the article to include this information. Further details may exist on the [[wikipedia:Talk:International_Baccalaureate#|talk page]]. ''(March 2025)''
:[[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 02:05, 13 October 2026 (UTC)
== [[Character List for Baxter&Sagart]] ==
Seems completely out of scope as an educational book; it's just a list of characters and outlinks —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:53, 18 October 2024 (UTC)
:Adding [[Character List for Karlgren's GSR]] and [[Character List for Schuessler's CGSR]] for the same reason —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:55, 18 October 2024 (UTC)
:These three books do make a package and I agree they should be considered together. However, I strongly object to deleting them. They are really extremely useful resources. I use them every week and I know that many people who do work on Old Chinese phonology do so. There are lots of books out there that are lists of characters, these are called dictionaries. For example Axel Schuessler's ABC Etymological Dictionary of Old Chinese, or Pulleyblank's Lexicon of Reconstructed Pronunciation in Early Middle Chinese, Late Middle Chinese, and Early Mandarin. I see it as entirely a good thing for reference works of this kind to be available free online rather than only in expensive books in university research libraries. If this is in violation of a Wikibooks policy, I would at least like that policy to be drawn to my attention and to have some constructive comment offered about which Wikiproject such a resource should fall under. I will also say on a personal note that I have put literally hundreds of hours of work into these projects and it would grieve me a lot to see this work simply vanish, in particular when I know that colleagues around the world use these books. --[[User:Tibetologist|Tibetologist]] ([[User talk:Tibetologist|discuss]] • [[Special:Contributions/Tibetologist|contribs]]) 07:27, 1 November 2024 (UTC)
::Hi @[[User:Tibetologist|Tibetologist]], and thank you for the feedback! Official Wikibooks policy does not permit standalone dictionaries (see [[WB:DICT]]), though I understand the argument that it is a useful resource. I am wondering if there might be a home for it at [[Wiktionary:Wiktionary:Welcome, newcomers|Wiktionary]] or [[Wikiversity:Wikiversity:SHARE|Wikiversity]]? Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 12:14, 1 November 2024 (UTC)
:::The policy says to use Wiktionary, but these books cannot be moved there. In fact they link there, you can understand me as having made an index to wiktionary, if you like, where the ORDER of the characters is extremely important, information that would be lost in Wiktionary.
:::Wikiversity is not a project I participate in, and in any event my books here are older than it, so this option was not available for me at the relevant moment. If you are offering to move my books to Wikiversity, that is very kind of you and I will very graciously accept. [[User:Tibetologist|Tibetologist]] ([[User talk:Tibetologist|discuss]] • [[Special:Contributions/Tibetologist|contribs]]) 14:10, 1 November 2024 (UTC)
::::I have pinged over at Wikiversity Colloquium to ask about suitability and have looped you into the conversation over there. Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 18:20, 1 November 2024 (UTC)
::I concur. I'm just an undergrad who tries to learn about Sino-Tibetan historical linguistics in his free time but I've found this wikibook to be incredibly useful, and I keep it open in one tab while I watch Professor Nathan Hill's lectures that he uploads to youtube in another tab, and another tab for taking notes. In fact if I remember correctly Professor Hill actually pointed his students to this wikibook.
::I'm not familiar with [[wikiversity:Wikiversity:SHARE|Wikiversity]] but if all the content were as accessible there as it is here then I think that could work. [[User:ChromeBones|ChromeBones]] ([[User talk:ChromeBones|discuss]] • [[Special:Contributions/ChromeBones|contribs]]) 02:43, 9 July 2025 (UTC)
:Per [[:v:Wikiversity:Colloquium#Import_Resource_From_Wikibooks?]], I recommend copying and pasting, including attribution via the edit summary and talk page, add appropriate categories and links, and then it could be deleted locally. —[[User:Koavf|Justin (<span style="color:grey">ko'''a'''vf</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 22:32, 3 November 2024 (UTC)
== [[Suomen kieli käyttöön]] ==
Multiple pages in this book are written entirely in Finnish, which is out of the enWB scope. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 00:09, 19 October 2024 (UTC)
:I was going to say whether we should ask any fiwikibooks sysop to maybe see if this could be transwikied to fiwb if it's within the scope there. But [[:fi:Toiminnot:Käyttäjät/sysop]] indicates that there are only 3 sysops, and only {{u|Anr}} and {{u|Zache}} have made edits this ''year''. If they deem it to be salvageable, then transwiki + delete, otherwise straight-up delete. --[[User:SHB2000|SHB2000]] ([[User talk:SHB2000|discuss]] • [[Special:Contributions/SHB2000|contribs]]) 11:24, 14 November 2024 (UTC)
::It seems that the idea behind the book was for the pages to be bilingual, as it’s a language learning book. That’s why there are Finnish texts included intentionally even on the pages that are complete. There are similar books in dewikibooks and ruwikibooks as well. For the English version, I think the easiest way to proceed would be to clean up and adjust the page layout to fit enwikibooks better, and then translate the missing parts. By the way, if anyone wants to update the book’s name in English, it can be titled ''"Using the Finnish Language"'' or ''"Put Finnish Language into Use"'' for a direct translation. [[User:Zache|Zache]] ([[User talk:Zache|discuss]] • [[Special:Contributions/Zache|contribs]]) 11:57, 14 November 2024 (UTC)
== [[AT&T Mobility FAQ]] ==
* [[AT&T Mobility FAQ]]
* [[AT&T Mobility FAQ/MEdia Net Configuration]]
* [[AT&T Mobility FAQ/Data Connect Configuration]]
An ''extremely'' outdated FAQ on AT&T's cell phone services. Most of this document was written 20+ years ago as a Usenet FAQ; very little of it is accurate or useful anymore (particularly the two subpages, which have to do with obsolete configurations for "tethering" a computer to a cell phone). No objection if someone wants to update it, but there's clearly been no appetite to do that. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 22:20, 30 December 2024 (UTC)
:I'm wondering if it might make sense for us to develop some kind of policy on archiving books here. There are many like this one that have a good deal of content but are extremely out of date and just not useful as originally intended. ——[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 22:34, 30 December 2024 (UTC)
::@[[User:Kittycataclysm|Kittycataclysm]]: See the newly developed [[Wikibooks:Outdated books]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 00:16, 31 December 2024 (UTC)
:::Ooh, thanks - something like that seems like it could be an appropriate way to handle this book. A lot of the other outdated books I've tagged have been so incomplete that they wouldn't have been particularly useful even as historical references; this one might at least have some interest.
:::Any chance we can get a separate namespace (maybe "Archive:") set up for archived book content? That'd make it possible to do things like exclude them from on-site search by default. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:07, 31 December 2024 (UTC)
::::I think this might be a more extended discussion, so I'll bump it over to the [[Wikibooks talk:Outdated books|talk page of the draft policy]]! —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 21:54, 31 December 2024 (UTC)
== Algebra/Chapter 10/Symmetric Polynomials ==
I personally believe that [[Algebra/Chapter 10/Symmetric Polynomials|this]], and all of the sections should be deleted for the fact that this goes WAY beyond the scope of what was intended for the Chapter (Algebra II level polynomials). [[User:GoreyCat|GoreyCat]] ([[User talk:GoreyCat|discuss]] • [[Special:Contributions/GoreyCat|contribs]]) 15:07, 6 February 2025 (UTC)
:'''Split''': Deletion here is not the best solution (see [[w:WP:ATD]]). Instead, this page and its subpages should be moved to another book, most likely [[Abstract Algebra]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 17:35, 6 February 2025 (UTC)
:{{keep}} since there is a good amount of content. If [[Abstract Algebra]] is appropriate, it seems like a fine idea to move there. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 22:59, 7 February 2025 (UTC)
::Eh, yeah, I supposed moving it is better. I just don't think it's suitable for where it appears. [[User:GoreyCat|GoreyCat]] ([[User talk:GoreyCat|discuss]] • [[Special:Contributions/GoreyCat|contribs]]) 01:40, 8 February 2025 (UTC)
== [[Puredyne]] ==
Development of Puredyne Linux was discontinued in 2012, and the software no longer appears to be available for download anywhere. (An archive of the web site is still up - with a bunch of embedded spam links - but the download links are all dead.) Is this a suitable candidate for archival (cf. [[Wikibooks:Outdated books]]), or should it just be deleted? [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 04:35, 5 March 2025 (UTC)
:I'd just archive stuff like this. Looks like a decent bit of work went into it, and you never know when someone might need to use Puredyne for some obscure project. I'd be willing to bet mirrors exist of it somewhere, or someone has it on a drive. If you want to find some stuff worth deleting, comb through [[:Category:Allbooks categories]]. [[User:MediaKyle|MediaKyle]] ([[User talk:MediaKyle|discuss]] • [[Special:Contributions/MediaKyle|contribs]]) 11:30, 5 March 2025 (UTC)
== [[Template:Qr-twwp]] ==
This isn't exactly a request to delete the template, but rather to merge it with {{tlx|Copypaste}}. The {{tlx|Qr-twwp}} template serves the same purpose as {{tlx|Copypaste}}, but without the seven-day period after which the page is deleted. This leads to confusion, as well as a perpetually full [[:Category:Queried pages]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 17:37, 30 March 2025 (UTC)
== [[Ghouls of the Miskatonic]] ==
I don't think that a plot summary of a book is in-scope here. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 18:43, 20 August 2025 (UTC)
:{{vd}} - at least, not a summary of ''this'' book. A summary and/or study guide to a notable work of literature might be in scope, but this is certainly not one. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:23, 25 August 2025 (UTC)
::Hi. I am the creator of the pages of this book. If I understand correctly, it has to be a summary of a notable work of literature? So what exactly is defined as such? I only started this as I thought it would be fun, interesting and encouraging to others who read the Arkham Horror novels, and I thought it was permitted as I've seen other summaries of books on wikibooks. [[User:Dayne90|Dayne90]] ([[User talk:Dayne90|discuss]] • [[Special:Contributions/Dayne90|contribs]]) 13:27, 26 August 2025 (UTC)
:::Your problem is it is just the plot... it needs to include an educational textual analysis to be in scope [[User:MarcGarver|MarcGarver]] ([[User talk:MarcGarver|discuss]] • [[Special:Contributions/MarcGarver|contribs]]) 12:47, 28 August 2025 (UTC)
::::And ideally it'd be a text which has ''already'' been the subject of literary analysis, such that the analysis on Wikibooks isn't original research. A notable work of literature like ''Frankenstein'' or ''Moby-Dick'' would easily meet that requirement; a tie-in novel for a tabletop RPG probably does not. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 22:08, 29 August 2025 (UTC)
== [[A-level Computing AQA Paper 1 Skeleton program 2027]] ==
This was proposed for speedy deletion by [[User:Omphalographer]] as 'not being a book'. However, I think this page's future requires further discussion from the community. Maybe some input would be appreciated?[[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 23:51, 21 September 2026 (UTC)
:As best I can tell, this is a page students are using to collaborate on solutions for a standardized test. There are a number of similar pages for other years linked from [[A-level Computing/AQA/Paper 1/Skeleton program]].
:This is not a good fit for Wikibooks. If these students are interested in this kind of collaboration, it should take place elsewhere. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:14, 22 September 2026 (UTC)
::The project can be moved to Wikiversity, I think. If the students can contribute it and make sure it complies with Wikibooks' guidelines, it can stay here. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 00:17, 22 September 2026 (UTC)
:::@[[User:Omphalographer|Omphalographer]] @[[User:TechVindicator|TechVindicator]]
:::There's been a Wikibook on this every single year, as I mentioned in my comment on the deletion notice. That doesn't mean that this shouldn't be on Wikiversity, just that there is ample precedent of it being a Wikibook. Dunno if this matter to those kind of editorial decisions, though. [[Special:Contributions/~2026-51010-27|~2026-51010-27]] ([[User talk:~2026-51010-27|talk]]) 13:39, 22 September 2026 (UTC)
::::@[[User:~2026-51010-27|~2026-51010-27]]: How would the page comply with [[WB:What is Wikibooks?|Wikibooks' mission]]?. Could you provide an explanation of what the project is? If it's a collaborative project to work on solutions for a standardized test (like @[[User:Omphalographer|Omphalographer]] said), it would be more suitable for Wikiversity. If it's a textbook about A-level computing, then it would be suitable here. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 13:58, 22 September 2026 (UTC)
:::::Hi,
:::::This is definitely the former, not the latter. As I said, I don't particularly think this should be on Wikibooks, it just happens the previous years had been, and clearly they weren't subject to this degree of scrutiny 😅
:::::I have created https://en.wikiversity.org/wiki/A-level_Computer_Science_AQA_Paper_1_Skeleton_program_2027 - I'll delete the content of the page and put the link at the top. If there is a more appropriate banner to indicate the migration, please make it look how it should :D [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 10:23, 29 September 2026 (UTC)
::::::I can't seem to put a link without the edit being deemed destructive, so I'll let you trusted people do what's needed. [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 10:27, 29 September 2026 (UTC)
: {{comment}}: I cannot determine consensus in this request on whether or not it should either be deleted or imported to English Wikiversity. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:28, 13 October 2026 (UTC)
== [[Talmudic aramic]] ==
{{closed|Deleted per consensus below. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:18, 13 October 2026 (UTC)}}
Per the user's other mass-created pages, I concur with the AI flagging that Kittycataclysm placed on the page. I believe this to be LLM-generated, and it should thus be deleted. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 03:29, 30 September 2026 (UTC)
:{{vd}}, LLM spam. [[User:Ternera|Ternera]] ([[User talk:Ternera|discuss]] • [[Special:Contributions/Ternera|contribs]]) 13:22, 30 September 2026 (UTC)
:{{vd}} - like most LLM-generated books, this is heavy on structure and light on substance. Most of the content amounts to a poorly organized glossary, and there are a lot of pieces missing. (For instance, there is no discussion of the grammar of the language beyond a couple of fixed expressions.) [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:11, 1 October 2026 (UTC)
:{{vd}} per stated reasoning. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 14:43, 12 October 2026 (UTC)
{{end closed}}
== [[Job Search]] ==
{{closed|Per minimal consensus, I deleted these books, but I only kept the main pages of these books by creating them as redirects for [[Find Employment]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:24, 13 October 2026 (UTC)}}
* as well as [[Job Search Automation for College Students]].
Neither of these books contains any useful information. The first book seems to be written primarily to funnel users to the second, and the second to funnel users to [[PlanoTse Handbook for Job Search Automation]], which was deleted last year. (The deletion request doesn't seem to have been archived.)
The sum total of information in these two books is, essentially, "you can search for jobs online", which is insultingly trivial. The second book's suggestion that users automate the job search process is of no practical value; most web search engines and job search sites nowadays will detect and block automated access.
[[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:36, 1 October 2026 (UTC)
: {{vd}} and redirect to [[Find Employment]]. ‑‑[[User:Kai Burghardt|Kai Burghardt]] ([[User talk:Kai Burghardt|discuss]] • [[Special:Contributions/Kai Burghardt|contribs]]) 05:14, 2 October 2026 (UTC)
{{end closed}}
== [[Wikipage]] ==
{{closed|Deleted per minimal consensus below. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:26, 13 October 2026 (UTC)}}
Like a few other books created by this user, the purpose of this book appears to have been to promote a piece of software written by the author ([[User:Planotse]]). The software is no longer available, and there is no actual content in the book.
[[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:40, 1 October 2026 (UTC)
:{{Vd}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
{{end closed}}
== [[Becoming a Linguistic Mastermind]] ==
Old book (created 2007) with no substantial content. The intent of this book appears to have been to create a single textbook encompassing ''all'' languages, with sub-courses for each language at [[Becoming a Linguistic Mastermind/The courses]], but no such courses were ever created. An analogous project on dewikibooks [[:b:de:Wikibooks:Löschkandidaten/ 2011-04#Der einfache Weg zum Sprachgenie|was deleted in 2011 for similar reasons]]. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:20, 7 October 2026 (UTC)
:{{Vd}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
== [[The Permanent Advantage]] ==
Probably LLM-generated, given broken templates, references to Claude, and section identifiers. This could probably be speedied, but not 100% sure so throwing it to RfD. Even regardless of whether it's LLM-generated or not, I can't see any way it's really suitable for the project. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 07:49, 10 October 2026 (UTC)
:{{vd}} - a book ''about'' chess problems isn't necessarily out of scope, but there needs to be some written content to accompany the problems. And I'm not sure these are even meaningful problems - the few problems with viewable Lichess links appear to be in the early game, so there aren't necessarily objective "solutions" to them. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:51, 10 October 2026 (UTC)
:{{vd}}, the Claude references throughout the book support that it's LLM-generated. [[User:Ternera|Ternera]] ([[User talk:Ternera|discuss]] • [[Special:Contributions/Ternera|contribs]]) 14:55, 11 October 2026 (UTC)
== [[Digital Synthora]] ==
Not within WB scope since it seems to be entirely fabricated by the editor. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 14:20, 12 October 2026 (UTC)
:{{vd}} While some amount of original research is allowed here, completely fabricated topics aren't. This is just fiction writing, which is nice, but not within our scope. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
:{{vd}} - per my initial tag, this appears to be an invention of the page creator; I can't find anything relevant online beyond the empty https://synthoraactstuff.fandom.com/. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 01:32, 13 October 2026 (UTC)
e1mlrvcztpl62vd8yqzk3li0ir3072f
4675857
4675853
2026-10-13T14:35:44Z
MrBerard
3626488
/* A-level Computing AQA Paper 1 Skeleton program 2027 */ Reply
4675857
wikitext
text/x-wiki
__NEWSECTIONLINK__
[[Category:Wikibooks deletion|{{PAGENAME}}]]
{{Discussion Rooms}}
{{TOCleft}}
{{shortcut|WB:RFD}}
{{Requests for deletion/New deletion}}
{{Requests for deletion/Deletion intro}}
<!-- New deletion nominations go at the bottom of page. -->
== [[Salute, Jonathan!]] and its translations ==
<div style="column-count: 7;">
* [[Salute, Jonathan!|Interlingue/Occidental]] ([[w:en:Occidental|w]], original)
* [[Òla, Ionatà!|Audià]]
* [[Holo, Jonathan!|Cristianés]]
* [[Terve, Jonathan!|Ekumenski]]
* [[Hej, Jonathan! (Germanisch)|Germanisch]]
* [[Salom, Jonatan!|Globasa]]
* [[Àlŏ, Jonathan!|Guosa]] ([[w:en:Guosa|w]])
* [[Salut, Jonathan!|Idiom Neutral]] ([[w:en:Idiom Neutral|w]])
* [[Saluto, Jonathan! (Ido)|Ido]] ([[w:en:Ido|w]])
* [[Hallo, Jonathan!|Interlingua]] ([[w:en:Interlingua|w]])
* [[Salut, Jonathan! (Interocidental)|Interocidental]]
* [[Bune Ğonatan!|Lingaust]]
* [[Oila, Jonatan!|Lingue Simple]]
* [[Haloo, Jonatan!|Lingwa de Planeta]] ([[w:en:Lingwa de Planeta|w]])
* [[Sin Chao, Jonathan!|Masa Tang]]
* [[Salut, ionatano!|Meteza]]
* [[Salu, Jon!|Mini]]
* [[Hay, Jonathan!|Mirad]]
* [[Hai, Jon!|Monav]]
* [[Sesan Jon!|Monkel]]
* [[Salam, Jonathan!|Mundeze]]
* [[Dag, Jonathan!|Negerhollands]] ([[w:en:Negerhollands|w]])
* [[Salut Jonathan!|Neo]] ([[w:en:Neo|w]])
* [[Hej, Jonathan!|Nordien]]
* [[Saluto, Jonathan!|Novial]] ([[w:en:Novial|w]])
* [[Salute, Jonathan! (Novlingue)|Novlingue]]
* [[Alo, Jonathan!|Numo]]
* [[Hela, Jonathan!|Proyo]]
* [[Salute, Jonathan! (Romanica)|Romanica]] ([[w:en:Romanica|w]])
* [[Simi, Jonathan!|Solresol]] ([[w:en:Solresol|w]])
* [[Toki a, jan Jonatan!|Toki Pona]] ([[w:en:Toki Pona|w]])
* [[Glidis, o Jonathan!|Volapük]] ([[w:en:Volapük|w]])
</div>
There are a couple of issues here:
# Beyond their introductions, all of these books are written in languages which are not English, making them out of scope for the English Wikibooks.
# All but one of these books are in fact written in constructed languages, most of them in recently created conlangs. In some cases (e.g. [[Sin Chao, Jonathan!]]), I can't find any reliable sources describing the target language outside of the translation itself.
# Most of the translations (i.e. other than [[Salute, Jonathan!]] itself) were abandoned within the first five or so chapters (out of 100); none of them are complete, and there seems to be little effort to complete any of them.
While I recognize that this is an unusual project, and potentially one which could have some value, it's not at all clear to me that the English Wikibooks is the right place for it. — [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:24, 29 September 2024 (UTC)
: I'm really not sure what to do about these ones. While I recognize that this approach is certainly one method of teaching a language, I'm not sure that it constitutes an educational textbook. We do require that the English Wikibooks be written in English—for language-learning books, this typically means that the instructional parts are in English while the exercises are in the language being taught. I do think that if the language doesn't have much supporting evidence outside the book itself, it can safely be deleted. — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 01:01, 29 September 2024 (UTC)
: Author of the book here. I originally wanted to put it in the Interlingue Wikibooks https://ie.wikibooks.org/wiki/Principal_p%C3%A1gine but it somehow got locked when I wasn't paying attention and so I ended up putting it here. Getting it unlocked requires going through the process of starting an Incubator and all the rest so I opted for here and then started putting some English-only content once it was done. It's sort of in the same vein as books like Lingua Latina per se Illustrata that have separate versions with teacher notes and whatnot. [[Salute, Jonathan!/Capitul 1 - with notes]] After it was done the auxlang community really took to it which was a nice surprise. I think Ido has the largest number of chapters at the moment at 15.
:If the vast content of this book could be used to justify a quick reopening of the Interlingue Wikibooks to move it there, I'd love to do that. I imagine that an incubator with 100+ book chapters would be enough to open a Wikibooks and that's what this is. — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 06:02, 29 September 2024 (UTC)
: Ah, I just realized that we do have a proposal to reopen the Interlingue Wikibooks: https://meta.wikimedia.org/wiki/Requests_for_new_languages/Wikibooks_Interlingue along with an Incubator page here. https://incubator.wikimedia.org/wiki/Wb/ie/Principal_p%C3%A1gine
: How easy would it be to migrate the entirety of Salute Jonathan to there? — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 06:30, 29 September 2024 (UTC)
:: Hi @[[User:Mithridates|Mithridates]]! I'm not sure how incubator projects work, but I fully support migrating these books there. You may want to inquire over there and link to this discussion to support your request to move the content over there. Cheers! — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 13:16, 29 September 2024 (UTC)
::: Hi! Actually I have a third idea to propose after thinking about this again today (haven't been here much since I finished the book): I noticed that there is more English content than I remember and that might make it an awkward fit for the Interlingue Wikibooks. I definitely agree that having all the auxlang translations for new auxlang projects goes well beyond the scope of this Wikibooks. Finally, there are some auxlangs that are notable with their own Wikipedias.
::: So the idea is the following:
:::# Leave the original here and I can continue the work on the version with English notes and grammar. That will make it the same as Lingua Latina per se Illustrata, English by the Nature Method, Athenaze and all the rest.
:::# The Interlingua one can move to the Interlingua Wikibooks (maybe Romanica too if they want as it is sort of a dialect of Interlingua).
:::# For Ido and Lingua Franca Nova which have a Wikipedia but not a Wikibooks, I'm a little bit unsure...technically they could have their own version like the original one but would require English explanations. I could let them know and see if they are willing to do so and see what they think (work on adding English to the books vs. move the content elsewhere).
:::# The rest can move to a Github repo, then be deleted, and the front page of this book can have a single link to the repo.
::: Any thoughts on that? Adding the extra English content will be easy as it is my book and I know it inside and out.
::: Edit: [https://en.wikibooks.org/wiki/Salute,_Jonathan!/Grammar_(pronouns) this page] I just added. — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 13:50, 29 September 2024 (UTC)
:::: Thanks for taking the time to consider this! Here are my responses/questions:
::::* Is the original [[Salute, Jonathan!]] (Occidental)? Since that one is quite fleshed out, I agree that if you edit it so the primary language of the book (e.g. headers, instructions, etc) are written in English while leaving the actual story in Occidental, it would be okay and fit in more with instructional language textbooks.
::::* For your points 2 and 3, I'm not sure how those other projects work, so I'll leave it up to them. I'm not quite sure why they would need to move, since in theory they could be revised with English as the language of instruction? Although, they have been left incomplete for a long time.
::::* For your point 4, I have no problem with that. Cheers! — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 16:51, 29 September 2024 (UTC)
::::: Hello again, it's the weekend so I have a bit more time to work on this. I've decided to merge the extra content from the following five chapters since the difference is fairly small and the original chapters should now have this English content. Could you delete these five pages now that they are no longer needed? [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:02, 5 October 2024 (UTC)
::::: [[Salute, Jonathan!/Capitul 1 - with notes]]
::::: [[Salute, Jonathan!/Capitul 2 - with notes]]
::::: [[Salute, Jonathan!/Capitul 3 - with notes]]
::::: [[Salute, Jonathan!/Capitul 4 - with notes]]
::::: [[Salute, Jonathan!/Capitul 5 - with notes]] [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:02, 5 October 2024 (UTC)
:::::: [[File:Yes_check.svg|{{#ifeq:|small|8|15}}px|link=|alt=]] {{#ifeq:|small|<small>|}}'''Done'''{{#ifeq:|small|</small>|}} — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:34, 5 October 2024 (UTC)
::::::: Hi again! No luck trying to find a home for the random language translations on other auxlang wikis, can't find one that is actively maintained.
::::::: The thought struck me that maybe I could just put those ones on a sub page of my user page, would that be permitted? If not, I think I'll just stick them somewhere in GitHub and call it a day since none of the people who started the translations seem to care enough to do anything about them. I'd rather not see them outright disappear but since they aren't mine I don't care enough about them to do much more work than copy and paste them somewhere.
::::::: (I would leave the ones in languages with an ISO-639 code and Wikipedia here, of course) — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 14:13, 9 November 2024 (UTC)
:::::::: Thank you for checking! I don't personally see an issue with moving them to your user space right now. Cheers — [[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 17:21, 9 November 2024 (UTC)
::::::::: Thanks a lot! I've started a single page where I will put them all here [[User:Mithridates/SJ]] and will proceed slowly due to lack of time and also to avoid stepping on any toes / asking you to delete too much at a time and possibly deleting the wrong content.
::::::::: For this week I have put the content for the languages Audia, Cristianès, Guosa, Lingaust, Mini, Mirad, and Monav on that page as they all have a single page of content and didn't take much time to move. Please delete those. Once they are gone I will add a note on the main page letting people know where they have gone (in addition to a thank you for their interest in the book! I do love how many people have recognized it as a good source material for teaching a language). — [[User:Mithridates|Mithridates]] ([[User talk:Mithridates|discuss]] • [[Special:Contributions/Mithridates|contribs]]) 04:09, 10 November 2024 (UTC)
: {{keep}} the translations for languages that have an article on the English Wikipedia, i.e. Guosa, Idiom Neutral, Ido, Interlingua, Lingwa de Planeta, Negerhollands, Neo, Novial, Occidental, Romanica, Solresol, Toki Pona, and Volapük.
: Translations for languages that don't have an article can be kept if they have reliable sources, which I was able to find for the following languages (if you think they are not reliable, please let me know):
:* Globasa: [https://www.languagesandnumbers.com/how-to-count-in-globasa/en/globasa/] [https://greyson.conlang.org/2020/01/29/shouting-out-globasa-and-pandunia/]
:* Mini: [https://jprogr.github.io/mini] [https://www.omniglot.com/language/phrases/mini.htm] [https://www.languagesandnumbers.com/how-to-count-in-mini/en/mini/]
: {{del}} and move to [[User:Mithridates/SJ]] the rest of the translations, i.e. Audià/Audian, Cristianés, Ekumenski, Germanisch, Interocidental, Lingaust, Lingue Simple, Masa Tang, Mirad, Monav, Monkel, Mundeze, Nordien, Novlingue, Numo, Proyo, and Scuian/Meteza. If you can find reliable sources for those languages, please let me know.
: In particular, I could not find resources for Audià/Audian and Monav after searching through 15 and 17 pages on Google, respectively. It doesn't help that [[Òla, Ionatà!|their]] [[Hai, Jon!|translations]] don't explain what those languages are and where to find resources for them. This makes contributing to those translations almost impossible until @[[User:Caro de Segeda|Caro de Segeda]] can provide resources to us. It's possible that the resources may have disappared from the Internet, or that those languages were created by Caro de Segeda him/herself. If you can find resources for Audià/Audian and Monav, please let me know.
: I'm notifying the primary contributors of the translations: @[[User:Caro de Segeda|Caro de Segeda]], @[[User:Frzzl|Frzzl]], @[[User:Greatscotteh|Greatscotteh]], @[[User:IHateNumbers234|IHateNumbers234]], @[[User:Jayeless2|Jayeless2]], @[[User:Morozof|Morozof]], @[[User:Omnihom|Omnihom]], @[[User:Omoutuazn|Omoutuazn]], @[[User:PovriNaivon|PovriNaivon]], @[[User:Sir Beluga|Sir Beluga]] and @[[User:Tyoyafud|Tyoyafud]]. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 09:52, 30 June 2025 (UTC)
:: Caro de Segeda said on [https://www.reddit.com/r/conlangs/comments/1lcnz9g/comment/n0sc3wx/ Reddit] that Monav was created by him/her and that he/she didn't publish any resources about it other than [[Hai, Jon!]]. With '''zero''' other resources to rely on for contributing to the translation, and the fact that Monav is in [[User:Mithridates/SJ]], [[Hai, Jon!]] should be speedy deleted. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 01:38, 3 July 2025 (UTC)
::: I've undone the speedy deletion as Caro de Segeda posted a [https://prexins.wordpress.com/2025/07/04/monav/ resource] for Monav. — [[User:EJPPhilippines|EJPPhilippines]] ([[User talk:EJPPhilippines|discuss]] • [[Special:Contributions/EJPPhilippines|contribs]]) 07:18, 4 July 2025 (UTC)
:::: You can delete all the ones that I have created myself, I have already moved them to other places. — [[User:Caro de Segeda|Caro de Segeda]] ([[User talk:Caro de Segeda|discuss]] • [[Special:Contributions/Caro de Segeda|contribs]]) 12:39, 5 July 2025 (UTC)
{{outdent|::::}}I don't know if this is helpful since it wouldn't apply to most of these, but [[s:mul:]] could hold some of these. — [[User:Arlo Barnes|Arlo Barnes]] ([[User talk:Arlo Barnes|discuss]] • [[Special:Contributions/Arlo Barnes|contribs]]) 09:18, 30 November 2025 (UTC)
: I don't think that would be within the scope of that project. I'm not aware of any other situation where Wikisource publishes translations of texts created on Wikimedia projects - that's usually left up to other language editions of the same project. — [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 05:34, 1 December 2025 (UTC)
:: In this situation there isn't a separate [[s:ie:]] distinct from Multilingual Wikisource (see [[meta:Wikisource#List of Wikisources]]). In fact, there are very few multilingual wikis in the Wikimedia sphere; while this project ''could'' move to a Miraheze-hosted or similar wiki farm location, I think it would be a missed opportunity. I suppose an [[Interlingue]] book could be started in [[shelf:Constructed languages]] which would have all 100 chapters as an appendix (and likewise for the other languages), but that also seems non-ideal since it requires an English-language text that doesn't currently exist to be created. [[WB:AT]] seems to describe a similar situation to this one and prescribe Wikisource as the solution, and [[WB:SOURCE]] mentions fiction as out-of-scope for Wikibooks (even as in this case, language-educational fiction). [[s:mul:Wikisource:about Wikisource]] simply speaks of source texts and doesn't mention publication requirements, so maybe that is specific to some of the monolingual editions? — [[User:Arlo Barnes|Arlo Barnes]] ([[User talk:Arlo Barnes|discuss]] • [[Special:Contributions/Arlo Barnes|contribs]]) 22:28, 5 December 2025 (UTC)
:{{keep}} 100% keep. These books are a core part of language textbooks on Wikibooks and have been for years. Not sure why this is even being debated.--[[User:Xania|Xania]] [[Image:Flag_of_Estonia.svg|15px]] [[Image:Flag_of_Ukraine.svg|15px]] [[User talk:Xania|<sup>talk</sup>]] 17:55, 16 May 2026 (UTC)
::With all due respect, some of the books included in this nomination (like [[Sin Chao, Jonathan!]]) are written in constructed languages which are not substantially attested anywhere else. I struggle to imagine any educational purpose for such a book. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:12, 17 May 2026 (UTC)
== [[International Baccalaureate]] ==
Not actually a book in and of itself; rather, it is just a compilation of links to other books —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:24, 18 October 2024 (UTC)
: Could this be salvaged as a shelf? [[User:Pppery|Pppery]] ([[User talk:Pppery|discuss]] • [[Special:Contributions/Pppery|contribs]]) 05:23, 27 January 2025 (UTC)
::Probably, but are the linked books even useful? IB exams change from year to year - sometimes quite dramatically - so an old exam guide is of very limited value. Many of these books were written 10-15 years ago, and some of them (like [[IB French]]) even have comments indicating that they're no longer applicable. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 02:18, 8 December 2025 (UTC)
:I would be interested in a book that explains what an [[International Baccalaureate]] is. They may be books about it in the real world, but they are not free and with the online world becoming a fortress of paywalls I wonder how much longer one would be able to find such information on the web. This is what the wikipedia article says:
:* This article '''is missing information''' about the educational programs and curricula. Please expand the article to include this information. Further details may exist on the [[wikipedia:Talk:International_Baccalaureate#|talk page]]. ''(March 2025)''
:[[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 02:05, 13 October 2026 (UTC)
== [[Character List for Baxter&Sagart]] ==
Seems completely out of scope as an educational book; it's just a list of characters and outlinks —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:53, 18 October 2024 (UTC)
:Adding [[Character List for Karlgren's GSR]] and [[Character List for Schuessler's CGSR]] for the same reason —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 23:55, 18 October 2024 (UTC)
:These three books do make a package and I agree they should be considered together. However, I strongly object to deleting them. They are really extremely useful resources. I use them every week and I know that many people who do work on Old Chinese phonology do so. There are lots of books out there that are lists of characters, these are called dictionaries. For example Axel Schuessler's ABC Etymological Dictionary of Old Chinese, or Pulleyblank's Lexicon of Reconstructed Pronunciation in Early Middle Chinese, Late Middle Chinese, and Early Mandarin. I see it as entirely a good thing for reference works of this kind to be available free online rather than only in expensive books in university research libraries. If this is in violation of a Wikibooks policy, I would at least like that policy to be drawn to my attention and to have some constructive comment offered about which Wikiproject such a resource should fall under. I will also say on a personal note that I have put literally hundreds of hours of work into these projects and it would grieve me a lot to see this work simply vanish, in particular when I know that colleagues around the world use these books. --[[User:Tibetologist|Tibetologist]] ([[User talk:Tibetologist|discuss]] • [[Special:Contributions/Tibetologist|contribs]]) 07:27, 1 November 2024 (UTC)
::Hi @[[User:Tibetologist|Tibetologist]], and thank you for the feedback! Official Wikibooks policy does not permit standalone dictionaries (see [[WB:DICT]]), though I understand the argument that it is a useful resource. I am wondering if there might be a home for it at [[Wiktionary:Wiktionary:Welcome, newcomers|Wiktionary]] or [[Wikiversity:Wikiversity:SHARE|Wikiversity]]? Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 12:14, 1 November 2024 (UTC)
:::The policy says to use Wiktionary, but these books cannot be moved there. In fact they link there, you can understand me as having made an index to wiktionary, if you like, where the ORDER of the characters is extremely important, information that would be lost in Wiktionary.
:::Wikiversity is not a project I participate in, and in any event my books here are older than it, so this option was not available for me at the relevant moment. If you are offering to move my books to Wikiversity, that is very kind of you and I will very graciously accept. [[User:Tibetologist|Tibetologist]] ([[User talk:Tibetologist|discuss]] • [[Special:Contributions/Tibetologist|contribs]]) 14:10, 1 November 2024 (UTC)
::::I have pinged over at Wikiversity Colloquium to ask about suitability and have looped you into the conversation over there. Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 18:20, 1 November 2024 (UTC)
::I concur. I'm just an undergrad who tries to learn about Sino-Tibetan historical linguistics in his free time but I've found this wikibook to be incredibly useful, and I keep it open in one tab while I watch Professor Nathan Hill's lectures that he uploads to youtube in another tab, and another tab for taking notes. In fact if I remember correctly Professor Hill actually pointed his students to this wikibook.
::I'm not familiar with [[wikiversity:Wikiversity:SHARE|Wikiversity]] but if all the content were as accessible there as it is here then I think that could work. [[User:ChromeBones|ChromeBones]] ([[User talk:ChromeBones|discuss]] • [[Special:Contributions/ChromeBones|contribs]]) 02:43, 9 July 2025 (UTC)
:Per [[:v:Wikiversity:Colloquium#Import_Resource_From_Wikibooks?]], I recommend copying and pasting, including attribution via the edit summary and talk page, add appropriate categories and links, and then it could be deleted locally. —[[User:Koavf|Justin (<span style="color:grey">ko'''a'''vf</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 22:32, 3 November 2024 (UTC)
== [[Suomen kieli käyttöön]] ==
Multiple pages in this book are written entirely in Finnish, which is out of the enWB scope. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 00:09, 19 October 2024 (UTC)
:I was going to say whether we should ask any fiwikibooks sysop to maybe see if this could be transwikied to fiwb if it's within the scope there. But [[:fi:Toiminnot:Käyttäjät/sysop]] indicates that there are only 3 sysops, and only {{u|Anr}} and {{u|Zache}} have made edits this ''year''. If they deem it to be salvageable, then transwiki + delete, otherwise straight-up delete. --[[User:SHB2000|SHB2000]] ([[User talk:SHB2000|discuss]] • [[Special:Contributions/SHB2000|contribs]]) 11:24, 14 November 2024 (UTC)
::It seems that the idea behind the book was for the pages to be bilingual, as it’s a language learning book. That’s why there are Finnish texts included intentionally even on the pages that are complete. There are similar books in dewikibooks and ruwikibooks as well. For the English version, I think the easiest way to proceed would be to clean up and adjust the page layout to fit enwikibooks better, and then translate the missing parts. By the way, if anyone wants to update the book’s name in English, it can be titled ''"Using the Finnish Language"'' or ''"Put Finnish Language into Use"'' for a direct translation. [[User:Zache|Zache]] ([[User talk:Zache|discuss]] • [[Special:Contributions/Zache|contribs]]) 11:57, 14 November 2024 (UTC)
== [[AT&T Mobility FAQ]] ==
* [[AT&T Mobility FAQ]]
* [[AT&T Mobility FAQ/MEdia Net Configuration]]
* [[AT&T Mobility FAQ/Data Connect Configuration]]
An ''extremely'' outdated FAQ on AT&T's cell phone services. Most of this document was written 20+ years ago as a Usenet FAQ; very little of it is accurate or useful anymore (particularly the two subpages, which have to do with obsolete configurations for "tethering" a computer to a cell phone). No objection if someone wants to update it, but there's clearly been no appetite to do that. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 22:20, 30 December 2024 (UTC)
:I'm wondering if it might make sense for us to develop some kind of policy on archiving books here. There are many like this one that have a good deal of content but are extremely out of date and just not useful as originally intended. ——[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 22:34, 30 December 2024 (UTC)
::@[[User:Kittycataclysm|Kittycataclysm]]: See the newly developed [[Wikibooks:Outdated books]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 00:16, 31 December 2024 (UTC)
:::Ooh, thanks - something like that seems like it could be an appropriate way to handle this book. A lot of the other outdated books I've tagged have been so incomplete that they wouldn't have been particularly useful even as historical references; this one might at least have some interest.
:::Any chance we can get a separate namespace (maybe "Archive:") set up for archived book content? That'd make it possible to do things like exclude them from on-site search by default. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:07, 31 December 2024 (UTC)
::::I think this might be a more extended discussion, so I'll bump it over to the [[Wikibooks talk:Outdated books|talk page of the draft policy]]! —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 21:54, 31 December 2024 (UTC)
== Algebra/Chapter 10/Symmetric Polynomials ==
I personally believe that [[Algebra/Chapter 10/Symmetric Polynomials|this]], and all of the sections should be deleted for the fact that this goes WAY beyond the scope of what was intended for the Chapter (Algebra II level polynomials). [[User:GoreyCat|GoreyCat]] ([[User talk:GoreyCat|discuss]] • [[Special:Contributions/GoreyCat|contribs]]) 15:07, 6 February 2025 (UTC)
:'''Split''': Deletion here is not the best solution (see [[w:WP:ATD]]). Instead, this page and its subpages should be moved to another book, most likely [[Abstract Algebra]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 17:35, 6 February 2025 (UTC)
:{{keep}} since there is a good amount of content. If [[Abstract Algebra]] is appropriate, it seems like a fine idea to move there. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 22:59, 7 February 2025 (UTC)
::Eh, yeah, I supposed moving it is better. I just don't think it's suitable for where it appears. [[User:GoreyCat|GoreyCat]] ([[User talk:GoreyCat|discuss]] • [[Special:Contributions/GoreyCat|contribs]]) 01:40, 8 February 2025 (UTC)
== [[Puredyne]] ==
Development of Puredyne Linux was discontinued in 2012, and the software no longer appears to be available for download anywhere. (An archive of the web site is still up - with a bunch of embedded spam links - but the download links are all dead.) Is this a suitable candidate for archival (cf. [[Wikibooks:Outdated books]]), or should it just be deleted? [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 04:35, 5 March 2025 (UTC)
:I'd just archive stuff like this. Looks like a decent bit of work went into it, and you never know when someone might need to use Puredyne for some obscure project. I'd be willing to bet mirrors exist of it somewhere, or someone has it on a drive. If you want to find some stuff worth deleting, comb through [[:Category:Allbooks categories]]. [[User:MediaKyle|MediaKyle]] ([[User talk:MediaKyle|discuss]] • [[Special:Contributions/MediaKyle|contribs]]) 11:30, 5 March 2025 (UTC)
== [[Template:Qr-twwp]] ==
This isn't exactly a request to delete the template, but rather to merge it with {{tlx|Copypaste}}. The {{tlx|Qr-twwp}} template serves the same purpose as {{tlx|Copypaste}}, but without the seven-day period after which the page is deleted. This leads to confusion, as well as a perpetually full [[:Category:Queried pages]]. [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 17:37, 30 March 2025 (UTC)
== [[Ghouls of the Miskatonic]] ==
I don't think that a plot summary of a book is in-scope here. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 18:43, 20 August 2025 (UTC)
:{{vd}} - at least, not a summary of ''this'' book. A summary and/or study guide to a notable work of literature might be in scope, but this is certainly not one. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:23, 25 August 2025 (UTC)
::Hi. I am the creator of the pages of this book. If I understand correctly, it has to be a summary of a notable work of literature? So what exactly is defined as such? I only started this as I thought it would be fun, interesting and encouraging to others who read the Arkham Horror novels, and I thought it was permitted as I've seen other summaries of books on wikibooks. [[User:Dayne90|Dayne90]] ([[User talk:Dayne90|discuss]] • [[Special:Contributions/Dayne90|contribs]]) 13:27, 26 August 2025 (UTC)
:::Your problem is it is just the plot... it needs to include an educational textual analysis to be in scope [[User:MarcGarver|MarcGarver]] ([[User talk:MarcGarver|discuss]] • [[Special:Contributions/MarcGarver|contribs]]) 12:47, 28 August 2025 (UTC)
::::And ideally it'd be a text which has ''already'' been the subject of literary analysis, such that the analysis on Wikibooks isn't original research. A notable work of literature like ''Frankenstein'' or ''Moby-Dick'' would easily meet that requirement; a tie-in novel for a tabletop RPG probably does not. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 22:08, 29 August 2025 (UTC)
== [[A-level Computing AQA Paper 1 Skeleton program 2027]] ==
This was proposed for speedy deletion by [[User:Omphalographer]] as 'not being a book'. However, I think this page's future requires further discussion from the community. Maybe some input would be appreciated?[[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 23:51, 21 September 2026 (UTC)
:As best I can tell, this is a page students are using to collaborate on solutions for a standardized test. There are a number of similar pages for other years linked from [[A-level Computing/AQA/Paper 1/Skeleton program]].
:This is not a good fit for Wikibooks. If these students are interested in this kind of collaboration, it should take place elsewhere. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 00:14, 22 September 2026 (UTC)
::The project can be moved to Wikiversity, I think. If the students can contribute it and make sure it complies with Wikibooks' guidelines, it can stay here. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 00:17, 22 September 2026 (UTC)
:::@[[User:Omphalographer|Omphalographer]] @[[User:TechVindicator|TechVindicator]]
:::There's been a Wikibook on this every single year, as I mentioned in my comment on the deletion notice. That doesn't mean that this shouldn't be on Wikiversity, just that there is ample precedent of it being a Wikibook. Dunno if this matter to those kind of editorial decisions, though. [[Special:Contributions/~2026-51010-27|~2026-51010-27]] ([[User talk:~2026-51010-27|talk]]) 13:39, 22 September 2026 (UTC)
::::@[[User:~2026-51010-27|~2026-51010-27]]: How would the page comply with [[WB:What is Wikibooks?|Wikibooks' mission]]?. Could you provide an explanation of what the project is? If it's a collaborative project to work on solutions for a standardized test (like @[[User:Omphalographer|Omphalographer]] said), it would be more suitable for Wikiversity. If it's a textbook about A-level computing, then it would be suitable here. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 13:58, 22 September 2026 (UTC)
:::::Hi,
:::::This is definitely the former, not the latter. As I said, I don't particularly think this should be on Wikibooks, it just happens the previous years had been, and clearly they weren't subject to this degree of scrutiny 😅
:::::I have created https://en.wikiversity.org/wiki/A-level_Computer_Science_AQA_Paper_1_Skeleton_program_2027 - I'll delete the content of the page and put the link at the top. If there is a more appropriate banner to indicate the migration, please make it look how it should :D [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 10:23, 29 September 2026 (UTC)
::::::I can't seem to put a link without the edit being deemed destructive, so I'll let you trusted people do what's needed. [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 10:27, 29 September 2026 (UTC)
: {{comment}}: I cannot determine consensus in this request on whether or not it should either be deleted or imported to English Wikiversity. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:28, 13 October 2026 (UTC)
::I've actioned the migration to Wikiversity as per my comment of 29 sep. I'd rather this stayed in as a stub with a link to the Wikiversity entry, for a couple of months, though I'm sure search engines are still vaguely good enough that this shouldn't matter too much. [[User:MrBerard|MrBerard]] ([[User talk:MrBerard|discuss]] • [[Special:Contributions/MrBerard|contribs]]) 14:35, 13 October 2026 (UTC)
== [[Talmudic aramic]] ==
{{closed|Deleted per consensus below. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:18, 13 October 2026 (UTC)}}
Per the user's other mass-created pages, I concur with the AI flagging that Kittycataclysm placed on the page. I believe this to be LLM-generated, and it should thus be deleted. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 03:29, 30 September 2026 (UTC)
:{{vd}}, LLM spam. [[User:Ternera|Ternera]] ([[User talk:Ternera|discuss]] • [[Special:Contributions/Ternera|contribs]]) 13:22, 30 September 2026 (UTC)
:{{vd}} - like most LLM-generated books, this is heavy on structure and light on substance. Most of the content amounts to a poorly organized glossary, and there are a lot of pieces missing. (For instance, there is no discussion of the grammar of the language beyond a couple of fixed expressions.) [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:11, 1 October 2026 (UTC)
:{{vd}} per stated reasoning. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 14:43, 12 October 2026 (UTC)
{{end closed}}
== [[Job Search]] ==
{{closed|Per minimal consensus, I deleted these books, but I only kept the main pages of these books by creating them as redirects for [[Find Employment]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:24, 13 October 2026 (UTC)}}
* as well as [[Job Search Automation for College Students]].
Neither of these books contains any useful information. The first book seems to be written primarily to funnel users to the second, and the second to funnel users to [[PlanoTse Handbook for Job Search Automation]], which was deleted last year. (The deletion request doesn't seem to have been archived.)
The sum total of information in these two books is, essentially, "you can search for jobs online", which is insultingly trivial. The second book's suggestion that users automate the job search process is of no practical value; most web search engines and job search sites nowadays will detect and block automated access.
[[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:36, 1 October 2026 (UTC)
: {{vd}} and redirect to [[Find Employment]]. ‑‑[[User:Kai Burghardt|Kai Burghardt]] ([[User talk:Kai Burghardt|discuss]] • [[Special:Contributions/Kai Burghardt|contribs]]) 05:14, 2 October 2026 (UTC)
{{end closed}}
== [[Wikipage]] ==
{{closed|Deleted per minimal consensus below. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:26, 13 October 2026 (UTC)}}
Like a few other books created by this user, the purpose of this book appears to have been to promote a piece of software written by the author ([[User:Planotse]]). The software is no longer available, and there is no actual content in the book.
[[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:40, 1 October 2026 (UTC)
:{{Vd}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
{{end closed}}
== [[Becoming a Linguistic Mastermind]] ==
Old book (created 2007) with no substantial content. The intent of this book appears to have been to create a single textbook encompassing ''all'' languages, with sub-courses for each language at [[Becoming a Linguistic Mastermind/The courses]], but no such courses were ever created. An analogous project on dewikibooks [[:b:de:Wikibooks:Löschkandidaten/ 2011-04#Der einfache Weg zum Sprachgenie|was deleted in 2011 for similar reasons]]. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 21:20, 7 October 2026 (UTC)
:{{Vd}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
== [[The Permanent Advantage]] ==
Probably LLM-generated, given broken templates, references to Claude, and section identifiers. This could probably be speedied, but not 100% sure so throwing it to RfD. Even regardless of whether it's LLM-generated or not, I can't see any way it's really suitable for the project. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 07:49, 10 October 2026 (UTC)
:{{vd}} - a book ''about'' chess problems isn't necessarily out of scope, but there needs to be some written content to accompany the problems. And I'm not sure these are even meaningful problems - the few problems with viewable Lichess links appear to be in the early game, so there aren't necessarily objective "solutions" to them. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:51, 10 October 2026 (UTC)
:{{vd}}, the Claude references throughout the book support that it's LLM-generated. [[User:Ternera|Ternera]] ([[User talk:Ternera|discuss]] • [[Special:Contributions/Ternera|contribs]]) 14:55, 11 October 2026 (UTC)
== [[Digital Synthora]] ==
Not within WB scope since it seems to be entirely fabricated by the editor. —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 14:20, 12 October 2026 (UTC)
:{{vd}} While some amount of original research is allowed here, completely fabricated topics aren't. This is just fiction writing, which is nice, but not within our scope. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 15:30, 12 October 2026 (UTC)
:{{vd}} - per my initial tag, this appears to be an invention of the page creator; I can't find anything relevant online beyond the empty https://synthoraactstuff.fandom.com/. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 01:32, 13 October 2026 (UTC)
o4iw6y939m5i80425h4qu0rg34lrdpe
Haskell
0
4329
4675940
4632183
2026-10-14T00:11:17Z
~2026-54868-50
3628373
4675940
wikitext
text/x-wiki
__NOTOC__
[[File:Haskell-Logo.svg|250px|right|Haskell Logo]]
{{Print version}}
{{Collection}}
{{PDF version}}
{{E-Book Reader PDF version|Haskell eBook Reader.pdf}}
{{Featured book}}
{{Book search|float=right}}
'''Haskell''' is a [[Computer Programming/Functional programming|functional programming]] language. It is distinct in a few ways:
* Haskell is ''pure''. A function when invoked using the same arguments will return the same result every time.
* Haskell is ''lazy''. Evaluations are performed only when needed.
* Haskell provides a modern type system with state-of-the-art features like type classes and generalized algebraic data types (soon enough, terms like those will roll smoothly off your tongue).
Haskell is enjoyable to use because dealing with pure functions makes code much easier to reason about, and the advanced type system helps catch silly mistakes that may have profound consequences.
Our aim in this book is to introduce you to the Haskell programming language — from the very basics to advanced features — and to computer programming in general. We urge seasoned programmers to be especially patient with this process. The languages you are familiar with are likely to differ greatly from Haskell, and the habits acquired from those languages might make it difficult to understand how things work — Haskell is simple, but different. Learning to see the world through the warped mindset of a functional programmer is an adventure in a brave new world, which brings knowledge valuable far beyond the boundaries of any language.
== Overview ==
The book is divided into three sections: a Beginner's Track, an Advanced Track, and a section called ''Haskell in Practice''. The last section, which covers practical use cases, depends only on the Beginner's Track. Seasoned programmers may read [[/Overview|the overview]] to quickly evaluate what makes Haskell unique and different from other languages.
{{Info|Please contribute! Anyone, regardless of Haskell competency, can help out. Spend five minutes improving a module and save someone else hours of time. Check out the [[/Notes for contributors|notes for contributors]]. Even if you get confused by a page, tell us about it on the discussion page (politely, of course).}}
== Beginner's Track ==
This section introduces you to Haskell basics and some commonly used libraries. At the end of this track, you should be able to write simple Haskell programs. Most chapters include exercises, with solutions, for your practice.
{| cellpadding="15" cellspacing="0" style="border: 1px solid MediumAquamarine; border-collapse: collapse; margin: 0.8em 0; vertical-align: top; width: 100%;"
| style="border-right: 1px dashed MediumAquamarine; vertical-align: top;" |
=== Haskell Basics ===
* {{Haskell/Haskell Basics|sep=
*}}
| style="border-right: 1px dashed MediumAquamarine; vertical-align: top;" |
=== Elementary Haskell ===
* {{Haskell/Elementary Haskell|sep=
*}}
| style="border-right: 1px dashed MediumAquamarine; vertical-align: top;" |
=== Intermediate Haskell ===
* {{Haskell/Intermediate Haskell|sep=
*}}
| style="vertical-align: top;" |
=== Monads ===
* {{Haskell/Monads|sep=*|subsep= - |breaksep=
**|firstsep=
*}}
|}
== Advanced Track ==
This section introduces wider functional programming concepts such as different data structures and type theory. It will also cover more practical topics like concurrency.
{| cellpadding="15" cellspacing="0" style="border: 1px solid SlateBlue; border-collapse: collapse; margin: 0.8em 0; vertical-align: top; width: 100%;"
| style="border-right: 1px dashed SlateBlue; vertical-align: top;" |
=== Welcome to Haskell ===
* {{Haskell/Advanced Haskell|sep=
*}}
| style="border-right: 1px dashed SlateBlue; vertical-align: top;" |
=== Fun with Types ===
* {{Haskell/Fun with Types|sep=
*}}
| style="border-right: 1px dashed SlateBlue; vertical-align: top;" |
=== Wider Theory ===
* {{Haskell/Wider Theory|sep=
*}}
| style="vertical-align: top;" |
=== Haskell Performance ===
* {{Haskell/Haskell Performance|sep=
*}}
|}
== Haskell in Practice ==
Day-to-day issues of working with Haskell include items such as knowing the standard libraries, building graphical interfaces, and working with databases. You should be able to jump directly to this section from the beginner's track.
{| cellpadding="15" cellspacing="0" style="border: 1px solid gold; border-collapse: collapse; margin: 0.8em 0; width: 100%;"
| style="border-right: 1px dashed gold; vertical-align: top;" |
=== Libraries Reference ===
* {{Haskell/Libraries Reference|sep=*|subsep= - |breaksep=
**|firstsep=
*}}
| style="border-right: 1px dashed gold; vertical-align: top;" |
=== General Practices ===
* {{Haskell/General Practices|sep=
*}}
| style="vertical-align: top;" |
=== Specialised Tasks ===
* {{Haskell/Specialised Tasks|sep=
*}}
|}
== Appendices ==
* [[/Syntactic sugar/]]
* [[/Solutions|Answers to exercises]]
* [[/Authors/|Authors and Acknowledgements]]
== About the book ==
* [[/Notes for contributors/]]
* [[/Style conventions/]]
* [[/To do/]]
* [[:{{BOOKCATEGORY|Haskell}}/Templates|Templates for the Haskell wikibook]]
* [[/Experimental Modules/|Experimental Modules]]
* [[/List of topics/|List of topics]]
== Other Haskell tutorials ==
* [https://wiki.haskell.org/Meta-tutorial Haskell Meta-tutorial] — the tutorial to find other tutorials
* [http://www.learnyouahaskell.com/Chapters Learn You a Haskell for Great Good] — Tutorial aimed at beginners who may have experience in imperative programming languages but haven't programmed in a functional language before. Available online at no charge (CC BY-NC-SA license); also released as a conventional book.
* [http://book.realworldhaskell.org/ Real World Haskell] — an O'Reilly book, available online at no charge (CC BY-NC license). Built around case studies of practical applications.
== Tutorials that have been incorporated into the Haskell Wikibook ==
The following may be read independently, but their content has been imported and adapted already into the Wikibook here
* [[Write Yourself a Scheme in 48 Hours]] — An alternate approach to teaching Haskell (and perhaps Scheme), aimed at a more advanced audience (though not necessarily one that knows how to program!)
* [[/YAHT|Yet Another Haskell Tutorial]] — aimed at beginners and takes a practical approach to things.
== Additional resources ==
* [http://www.haskell.org/haskellwiki/Learning_Haskell Learning Haskell] at haskell.org
* [https://github.com/sdiehl/wiwinwlh What I Wish I Knew When Learning Haskell] — A wide-ranging collection of concise summaries of many intermediate and advanced Haskell topics. Released in the public domain.
<!-- * [http://dohaskell.com/ Do Haskell] — An index site for articles about Haskell topics --><!-- Dead link. To be replaced with a comparable resource as soon as it matures enough.-->
{{Shelves|Haskell programming language}}
{{Alphabetical|H}}
{{Status|75%}}
[[de:Funktionale Programmierung mit Haskell]]
[[es:Haskell]]
[[fr:Programmation Haskell]]
[[ja:Haskell]]
[[pl:Haskell]]
[[pt:Haskell]]
[[ru:HaskellWikiBook]]
[[zh:Haskell]]
jy475z9ixeubagn5b7jgtoct2ljdamg
Aros/User/Docs
0
13106
4675856
4675760
2026-10-13T14:33:07Z
Jeff1138
301139
4675856
wikitext
text/x-wiki
{{ArosNav}}
==What is AROS==
Google translation
[http://translate.google.com/translate?hl=en&sl=auto&tl=de&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs German], [http://translate.google.com/translate?hl=en&sl=auto&tl=nl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Dutch], [http://translate.google.com/translate?hl=en&sl=auto&tl=fr&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs French], [http://translate.google.com/translate?hl=en&sl=auto&tl=it&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Italian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=da&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Danish],
[http://translate.google.com/translate?hl=en&sl=auto&tl=es&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Spanish], [http://translate.google.com/translate?hl=en&sl=auto&tl=hi&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Hindi], [http://translate.google.com/translate?hl=en&sl=auto&tl=zh-CN&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Chinese],
[http://translate.google.com/translate?hl=en&sl=auto&tl=ru&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Russian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Polish], [http://translate.google.com/translate?hl=en&sl=auto&tl=ja&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Japanese], [http://translate.google.com/translate?hl=en&sl=auto&tl=ko&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Korean],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pt&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Portuguese],
*Computer Hardware
*AROS (operating system)
*Applications and Games
*User
[http://www.osnews.com/story/15819 AROS] is one of the intermediate levels between the computer hardware and the user. It is an open-source, clean-room implementation of AmigaOS 3.x that can be run on many different computer architectures. It runs primarily on PC x86 32bit and 64bit but also on amiga motorola 68k and compatibles, some ARM like the Pi and Apple Silicon, RISC-V and some old PowerPC.
This page will cover enough to be able to write the downloaded image to your preferred media, to run a LiveUSB, LiveCD or LiveDVD on your office/home PC (Live meaning you can test without changing your existing setup) and, ultimately, to use it.
Intel / AMD PC hardware support mostly covers the years 2000 to 2024. At the moment, AROS is '''not''' recommended to be '''installed''' on a working vital data holding machine. Instead, writing to and booting from a '''USB stick''' could be a much better option.
AROS is an hobby OS and can co-exist with Windows(TM), MacOSX(TM), Android(TM) or Linux(TM) and act as an alternative.
Unfortunately, Aros has few developers so upgrades and improvements can take [https://sourceforge.net/p/aros/mailman/aros-cvs/ time to appear].
AROS core is now [http://en.wikibooks.org/wiki/Aros/Developer/IncompleteAPIs ~80%] finished and is usable, so keep in mind that the software is still considered ALPHA/BETA and in constant development. Currently AROS is fun to play with on a curiosity level, but it is also interesting to program. AROS has some multimedia features and has internet access.
Most importantly, use AROS to its maximum potential as it stands now, find ways to have fun with it and share your experiences.
Good Sites to visit
: [https://www.arosworld.org/home.php Aros World User forum]
: [https://arosnews.github.io/ AROS News]
: [https://www.facebook.com/ArosWorkshop/ Aros Workshop],
: [https://www.osnews.com/topic/amiga-aros/ OSNews]
: [https://www.reddit.com/r/aros/ Reddit]
: [https://archives.arosworld.org Aros Archives]
: [https://aminet.net/ Aminet]
: [http://www.amiga-news.de/en/ English translation of German site]
: [https://aros.sourceforge.io AROS] with [https://aros.sourceforge.io/download.html ABIv1 downloads]
: [https://github.com/aros-development-team/AROS Aros ABIv1 Codebase]
: [https://github.com/aros-development-team/AROS/issues register ABIv1 issues] and [https://sourceforge.net/p/aros/bugs/ old defunct bugs notification site]
: [https://sites.google.com/view/arosone Aros One x86, x64]
: [https://tinyarosdistro.flazio.com/ Tiny Aros x86 and x64]
: [https://arosnews.github.io/aros-portable/ AROS portable USB3 stick images of hosted Aros One x86 and x64 on debian]
: [http://vmwaros.blogspot.com Icaros Desktop x86 now on sabbatical, very old edition]
: [https://sites.google.com/site/arosaspireone AspireOS, of the netbook Aspire One, very old edition]
: [https://github.com/deadwood2 Deadwood's builds], [https://www.axrt.org/download/aros/v11/ v11 64bit PC builds], [https://axrt.org/downloads-aros Updated i386 32bit PC builds],
: [https://github.com/ezrec Ezrec x86 m68k mirror of old svn version]
: [http://arosalive.blogspot.co.uk/p/10-basic-aros-how-tos-tutorials.html Basic How To guides]
: [http://arosgamer.blogspot.co.uk/ AROS Playground], [http://thewetmachine.net/tag/aros/ Jess Wet Machine], [https://aroshacking.wordpress.com/ Jon Robertson's AROS Experiences and FPC Free Pascal], [],
:[http://www.apollo-accelerators.com/ Apollo Accelerators m68k], [http://www.amigablogs.net/ Amiga Blogs], [http://blog.a-eon.biz/blog/ Trevor Dickinson blog],
: [https://forum.amiga.org/ Amiga OS AOS 3.x forum]
: [http://eab.abime.net/ EAB Amiga]
: [http://www.amigaworld.net/ AmigaWorld]
: [http://www.ppa.pl/ Polish Amiga Like News]
: [http://www.apollo-core.com/ Apollo Forum]
: [https://amigaalive.blogspot.com/ AmigaAlive]
: [https://www.amigalove.com/software Disk Mags]
: [https://amigachristmastree.ultimateamiga.com/ Xmas Amiga Game Jam]
: [https://www.reddit.com/r/amiga/ Amiga]
== Distributions aka Distros ==
For end users there are distributions (ready made with selected apps aiming to be easy to use), mostly created and maintained by one person in their own workflow/style. They reuse the nightly boot compiles to suit their needs and possibly other end users. You are free to create your own if required.
* For native 64bit Intel/AMD: [https://sites.google.com/view/arosone Aros One x64], [https://tinyarosdistro.flazio.com/ Tiny Aros],
* For native 32bit Intel/AMD which will run on 64bit machines: [https://sites.google.com/view/arosone Aros One x86], [https://www.tinyaros.it/ Tiny Aros],
* For native 68k [https://sites.google.com/view/arosone Aros One m68k], [http://www.aros-platform.de/ AROS Vision],
'''Please, keep in mind that the distros listed above use a different ABI (abi v11) , which is NOT binary compatible with the official ABI V1.'''
* For hosted Linux usb drive image [https://arosnews.github.io/aros-portable/ x64 Debian hosted version of Aros One],
* For hosted ARM there is [https://github.com/jonx/AROS-AArch64/releases alpha for Apple Silicon] and [https://aros.sourceforge.io/nightly1.html RaspberryPi Pi3, Pi4, Pi400, Pi5, 500+ raspi-aarch64-system native 64bit]
AROS was originally developed on Linux but can run on an Intel-based Linux distro as an app. As time has gone on, it can be run as an app on many more operating systems (Windows, FreeBSD, Linux and limited on MacOS). This may sound strange: an OS running on top of another OS.
Basically, this is to take advantage of drivers (audio, internet, graphics, etc.) and compiler environments, in the existing OS, with which people may be already familiar. The term we use for what AROS does is "Hosted".
AROS Native is the term coined to describe AROS being run without any OS underneath it. It runs alone just like AmigaOS(TM) did. As this version does not benefit from "Hosted" drivers, dedicated ones have to be ported/written. Hence the smaller range of supported hardware / peripherals. We have other pages highlighting this support
AROS is open source so basically everyone can take part. The source is public on github and there are new commits most days. AROS is automatically compiled daily, result are the nightly builds hosted on Sourceforge. The nightly builds are only used for testing changes, testing software and the starting point for distribution maintainers or even your own distribution. They are very basic, miss some functionality and apps like web browsers and generic general appearance which can be changed.
* The [https://sourceforge.net/projects/aros/files/nightly2/ Nightly2], [http://aros.sourceforge.net/download.php nightly builds File Release Service] or [http://aros.sourceforge.net/downloads/ Sourceforge Project Web builds] are made automatically every night directly from the Github and in the past, SVN (Subversion) tree and contain the latest code for the AROS operating system. It should be noted that the builds have not been tested in any way and can be horribly broken but usually are not.
*ABIv1 standard for most nightly builds, it is where the most work is done by developers
*ABIv11 offspring aka fork of 64bit PC ABIv1 i.e. another PC 64bit build
*ABIv0 standard for PC 32bit intel / amd PC distributions for historic reasons
==Media==
AROS media tends to boot in this tier list of media types, first internal HDD SSD, CD DVD drive, and finally usb drive (last two can depend on bios boot order)
* USB .VHD
[https://sites.google.com/view/arosone Aros One x86 and x64], with md5 below
<pre>
0a656d53a9c902e9934000d8392e30ec *ArosOne-USB-1.3-64Bit.zip
7dd7119ab3e56d75ee852c137226b4d7 *ArosOne-USB-v1.2-x86_64-v11.zip
cf906eeaad4a83b3520b1896bdc6b0d3 *ArosOne-USB-v1.1-x86_64-v11.zip
e2eb8fe8cfd61c567b0152a61cf85251 *ArosOne-x86-v2.8-USB-IMG.zip
559909c75c2f56472c74267a7d075355 *ArosOne-x86-v2.7-USB-IMG.zip
93da5898508c1a8c05bb8991ab7bd117 *AROS One Image-USB-2.4.zip
59fcabd7090e47f12d54f7eb78cf0f45 *ArosOne-x86-v2.2-USB-Image.zip
24fb8de726ae8fc5fe5bac6d30f03dc5 ArosOne-x86-v2.0-USB-Image.zip
f3d725e990072edce633b59747911b6b ArosOne-x86-v1.8-USB-IMG.zip
e089a24ae310e92fcc407a0125602ce8 Aros-One x86-IMG-USB-v1.6.zip
</pre>
[https://tinyaros.flazio.com/ Tiny AROS]
22bc993625b7c75b17263c0cc7e7baaa *Tiny Aros_copy.vhd (March 2024)
There is usually a vhd image inside the zip that can be written to USB sticks which is so much faster than the old ISO written to physical CD DVD method. This .vhd can be written to an USB stick / ssd with these pieces of software below but it will erase the previous contents from the usb
Windows - [https://www.raspberrypi.com/software/ RPi Raspberry Imager, use custom and see all files], [https://hddguru.com/software/HDD-Raw-Copy-Tool/ HDD-Raw-Copy-Tool], [https://rufus.ie/ Rufus up to version 3.20 may work with VirtualBox HD vhd images with Win7 but not some Rufus 4.x versions], [https://etcher.balena.io/ Balena Etcher but may spy on you],
Linux - [https://www.raspberrypi.com/software/ Raspberry Imager Ubuntu], Suse Image / Multi writer, dd,
Mac -
* Virtual Machine .ISO or CDs DVDs
The native iso images are currently not compatible with Ventoy, Yumi, MultiBootUSB, Easy2Boot E2B, or similar
<pre>
617a905b1665128c5e05f94dcc48e7f1 *AROS-One-v1.3-64Bit-v11.zip
11c8a147fcad7ecf52ae3a43e1934b69 *ArosOne-DVD-v1.2-x86_64-v11.zip
f93053d3b9ccf304d7e6ac3389e1987b *ArosOne-DVD-v1.1-x86_64-v11.zip
86d808a40dc7be389a758799a9b4f595 *ArosOne-x86-v2.0-ISO-DVD.zip
f1fc8599ef6a39e5df394e0f41d55526 *AROS-One-x86-ISO-DVD-v1.6.zip
</pre>
You can use a virtual emulator like VirtualBox, VMWare to mount the iso image which can then be used to boot and/or install to USB.
No current software can write an AROS ISO to a Pendrive. The author of ‘Rufus’ (who used an Amiga 500 as a child) once tried, but when he saw the system composition, he said he was unable to do it.
The solution is to boot the ISO from a VM (WMware, VBox), then install the AROS build on the Pendrive, which will eventually become a Live Pendrive that can be booted on a PC.
The only precaution is that in some cases it is necessary to thoroughly clean the Pendrive of any partitions and remove any bootloader that is not AROS. The Pendrive must remain raw without any partitions.
You can clean the USB stick on a PC with a program that manages hard disks. You need to do a partition wipe. On some USB sticks, you can clean it with InstallAROS.
For some USB pendrives, please use a reputable partition editor to remove any and all partitions from a usb pendrive as HDToolbox cannot do this task sometimes with a wipe all option.
Previously the only installation option was CD-RW or DVD-RW, since the whole system can be burnt onto a single disk and can be reused when the next version is released. Good branded discs like Taiyo Yuden (later JVC) or Verbatim should be used to reduce frustration later. The days for this media is gone but kept here for information
Since nobody currently sells AROS on any other media, you will need access to a CD/DVD burner to create the installation disk yourself. After it is on a CD or DVD, then access and writing to USB pendrives becomes available (this should be viewed as an outdated or last resort alternative method now), as well as using good USB manufacturers like Sandisk, Kingston, etc. rather than some other no-names.
Try burning it to a CD-RW or DVD-RW using your CD/DVD burning program (most burning software have a burn iso option). The ideal writing speed is 2x or 4x, higher speeds can give errors and problems. Check the writing integrity of your CD or DVD if your software has an option to do so before going any further.
Standalone portable usb cd dvd drives do not boot physical burnt discs, please use an internal ide sata drive instead.
* SD-card
For [https://aros.sourceforge.io/nightly1.html ARM Pi Aros 64bit], copy the files onto a FAT32 formatted micro SD card.
==Booting==
The LiveUSB, and in the past LiveCD LiveDVD, is designed to trial (test drive) various operating systems without having to install them to your working system.
Since 2011, UEFI was introduced to replace the original PC BIOS which made booting media more confusing. Some changes in the UEFI/bios may be needed
*go into the bios using esc, f2 or f? and disable the Security -> Secure Boot and maybe apply option for Legacy IDE mode
*you may have to press F9, F10 or F12 or p on boot up to present a device boot options like USB or CD/DVD
*disable the Fast Boot config so it would recognize portable DVD-drive and changed the Boot-sequence
Secure boot was introduced by Microsoft and later consortium, control what operating systems work with Secure Boot via shims.
For Aros, it is best to disable and save the turn off change to Secure Boot (if you dual boot with Windows this will cause issues with further Window boots)
For the best experience, it is advised to install to another SSD than the one Windows resides on.
The grub part of the boot should be fully automatic, and you should see a multiple choice graphic card screen after 10 seconds for USB or 40 seconds CDs and DVDs.
If boot does not occur within a minute, please reboot and choose the VGA boot option as it relays a message stream so you can see where the issue lies.
After the grub graphics choice, AROS takes over the booting and any issues can arise here
If possible please use a branded usb pen drive as most of the time when we get reports of "crashes right after grub boot selection" it is mostly due to the recorded pendrive as they are made, notoriously on a will it work / will it fail nature, every time it is used.
<pre>
So one usb drive written may stop at a System halted. Reset the machine.
Or another pendrive will show give errors Smart Filesystem request - Volume 'Aros Live Drive' (DU0: usbscsi.device unit 0) There was an error while accessing this volume:
Or if a FAT32 partition present - FAT filesystem - Device USBSCSI0P1 has a read error on block xxxxxxxx -
</pre>
Sadly, no drive even branded are resistant or totally reliable, so the only solution is to try another pendrive, and possibly to repeat, until no errors.
It will give an indication on how reliable the usb drive could be.
=====Advice for various machines=====
Some of the stages involved and shown on the display in a typical AROS boot start up
<pre>
[MultiLoader]
[ELF Loader]
[Boot]
[HPET]
[Kernel:ACPI]
[Kernel:APIC-IA32]
[Kernel:SMP APIC]
[HiddStorage]
ACPI: ????
ACPI Error
[ACPI]AcpiOs????
[BattClock] Got RTC century offset 0x32 from ACPI
[PCI] Scanning bus ?
[AHCI] Sata
[Vesa] only if vesa is chosen as graphics option
[ATA] detect hd & cd drives
[ATA0?] ata-identity
[packet] fat.handler be.handler, etc.
[DOS]
[Storage:Bus]
[Storage:Controller]
[MSS] USB setup
[ehciInit] Port ? maps to controller ?
[I2C]
[ATI]
[drm] nouveau
[AROSTCP] if you have network driver prefs set up to start when booting
</pre>
; If boot fails, please give us some indication (pictures or videos) where the boot stops and the message(s) on screen.
AROS's native SATA/AHCI driver doesn't always work. If you get errors related to ahci.device, try disabling it. At your chosen boot entry in the GRUB menu, Press E, scroll down to the ahci.device entry, and add a # or ; at the start of that line or delete it with Ctrl-K. Then press Ctrl-X or F10 to boot.
If your disk isn't accessible at all with this change, you might need to change the SATA controller to IDE legacy mode in the BIOS: however, making this change will likely cause problems booting Windows on the same machine (if it's already installed). To disable ahci.device permanently, edit the text file "SYS:Arch/pc/grub/grub.cfg", and remove the ahci.device line from all boot entries you intend to use.
SATA AHCI Timeout while waiting for device to complete operations with BIOS SATA entry set to AHCI mode stops at "waiting for bootable media" screen, changing BIOS SATA setting back to IDE mode may allow it to continue booting
The ATA driver doesn't always work. If you get errors related to ata.device, try using the alternative in sys:devs/alt which is an older version. Press E when your chosen boot entry is highlighted in the GRUB menu, scroll down to the ata.device entry, and change it to read "module /Devs/Alt/ata.device". Then press Ctrl-X to boot. To make this change permanent, edit the text file "SYS:Arch/pc/grub/grub.cfg", and change the path to ata.device in all boot entries you intend to use.
Further options (removing the " ") to add to the GRUB menus to disable certain other components for debugging:
<pre>
Disable AHCI "AHCI=disable"
Disable NVME "NVME=disable"
Disable ATA: "ATA=disable"
Disable ATA: "ATA=nopci,nolegacy"
ATA safe mode: "ATA=nodma,32bit"
Disable IDE from SATA: "ATA=32bit,nosata2pata"
VIA / SIS with cdrom read io errors "ATA=nodma,nopoll"
noacpi all [PCI] devices to be invisible to AROS. disk drives work but network, sound won't
acpi=strict if there are issues with sound after boot
noioapic alternative to no acpi
Set AHCI "AHCI=force150/force300/force600"
Disable AHCI/SATA: comment out with a # ; or remove ahci.device line with Ctrl-K
Disable USB: comment out # ; or remove pciusb.device and poseidon.library lines with Ctrl-K
Disable native graphics: "nomonitors"
USB3 "USB=xhci"
</pre>
Other useful grub command line options - nomonitors, noacpi, vesahack, nopoll
Press Ctrl and X together (or F10) to exit and boot with the new options. Just experiment with different variations until successful. Those working options will need to be reused with every reboot of AROS until you can edit the grub.cfg and make it permanent i.e. install to hard disk or USB.
* If you use VESA mode, you can see the debug log if you add 'vesahack' to the command line. This will set up split-screen mode. In the upper half you'll see AROS screen, in the bottom - debug log.
* ACPI ie. PCI hardware - If you get crashes at early boot, try adding 'NOACPI' to the command line
If you're having boot issues and have a null modem cable and a spare pc, a boot log is always useful. Edit your grub line to include debug=serial but would try with an with sysdebug=all in the line later as it can cause issues booting on machines with sysdebug=all enabled (corrupts the cpu initialization).
However, if you feel you have found a genuine bug/fault in AROS that needs attention, please use the [http://sourceforge.net/tracker/?atid=439463&group_id=43586&func=browse bug submission form] to record as much information about what happened, why, and what hardware etc. you have so that people may try to assist you
For Virtual machines VMWare VirtualBox, etc., attach and press play to start the ISO image
If booting hasn't worked then it could be down to Bios/UEFI settings
=====nvme.device=====
Since 2018, nvme drives are standard on most machines
The requirement is that a PC can boot with legacy mode/BIOS at the moment - Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
This is still in testing and its' use should not be on or near precious own data
=====AHCI=====
Starting taking over since 2011 on a lot of machines
* Check that UEFI (replacement for PC BIOS) has options set to remove UEFI SecureBoot option and apply CSM
* SATA drive is set for Legacy or a mixture AHCI/IDE and not AHCI
AHCI sata can be very difficult to get working
Most Windows installs are already set to AHCI sata, changing this to a legacy IDE mode setting can help but please check if Windows will still boot. Some hardware like Lenovo laptops do not always like being set in legacy mode so only use as a last resort and aware of issues that can be caused.
Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
With a 16C/32T chip machine, disable SMT and it should boot.
=====ata.device for old BIOS's =====
Pre 2010 this was the de facto standard method of providing settings to the computer at a lower level
Some adjustments to the BIOS setup options are necessary (usually by pressing a key like DEL, F1, F2, F12 or ESC, p on the very early boot up of the computer).
*Adjust booting options like moving USB hdd, CDROM higher as it is quite often disabled or placed lower by default, i.e. USB hdd, CD/DVD are placed at the top above the hard drive. Try looking here [http://www.windowsreinstall.com/articles/bios/ Windows] or [http://www.hiren.info/pages/bios-boot-cdrom Bios] or [http://www.wikihow.com/Set-Bios-to-Boot-from-a-CD-ROM Boot] or web search "BIOS BOOT CDROM"
* At the '''SAME''' time, check if the SATA/AHCI option is set to Emulate or IDE Legacy, though this can have '''issues''' with any OS already on the hard disk. If in doubt, do nothing and seek advice.
* check that under BIOS settings you '''DO NOT''' have plug&play OS selected as Aros at this point is unable to route interrupts on its own and needs the BIOS to do that.
'''Save''' options changed at the end.
PCITool can show if the motherboard chipset is in IDE mode.
Class = 0x01 means STORAGE, Subclass = 0x01 means IDE. Also ProductID 0x3a20 resolves to non-AHCI mode in Intel ICH10 documentation.
==Installing==
We have a separate section [https://en.wikibooks.org/wiki/Aros/Platforms/x86_installing here]
We have a specific section for each CPU platform under the Specific platforms in the NavBar navigation bar on the right hand side menu
error code (-6) when using the ahci.device (has writing to disk problem but not reading) is enabled. change this line in your grub and reboot
<pre>
#module /Devs/ahci.device << disable
module /Devs/Alt/ata.device << add this line instead
</pre>
==File structure overview==
AROS' directory structure is mostly identical to AmigaOS directory structure, with some additions.
AROS: or SYS: also known as DH0: (i.e. the drive partition with AROS system) has the following simplified list of the main drawers (Amigas term for directories/folders).
{| class="wikitable"
|boot:
| grub bootloader
|----
|C:
| small apps, where AROS looks first for applications/games but will look at Tools, System afterwards
|----
|Classes:
| .class as well as datatypes
|----
|Devs:
| .device .resource and in their own drawers (folders) .audio, .hidd, network, graphics
|----
|L:
| where .handler files go
|----
|Libs:
| where .library files go
|----
|Locale:
| where help guide txt readme files go
|----
|Prefs:
| applications that adjust or setup AROS functions and capabilities
|----
|S:
| startup scripts (for the aros boot process '''not''' grub) are stored here
|----
|Storage:
| place to keep old or alternative device drivers
|----
|System:
| applications associated with AROS operating system
|----
|Tools:
| extra applications
|----
|Utilities:
| extra applications
|----
|WBStartup:
| copy applications here to autostart with needed icons, drawers, data etc
|----
|}
See [[Aros/User/DOS#Drives.2C_Files.2C_Assigns.2C_Directories|DOS manual: Drives, Files, Assigns, Directories]]
=== Filesystem ===
Whilst the kernel is the heart, the filesystem is the blood of the system they are split into two categories (only a few are supported)
<pre>
Journalling - SFS PFS3 but also NTFS ZFS XFS ext4
Non-journaling - FFS FAT32(VFAT) but also exFAT BtrFS ext2
</pre>
Filesystem options for AROS to install
* SFS default
* Professional File System PFS3 [http://eab.abime.net/showthread.php?t=52234&highlight=pfs3+free&page=13 only on motorola 68k at the moment]
* FFS very old now but left in for legacy usage
Other [https://archives.arosworld.org/index.php?function=browse&cat=driver/filesystem filesystems] for storage purposes
* FAT32 favorite as most OSs support
* NTFS (can lock AROS)
* exFAT
The only filesystems that really NEED defragging (i.e. disk tidy up) are from Microsoft(TM) - exFAT/VFAT/NTFS
*SFS tries to do exactly the same thing, but in certain cases it doesn't do as well as PFS. But you can defrag SFS
*PFS *minimises* the amount of fragmentation, but does not automatically defrags as it saves files to the drive
The setup of the below filesystems is usually done by the distro maintainer but if not....
<pre>
Copy L/exfat-handler L:
DOSDriver or Mountlist entry for an exFAT partition make sure that the FileSystem and Handler are set as follows:
FileSystem = exfat-handler
DosType = 0x46415458
</pre>
<pre>
Copy L/ntfs3g-handler L:
DOSDriver or Mountlist entry for an NTFS partition make sure that the FileSystem and Handler are set as follows:
FileSystem = ntfs3g-handler
DosType = 0x4e544653
Also to make a read-only mount you can set:
Control = ro
</pre>
The Smart File System (SFS) is a journaling filesystem used on Amiga computers and AmigaOS-derived operating systems. It is designed for performance, scalability and integrity, offering improvements over standard Amiga filesystems as well as some special or unique features.
SFS is written in C and was originally created and released as freeware in 1998 by John Hendrikx. After the original author left the Amiga scene in 2000, the source code to SFS was released and its development continued by Ralph Schmidt in MorphOS.
Its development has now forked; as well as the original Amiga version, there are now versions for MorphOS, AROS, AmigaOS 3, and a version for AmigaOS 4, which have different feature sets but remain compatible to each other. Versions for AROS, AmigaOS and MorphOS are based on different branches.
In addition, there is a driver for Linux to read Amiga SFS volumes, GRUB natively supports it and there are free drivers to use it from UEFI. The Linux version is [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ independent code].
SFS (Smart File System) partially defragments itself while the filesystem is in use. The defragmentation process is almost completely stateless
AROS SFS version has a 120GB partition size limit on hard disks and DVDs current 4gig size limit.
The sources for the MorphOS 64-bit version of SFS were available but no porting to AROS has happened so far due to endian issues, etc.
SFS Tools
* GUI - arSFSDoctor,
* CLI - sfscheck , [http://www.portacall.org/ sfsundelete], sfsformat, setcache hits a usability ceiling around the 10GB / 100,000 file mark,
sfscheck dh0: seek purge fraglist defragment
If there are two simultaneous file writes in progress and you reboot machine (or it locks up or crashes) you may end up with a corrupted filesystem. Although arSFSDoctor may help, you might have to copy the files to another partition, format the partition with the errors on and copy the files back.
PFS / SFS are way more advanced and much much faster than the FFS. FFS is supported for legacy reasons only.
The Professional File System (PFS) is a filesystem originally developed commercially for the Amiga and now distributed on Aminet with a 4-clause BSD license. It is a compatible successor of AmiFileSafe (AFS), with an emphasis on added reliability and speed compared to standard Amiga filesystems. It also features multi-user abilities like the older MuFS.
PFS has so many advantages including the important things, speed, the ability to recover all deleted files even simply same name by typing the command ". Deldir" convenient if done in Directory Opus, virtually deleted files are copied normally as if they had never been deleted, other convenience is to not ever invalidate the filesystem, just put it on top of the startup-sequence command "diskvalid", which automatically corrects any irregularities in the system startup; PFS also provides a device for floppy which makes them very fast and takes advantage of the full capacity of the floppy including the area dedicated to the bootloader.
The device is split into two main areas. At the beginning of the device is the metadata section, which consists of a root block, and a generic array of blocks that can be allocated to store metadata. The rest of the device is another contiguous generic array of blocks that can be allocated to store data. The metadata section usually uses a few percent of the device, depending on the size of the device.
The metadata is stored as a tree of single blocks in the metadata section. The entire directory structure is recorded in the metadata, so the data section purely contains data from files. The metadata describes the location of data in files with extents of blocks, which makes the metadata quite compact.
When a metadata update occurs, the system looks at the block containing the metadata to be changed, and copies it to a newly allocated block from the metadata section, with the change made, then it recursively changes the metadata in the block that points to that block in the same way. This way, eventually the root block needs to be changed, which causes the atomic metadata update.
The filesystem is reasonably good at keeping files unfragmented, although there is a defragmentation tool available which will work on an online filesystem ie whilst being used.
It was the first filesystem to introduce the concept of the Recycle Bin natively at filesystem-level to the Amiga, holding the last few deleted files in a hidden directory on the disk root.
PFS version 5.3 was developed in C and a small portion of assembly code by Michiel Pelt. There are endian issues to be overcome and adapting the small amount of m68k to C before use on intel based machines, etc.
Autoupdate of files in a directory is already implemented in Wanderer, but not all file systems handle dos.library/StartNotify() in its full extent. It seems to work correctly in Ram Disk (thanks to AmberRAM handler), and it also works on SFS formatted devices. Other file systems might not yet have it implemented correctly though.
The PC equivalent of the Amiga's RDB is the master boot record (MBR).
===Installing Applications===
The typical means to install applications under AROS/AmigaOS involves simply copying/extracting the archive (.zip .lha .rar .tar.gz) file containing the applications files to your own desired location i.e. drawer/folder. Once extracted, launching it by double clicking on an icon (recommended) or using the shell (alternative). Generally, this is on a separate partition from your AROS system files, however in reality it can be any location - including RAM: if you don't want it staying around too long especially when you switch off.
At some time in the future it may be desirable for AROS to have a package-manager like subsystem able to retrieve information online about packages available for AROS and whether they update anything you currently have installed, however at the moment no such ability exists.
===User Data files===
AmigaOS has no notion of a default location to store user data files, and presently neither does AROS - though it may be desirable at some time to provide a common start location.
Some people, have extra small FAT32 partition(s) using HDToolbox, and not Qparted, to store data especially if a reinstall is ever needed. And then setup the usual Sys: (DH0:) and maybe Work: (DH1:) / Live USB (DU0:) and maybe Briefcase (DU1:) partitions.
===User Environment configuration files===
AmigaOS/AROS stores persistent system configuration data in directory assigned to ENVARC:. This, by default, points to SYS:Prefs/EnvArc.
During boot a copy is made to another assign, ENV:, which is for runtime usage. Changes to the files here will not survive a reboot.
Setting the env variables is generally done by applications themselves, or when necessary by the user using the SetEnv command. SetEnv has a SAVE switch to force the persistent copy in ENVARC: to be written also for when you are sure the change should be permanent.
Under the standard installation of AmigaOS style OSs, ENVARC: is copied to ENV: upon startup, which, if you have a hard drive installation, is in RAM:, hence, ENV: ends up being RAM:Env.
ENVARC: is the Environment Archive, which is the permanent copy of ENV:, which is the Environment. It's roughly like the Registry in Windoze.
Most programs do (and all should) store their settings in ENVARC: somewhere, and load them from ENV:. The effect of this can be seen in the Preference editors. If you Save your preferences, they go in ENVARC: and ENV:. If you click Use, they only go in ENV:. If you reboot, normally, anything saved to ENV: is lost, and is replaced with a copy of what is in ENVARC:.
you can set the default public screen for any tool started from a cli with the PUBSCREEN variable. So open the pubscreen, set PUBSCREEN to the name and start newcli for example, then the new cli window (and all following windows opened from that window) will appear on that public screen.
===Drivers===
For certain hardware, e.g audio, networking and , there is no auto setup. Just like the original Amiga OS.
For audio, use AHI in the Prefs folder to set Music and at least Unit 0 with the appropriate driver and press Save. For ethernet and wifi, please use SYS:Prefs/Network
All hardware support is placed in the Devs drawer (folder/directory). The network drivers <something.device> go in the Networks sub-drawer. Audio drivers <something.audio> are put in the AHI sub-drawer. Graphics drivers <something.hidd> are put in the Drivers sub-drawer.
==Configuring==
AROS has mainly decided on a MUI-like requester&menu clone called Zune so changing the background, icons, font, menus can be done with SYS:Prefs/Zune
AROS has several desktop GUI front ends like
* DOpus5 Magellan II, Wanderer and Scalos (medium)
* AROS Workbench, Workbook (smaller)
File / Directory managers like Dopus4, MCAmiga,
App Launch Shortcuts like FKey, BoingIconBar, right mouse click on magellan, wanderer desktop, Amistart, etc.
General usability decisions - Prefs/IControl, Prefs/Locale, Prefs/Input, Prefs/Fonts,
Select an icon with left mouse button and then right click the mouse button and selecting Icon -> Information gains access to the tooltypes tab where information can be edited
CLI in icon's tooltypes means 'run it as if it was run from shell'
If, on the other hand, the WB parameter (or no parameter) is present in Tooltypes, Wanderer will execute the binary and, if provided, the options included in Tooltypes.
WBxCLI is very useful for adding options to DOS Commands.
Important: AROS has a different way of managing icons. If you have an executable file, you will never be able to add a project icon. AROS will automatically recognise that it is an executable file and will transform the icon into a tool icon.
Icons are typically now .png pictures renamed as .info e.g. so Office application name would have a Office.png renamed as Office.info or MyApp.png as MyApp.info, etc.
Leave Out menu option to leave app icon on desktop
To select multiple icons and save their positions, click on the first icon and after while you hold the Shift key down select further icons and don't release it before SnapShot is finished. You can also select a whole group of icons by pressing the LMB at the top left of the icons and while keeping the LMB down moving the power towards the bottom right. A expanding bounding box will appear and all the icons within it will be selected.
Clean Up menu option (right mouse button -> Icons) rearranges icons in a drawer or disk window into a neater condition. To use, open the window to rearrange and select Clean Up. To keep the icons in the new positions, select all the icons (shift key or mouse selection) and select 'Snapshot' and then Window and then again with All.
In DOpus5, Scalos, wanderer, most files have an icon file associated with it. To change the default tool, select Icon menu, Information, and change the default tool string. For example, you could use Multiview, Editor and so on for most text, graphics and some sound files as long as the appropriate Datatype classes are installed. For scripts, set the tool to C:IconX
We have new Icon edit tools in progress but if you need to...
C:Join Image1.png Image2.png TO MyFile.info
is enough to make a dual state icon from two png images. You can then use Wanderer's menu Icon/Information on it to edit its fields and tooltypes.
[https://archives.arosworld.org/index.php?function=browse&cat=graphics/icon AISS toolbar images] unpack unarc them into RAM: and copy Images directory to SYS:Prefs/Presets/ AISS icons are looked for in PROGDIR:, PROGDIR:Images, SYS:Prefs/Presets/Images and then in TBImages: according to Open Amiga guidelines.
there is Demos/iconscale which could be launched from S:User-Startup with two arguments, telling it the horizontal and vertical size. IE something like
Demos/iconscale 40 40
It will shrink icons... not sure if it will be very nice though. it doesn't work for the icons on the main desktop.
there is an option to scale an icon to a bounding box afair, try iconsize followed by two numbers, like:
iconsize 32 32
Is there any way in AROS to change an icon type from Project to Tool or vice versa?
Either the SIT option of [ ProcessIcon], or the TYPE option of HandleInfo (not sure if this one works at all, please test with care).
processicon sys:pathoftheicon SIT=Project
SIT Set type of ICON. Allowed types are: "Disk", "Drawer", "Tool", "Project", "Garbage", "Device", "Kick" and "AppIcon".
Btw, are your icons, the #?.info files, writable, is the W flag set ?
'''Decoration''' is Aros' way to provides a way to hide the old Workbench 3.1 style of windows and screens. In Prefs/Appearance some decorative theming elements need work
Themes - SYS:Prefs -> Appearance
The default content of Prefs/Env-Archive/SYS/themes.var should be "themes:ice" but can be changed via the Appearance prefs, please do NOT click the Use button. Its useless. As you know, it will ask for the theme volume. Just pick the theme you want, click on Save, then reboot.
* Decoration is on. Any time trying to change theme, you get: "Please insert volume Theme: in any drive"?
You could check if you find SYS:System/Themes or if it is missing. Then you could open startup-sequence which you can find in drawer "S". There should be a line:
Assign THEMES: SYS:SYSTEM/THEMES >Nil:
This does the trick.
Open a shell and run:
Assign THEMES: SYS:SYSTEM/THEMES
Than start the Theme prefs again... this should work
* The theme is the only thing that could slow the system a bit, but it's not that performance impacting on most uses, and you can switch it off completely. Remove C:Decoration from the bottom of the file sys:s/startup-sequence.
In each theme directory is
*Env-Archive -> Zune -> global.prefs
*images -> Gadgets -> 20x20 pngs for Down etc
*menu -AmigaKey - Background - Checkmark - SubMenu and config
*system - Arrowdown, Arrowleft, Arrowright, Arrowup, etc
There is an [https://archives.arosworld.org/index.php?function=browse&cat=graphics/theme ALua/Zulu script] built for faster Wanderer skin management. You can modify config files, install new (wdz format/zipped skin files) and delete skins via the Theme Manager. This has not been updated in a long time and may not work.
Certain features are added if from Tools/Commodities like Blanker screensaver, ClickToFront and DepthMenu with .info icons are selected and dragged to /WBStartup folder
Most apps can be autostarted by copying into SYS:WBStartup directory folder
e.g. WeatherBar.zip can be downloaded, unzip and the contents of the zip copied to wbstartup folder
ClicktoFront and .info to SYS:WBStartup so always be activated when turning on the computer
or add a text line to user-startup is SYS:S (scripts version of wbstartup)
e.g. standard Amiga / AROS does not allow clicking of background windows to come to the front to make it easy to get to the window you need but it has the ability if these apps are copied again to WBStartUp or are added to SYS:S/user-startup script
run QUIET sys:Tools/Commodities/ClickToFront >Nil:
run QUIET sys:Tools/Commodities/DepthMenu >Nil:
run QUIET sys:Tools/Commodities/Blanker seconds=300 >Nil:
Exchange controls Commodities and can be opened with alt, ctrl, h
*AltKeyQ uses left Alt key to add strange letters
*AutoPoint
*Blanker screensaver
*ClickToFront allows windows to be easily brought to the front
*DepthMenu adds menu to select window easily
*NoCapsKey
*Opaque
*FKey - Although there are heaps of docks, menus and other launcher programs on the Amiga like OSs, FKey has got to be one of the quickest once learnt ways to launch programs, and it comes with the OS. In SYS:Tools/Commodities, the FKey commodity (Ctrl Alt F) allows you to make actions assigned to some combinations of keys
<pre>
ALT TAB Cycle Windows
Cycle Screens
Enlarge Window
Shrink Window
Toggle Window Size
Insert Text
Run Program
Run Arexx Script
</pre>
e.g.
<pre>
LAmiga F1 = Avail Flush
LAmiga F2 = Open Prefs
LAmiga F3 = Finder
Alt Tab = Cycle Windows
LAmiga Tab or M = Cycle Screens
Alt Up arrow = Enlarge Window
Alt Down arrow = Shrink Window
Alt Home = Toggle Window Size
= Insert Text
LAmiga e = Run Program
= Run Arexx Script
</pre>
If your FKey GUI pops up when you start your Workbench up and you don't want it to, click once on the icon, go to the Icons-Information in the menu and make sure it has the tooltype set "CX_POPUP=NO".
Now let's launch it and assign the locale switching. After you double-click on FKey icon, launch the Exchange, choose the FKey from list and click the Show button. This will invoke the FKey window. You can see the ALT TAB in list assigned to window switching. Now enter the first key combination, say, ALT Z and go to the right panel. Choose Launch the program from pulldown menu and enter SYS:Prefs/Input as an argument. Append the USE switch and english preset name to the string as shown:
SYS:Prefs/Input USE SYS:Prefs/Presets/english
Click on the New Button to add the another combination. Now set the combination for your locale as shown above, replacing English name with your preset name. Click New button again and then Save Settings. Now you can use defined combinations to switch the layouts.
There is a system wide ARexx script capability (based on regina) that can manage many file manipulation task(s) but this would work only with those program that support [https://en.wikibooks.org/wiki/Aros/Developer/Docs/Rexx ARexx] like
*Desktop - DOpus5, Scalos
*Dock - FKey,
*Files - Multiview, DOpus4,
*Internet Apps - Odyssey, WookieChat,
*General Apps -
the shell can be modified with escape strings but not needed in most cases
Common Keyboard Shortcuts
<pre>
RAlt Right Alt Key
LAlt Left Alt Key
RWinKey Right Windows Key
LWinKey Left Windows Key
RAmiga Right Amiga Key (if one)
LAmiga Left Amiga Key (if one)
</pre>
;Bootup Options
:Spacebar during boot, enters the bootmenu which allows a boot without startup sequence, etc
;Left Click
:LAmiga = LWinKey = F11
;Right Click
:RAmiga = Help = F12
;Mark
:RAmiga and B
;Cut
:RAmiga and X
;Copy
:RAmiga and C
;Paste
:RAmiga and V
;Search
:RAmiga and S
;Mouse Movement
LAmiga and together with arrow keys - shift as well at the same time as well to move faster
;Mouse Selection
LAmiga and LAlt to select
;Screen Switching
LAmiga and M or N
;HELP key
Can sometimes be mapped to F11 but can be changed via FKey
ComKeyRemapper or AmigaKeyremapper could swap RAmiga to another key press
===DOpus 5 Directory Opus Magellan II===
Dopus 5.x is a whole desktop replacement on the Amiga Workbench (Desktop)
DirectoryOpus app will assign DOpus5: to it's PROGDIR: automatically but if not add the below (edit SYS:System to suit where Dopus5 was installed) to your startup-sequence
<pre>
Assign DOpus5: SYS:System/DOpus5
DOpus5:DirectoryOpus
;DOpus5:C/LoadDB
</pre>
Left mouse button clicked twice on the desktop background brings up the Device List window.
Green strip notifies SRCE (source) and if another is open it will be red for DEST (destination). clicking on the red strip changes to green
Word list of actions with a left mouse click on the DOWN Arrow and directory stuff with < button which mirrors the icons at the top of each lister
single-key hotkeys? exactly the same as in dopus4, edit your functions (button bank, toolbar, menus etc.) and under the flags gadget is a key gadget, just click in it and press the key you want to use.
As for the extra text field... try turning off Extended lister key selection in environment / miscellaneous.
Shift and click on the icon - runs the icon
DOpus5 Magellan 2 Directory folder drawer structure
<pre>
ARexx - Arexx scripts .rexx and .dopus5 to perform tasks
Buttons -
Commands -
Desktop -
Environment - two environment files bundled:
default gets loaded if you run DOpus as a normal app
workbench gets loaded if you run DOpus as a WB Replacement (with LoadDB on startup)
Filetypes -
Groups -
Icons -
Images -
Modules - compiled tasks
Settings -
Sounds -
Themes -
WBStartup - Use this if standard SYS:WBStartup gives cannot wait error messages
</pre>
Settings -> Environment -> Display -> Workbench (Use)
*Settings -> Clock (add to title bar as well as the date)
*Toolbar -> Editor (Right Win Key together with 1) for Copy, Move, Delete, etc above the Device List
*Menu -> (Right Win Key together with 2)
*Buttons -> Editor (Right Win Key together with 3)
*Settings -> Environment (Right Win key together with 4) for Backgrounds, etc
*File Types -> (Right Win key together with 5)
*User Menus -> (Right Win key together with 6)
*Hotkeys -> Setup for quick shortcut keypresses (Right Win Key together with 7)
*Scripts -> (Right Win key together with 8)
*Icon Positioning -> (Right Win key together with 9)
Each Dopus5 theme are stored in a separate directory, named appropriately, which contains further sub directories
* Font (amiga bitmap fonts)
* Screens (jpg or any picture supported by datatypes but not animations)
* Sounds (wav but not iff 8svx )
* Icons (png newicons glowicons )
* Patterns (iff jpg png )
Just use wildcards in background filenames and you get a different picture every reboot
For example, configure in Environment -> Backgrounds -> Desktop something like this:
<pre>
Work:Pictures/Backgrounds/#?
...or
Work:Pictures/back#?.iff
...etc...
</pre>
[https://aminet.net/util/dopus arcdir and themes]
If you want to change the backdrop pic after a period of time, paste below into a text file called dopusrandbg.rexx and place in DOPus5:ARexx
<pre>
/* Changes DOpus background image forever
Start with:
Run >NIL: RX dopusrandbg.rexx
*/
if ~show("L", "rexxsupport.library") then do
if ~addlib("rexxsupport.library", 0, -30,0) then exit 10
end
/* Configure these two lines for your needs: */
minutes=1
picpath="Work:Pics/#?.iff"
address DOPUS.1
do forever
call delay 3000*minutes
dopus set background '"'picpath'"' desktop center custom
dopus refresh background custom
end
</pre>
If you don't want to use/open rexxsupport.library just for DELAY() then use the DOS Wait command
<pre>
/* random diropus backdrop changer */
/* by paul trauth, 1999 */
/* to do: non-repeatable randomness? */
options results
parse arg path
address DOPUS.1
/* get current backdrop pattern so it actually changes */
dopus query background desktop custom
currentpatt=result
lastslash=lastpos('/',currentpatt)
currentpatt=substr(currentpatt,lastslash+1,(pos('"',currentpatt,2)-lastslash-1))
dir=showdir(path,'FILE','/')
num=0
do while dir~=''
where=pos('/',dir)
if where>0 then do
file=left(dir,where-1)
dir=right(dir,length(dir)-where)
end
else do
file=dir
dir=''
end
if left(file,1) ~='.' & file~=currentpatt then
do
pics.num=file
num=num+1
end
end
which=random(0,num-1,time(s))
newbg='"'||path||'/'||pics.which||'"'
dopus set background newbg desktop tile precision exact
dopus set background on
dopus refresh background
</pre>
Clock format commands available are defined by locale. They are:
<pre>
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
</pre>
like %a %d-%b-%y %H:%M or
A WB ARexx interface, you could enter a cli command as a menu item to open a WB drawer like this...
RX "address WORKBENCH;WINDOW 'device:drawer' OPEN"
Where device:drawer is replaced by the path of the drawer to open.
The ARexx script would be capable to manage such a task but this would work only with those program that support ARexx
<pre>
dopus addappicon
dopus addtrap
dopus back
dopus checkdesktop
dopus clear
dopus command
dopus desktoppopup
dopus error
dopus front
dopus getdesktop
dopus getfiletype
dopus getstring
dopus matchdesktop
dopus progress
dopus query background, font, palette, pens
dopus read
dopus refresh all, background, icons, lister
dopus remappicon
dopus remtrap
dopus request
dopus script
dopus screen
dopus send
dopus set background, font, palette, pens
dopus setappicon
dopus version
</pre>
<pre>
lister add
lister addstem
lister copy
lister clear value
lister clearcaches
lister close
lister empty
lister findcache
lister getstring
lister iconify
lister new
lister query active all, dest source
lister query abort, busy, case, dirs, display, entries, entry, files, flags, handler, header, hide
lister query label, lock, mode, namelength, numdirs, numentries, numfiles, numseldirs, numselfiles
lister query path, proc, position, seldirs, selentries, selfiles, separate, show, sort,
lister query title, toolbar, value, visible, window
lister read
lister refresh
lister reload
lister remove
lister request
lister set busy, case, dest, display, field, flags, handler, header, hide, label, lock, mode
lister set namelength, newprogress, off, path, position, progress, separate, show, sort, source
lister set title, toolbar, value, variable
lister select
lister wait
</pre>
The '''command''' allows you to call internal DOpus commands from an ARexx script
<pre>
command all
command wait copy
command read s:startup-sequence
command source 12345 makedir name noicon
</pre>
*SFTP secure encrypted comms over internet using libssh2 and zlib (different protocol to the two below) on port 22
*FTPS secured with https like security on port 21
*FTP not secure and unencrypted protocol over internet on port 21 (should not be used today on the internet but for your own server)
===Wanderer ===
Wanderer prefs in the prefs drawer - Appearance tab and Workbench icon allows backgrounds (wallpapers) icon text sizes, colors, etc but cannot use #? or *.* in the backgrounds file entry to randomly choose pictures - [https://developers.google.com/speed/webp/docs/riff_container webp riff container] issues with this format but Multiview has none.
Enable the bar, you need to edit the text file ‘statusbar.prefs’. The change is simple: just change “False” to ‘True’.
Prefs/Env-Archive/SYS/Wanderer/statusbar.prefs
===Scalos===
[https://web.archive.org/web/20180922220139/http://scalos.noname.fr/ Scalos] is not an OS replacement, it's a Workbench replacement. It replaces the desktop and graphical file management components.
Scalos is 100% Workbench replacement with most functions working like the original Workbench ones. Undo and Redo available for most window and icon operations. Fully multitasking so every window has its own task. While loading icons, any window function (e.g. Drag&Drop) is available.
24bit color support with window patterns - Unlimited and easily configurable via tooltypes. Optimised backgroundpatterns routine so patterns can be tiled, centred or even scaled to fit into the windows. Live updating window scrolling - Supports middle mouse button panning and drawer (folder) windows can be iconified on the desktop.
Icon imagetypes with all types are supported such as backfill or complement. Configurable surrounding iconborder. Icon support also visually highlights files which are soft-links in the file system. Icon dragging is more stable and far less flickery on graphics cards. Whilst dragging, icons are displayed with text and they can become transparent over anything where they can be dropped.
Single-window lasso mode, with scrolling window contents invoked by dragging mouse with configurable qualifier key. Text icon lasso selection used to ignore "Name column selects text icons" flag. Support for backfilled thumbnail icons, with selectable color and transparency. Added option to always generate square thumbnail icons with preview icons for images - Thumbnails can be permanently saved in icons.
Supports PNG icons with alpha channel and real transparency and displays OS3.5 GlowIcons and are all scalable. Iconborders with variations (normal, shadowed, outlined).
Completely configurable, filetype-specific user-definable popup menus and tooltips. Plugin system to exchange or add features and can enhance the Workbench and make it more configurable.
Filetype plugins to display filetype-specific information. - Currently, EXIF information viewer for JPEG images is included. Plugin included for 100% support of OS3.9 Workbench features. Plugin included for AREXX API compatible to OS3.9 Workbench.
Online update with updater.module
Scalos works also as a Workbench replacement. In this case the 'emulation mode' has to be set by using Scalos' own version of LoadWB and offers
* Scalos uses the Workbench Screen for its windows instead opening a new one
* AppIcon, AppMenuItem, AppWindow functions are redirected to Scalos
* all Programs placed in "WBStartup" should start
* The Screen will be reopened in case of changes in ScreenMode and Palette settings
<pre>
v1.0 (V39.201) - November 1999
v1.1 (V39.212) - December 1999
v1.2b (39.220) - June 6, 2000
v1.2d (39.222) - 2000 (latest public beta executable)
v1.3 (40.7) (beta) - August 2, 2001
v1.3 (40.22) - September 25, 2002
v1.4 (40.32) (beta) March 31, 2005
v1.6 (41.4) - March 27, 2007
v1.7 (41.5) - August 12, 2007
v1.8 (41.6) - March 12, 2009
v1.9 (41.7) (beta) - March 15, 2010
v1.9 (41.8) (RC1) - August 25, 2012 open source
v1.9.2 (41.10) Deadwoods' AROS late 2022 32bit and 64bit build unifying the code base of ` for AROS x86 ABIv0, AROS x86_64 ABIv11 and AROS m68k
</pre>
Distros may have Scalos files under SYS:System/Scalos or Extras:Scalos. Known [https://github.com/deadwood2/AROS/issues/75 bug list],
Certain files like Menu13.prefs, Palette13.prefs, Pattern.prefs and scalos.prefs need to be in SYS:Prefs/Env-Archive/Scalos they can be found in Scalos:Storage/envarc and country drawer
or run the "Scalos Menu" preferences program. Note if already setup with sub-menu entries and then re-save your menu prefs as it will now generate a new/overwrite prefs file called "Menu13.prefs" in "envarc:scalos/". The same is also required for the new Palette prefs update, click 'Save' and a "Palette13.prefs" file will be saved in to "envarc:scalos/" directory.
<pre>
ASSIGN Scalos: SYS:xxx/xxx DEFER
ASSIGN Libs: Scalos:Libs add
;ASSIGN SYS:Devs/Datatypes Scalos:Devs/Datatypes add
Assign Theme: Scalos:Themes/Default_Theme add
Assign Locale: Scalos:Locale add
Protect Scalos:Tools/browse.script s add quiet
Protect Scalos:Tools/OpenShell s add quiet
Protect Scalos:Tools/run.script s add quiet
run Scalos:Tools/LoadWB
;Scalos:Scalos
</pre>
Add the above to SYS:S/startup-sequence or SYS:S/user-startup '''before any Wanderer entries'''
In the prefs drawer (folder) is the big prefs app Scalos_Prefs which covers these user setup areas
<pre>
About Scalos
Paths - should be preset
Startup - WBStartup drawer contents should auto run on each startup
Desktop - edit titlebar, icon layout and in misc, auto leave-out (drag icon to desktop)
Icons -
Drag and Drop -
Windows -
Text Windows - in misc, drawer sorting at start of listing if needed
TrueType Fonts - use Truetype fonts rather than system ones
Miscellaneous -
Plugins - after adding oop/title_clock.plugin %ti %da does not work, maybe needs ASCII .prefs added
Modules - ??
Menu - setup for MainMenu and PopupsMenu with New Menu, RE Name, Key: shortcut, Command Properties
FileTypes - already added def_Project icons and def_Disk (hdd sdd cd dvd etc) support
PopupMenu - tweak how popups appear
Pattern - Wallpaper backgrounds with Type DE, each pattern in the list can be edited, Save as Pattern.pre
Palette - change the color of things , Save as Palette.pre
</pre>
Scalos_Prefs - Pattern - Minimum options to be changed are
*DE Desktop/Background
*SC Screen
*TW Window/TextBackground ie Text listing showing if icon type not recognised
*IW Window/Background ie Icons showing
Workflow - In "Pattern List" tab, select New - choose a picture, highlight in list, click in number box under New button and slide to another number, click on "Defaults" tab and adjust Pattern numbers slider to choose right picture for each of the above options - Click "Pattern List" tab to check eveything is OK and click Save
Pattern List tab on Patterns Page - Allows you to compile a list of pictures (one at a time rather than a whole folder e.g. with #? or *.*), assigning a number Nr to one or more of them for easy reference. Using this number you will be able to assign the pictures to specific windows on the Defaults tab Page. If multiple pictures have the same number, one of the pictures will be chosen randomly. This will allow you to have random desktop pictures, random window backdrops etc.
Defaults tab on Patterns Page - Here you can set the defaults for the background pictures for the Desktop, Screen, Window and/or Text Mode throughout Scalos.
Randomize every time [check box] - Usually Pictures with the same number will be randomly selected as soon as the configuration loads. If this option is set, the picture will be selected as soon as a window with the same number assignment is opened.
*Fit size: The picture will be resized to the dimension of the new window.You *MUST* have set GUIGfx on. asyncron layout: Pictures will be loaded and rendered while the windows opens (Like original Workbench). If this function is 'off', pictures will always be loaded before opening the windows.
*Use friendbitmap : The picture is present twice in memory for best speed. This option has no effect if V43 picture.datatype or GUIGfx are used. Always relayout: If "Fit size" is set, the picture will be scaled everytime the window's dimensions change.
*Randomize everytime: Usually Pictures with the same number will be randomly selected as soon as the If more pictures have the same number, one of them will be chosen randomly.
Patternlist New/Delete : Add a new picture. After that you should assign a number to it. The picture will be rendered as tiles. configuration loads. If this option is set, the picture
Asyncron-Task priority: You can set the CPU priority for the Task if "asyncron layout" is set.
<pre>
Desktop: Number of the Picture for the main window.
Screen: Number of the picture for the Scalos-Screen.
Window: Number of the picture for the Scalos-windows.
TextMode: Number of the picture for the Scalos-windows in Text Mode.
</pre>
Popup Menu preferences fully configurable menus (includes ToolsDaemon and ParM launch apps import), including support for context-sensitive Popup menus configs for top pull down menus for apps, etc.
Workflow - Scalos_Prefs then Menu, New Item, New Command add name at top then in Command Properties e.g. add Workbench and location e.g. DOpus:DOpus4 for apps Command for c apps or Rexx for scripts or Plugin for or AmigaDos for modules
<pre>
DESCRIPTION NAME/A This is the title that is displayed in the top line of any popup menu
INCLUDE NAME/A Name of file to be included. Path can be relative to "Scalos:FileTypes"
POPUPMENU Starts the popup menu description section for this filetype.
</pre>
The following Subcommands are allowed inside popup menus:
<pre>
SUBMENU "NAME/A"
ENDSUBMENU
MENUENTRY "NAME/A,KEY/K,DEFAULTACTION/S"
ENDMENUENTRY
INTERNALCMD "NAME/A"
WBCMD "NAME/A,STACK/K/N,WBARGS/S,PRI=PRIORITY/K/N"
AREXXCMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
CLICMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
ICONWINDOWCMD "NAME/A"
PLUGINCMD
MENUSEPARATOR
ENDPOPUPMENU
TOOLTIP
ENDTOOLTIP
</pre>
<pre>
Starts the tooltip description section for this filetype. The following Subcommands are allowed inside popup menus:
GROUP "ORIENTATION/K"
ENDGROUP
MEMBER "HIDE/K"
ENDMEMBER
HBAR
STRING "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K"
SPACE "SIZE/N/A"
DTIMAGE "FILENAME/A"
</pre>
Each theme drawer (folder) has these further folders
<pre>
About -
Desktop -
FileTrans -
FileType -
Icons -
Menu -
Modules -
PointerIcons -
Prefs -
Sound -
Window -
</pre>
*Plugins
<pre>
devicefilter.plugin
persist.plugin should a crash or reboot occur - next time Scalos started, all windows re-opened
title_clock.plugin add digital clock to title see more below
title_envvar.plugin %ev, which can be used to display the value (a string) of the variable in the titlebar
title_freepens.plugin
volumegauge.plugin
wb39.plugin
wbrexx.plugin plugin adds a Workbench 3.5+ compatible AREXX interface to Scalos internals
xtwindows.plugin left or right ALT or left or right SHIFT keys when open/close windows
filetype.plugin then run FileTypes-prefs and customize the filetypes (eg import from a DefIcons-brainfile)
menu.plugin
</pre>
*Modules - delete, empty_trashcan, execute, find, format_disk, information, iconproperties, newdrawer, reboot, rename, systeminfo, windowproperties
*Tools - scripts like LoadWB, quit.rexx, open_volume.rexx,
In Scalos_Prefs->Filetype->Recognition you can define the filetypes and on "Action" you define specific context menu for all filetypes defined in recognition (similar to magellan)
there is the same you must show all first (list is only limited) so you created a file type AAABBB, you need to have def_AAABBB icon
Associating files with "Scalos_FileTypes" is very simple, practically it is very similar to Dopus4, first you create the Def_icons to assign to the file type (will be seen automatically ), then run "Scalos_FileTypes" you add the extension, fill in the descriptor (MATCH or PATTERN etc..) and save
then you create an appropriate entry in the list and rename it, if def icon exists it is shown. Below you can define how files are identified. Use "pattern", similar to magellan to identify file by ending. Then you click on the shown icon and define in it what program is used when you double-klick on it and save it. On the tab action you can define popup menu for it.
defined all archive types from XAD in "filetypes". If you change to "action" and click on "archive" you can define the context menu that is shown if you do not define a specific context menu for a filetype
Reset to Default in Scalos_Prefs resets all settings so '''BEWARE'''
<pre>
The Scalos desktop screen titlebar may be configured using the main Scalos Preference program. This oop/time_clock plugin adds some additional placeholders:
%ti, displays the current time in the default Locale format. e.g. "10:43:37"
%da, displays the date in the default Locale format. e.g. "Saturday 14 July 2001"
Using the supplied prefs program for the plugin, or editing the ASCII file ENVARC:Scalos/title_clock.prefs you can use the following standard Amiga Locale values to change the formatting
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%C - same as "%a %b %e %T %Z %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%n - insert a linefeed
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%t - insert a tab character
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
like %d %m %y or %a %d %B %Y %p
</pre>
Shutdown -> right mouse button Scalos, About, Reboot, Shutdown
ToolTypes can be added to the Scalos.info icon like
*SCALOS_PATTERNNO=<number> : background image matching the number
*SCALOS_NOTEXT : The Icon will be drawn without Text.
*SCALOS_NODRAG : The Icon will not be draggable. Its position will be fixed.
*Module iconproperties - Added SCALOS_BROWSERMODE tooltype support
runcommand parameters... in which case:
<pre>
%p = parameters
%w = directory path
%d = device-name
%% = literal percentage token
</pre>
With the help of the wbrexx.plugin Scalos gains support for more of the compatible arexx API
If an arexx command produces an error you will find the error code placed in the WORKBENCH.LASTERROR variable.
ACTIVATEWINDOW
<pre>
/* Activate the root window */
ADDRESS workbench
ACTIVATEWINDOW root
/* Activate the "Work:" partition's window if already open*/
ACTIVATEWINDOW "Work:"
</pre>
CHANGEWINDOW
<pre>
/* Change the root window; move it to position 10,30. * and change its size to 200100 pixels */
ADDRESS workbench
CHANGEWINDOW root LEFTEDGE 10 TOPEDGE 30 WIDTH 200 HEIGHT 100
/* Change the currently active window */
CHANGEWINDOW active 20 40 200 100
</pre>
Most of Scalos' issue are due to the flexibility of its' user configuring nature but if
The sort menu plugin needs to be ported from ASM to C.
IIRC Scalos has a command line option to fully replace Workbench/Wanderer.
The Theme: assign is used by both Wanderer and Scalos but I didn't have any problems using both at the same time.
The Program will be started from the Shell.
If "WB Args" is set, with the Argument "%p" will be replaced by the path of the activated Icons. The Program will started with the specified Stack value.
IconWindow: Scalos opens the window of the specified path.
PlugIn: Starts a Scalos Menu-PlugIn.
If a Menu Item with empty name is specified, Scalos displays a separator line.
It's possible to Drag&Drop an Icon in the Configuration Window. All values will be set accordingly. Entries may be dragged across the list.
Mac-like selection : This function activates a multiselection method used on MacOS or Win95. Don't have to hold down shift to drag them. Clicking on an already activated icon will
not deselect all other icons.
MMB move: The window contents may be moved using the middle mouse button.
WindowPopup title only: PopupMenu for windows can be opened only on window's title bars.
FullBench: Screen-Titles removed and Main Window set Full Size.
Scalos Prefs. Go to Settings->Scalos->Prefs and then the Misc section. Remove the tick against Full Bench. If you've enabled it, the titlebar will disappear when you select backdrop.
Default Icons saveable : The icons which Scalos generates if "show all files" is enabled, can now be saved
using "snapshot" menu option. load DefDisk first : Try to read the icons first from the DefIcons Path before using disk info.
Hide hidden files : If this function is activated all files or directories where the "hide" flag is set will not be shown.
Many of my Icons display more than once on the screen, while on the workbench all seems ok.
The Workbench filters double displayed icons, Scalos does not. Solution: please edit the ".backdrop" file and clear double lines.
Background images not scaled. GUIGfx option not set or guigfx.library and/or render.library not installed.
If working with CD's causes crashs or Scalos doesn't work correctly.
Most Filesystems doesn't support the ExAll function correctly. Disable "Use ExAll" in Scalos prefs.
Scalos doesn't start any program in the WBStartup. WBStartup Path may be set wrongly or Scalos was not started in Emulation Mode (LoadWB etc)
Some programs will not startup with error message "has not returned, wait some more"? and "unable to open your tool"
need a def_icon with the same name predefined, then create an appropriate entry in the list and rename it, if def icon exists it is shown. Below this can define how files are identified.
* either "pattern", similar to magellan to identify file by ending
* or
Then click on the shown icon and define in it what program is used when you double-click on it and save it. On the tab action you can define popup menu for it. All in all handling is of course different to magellan but can do similar
For the RAM Icon, to obtain this you have only to copy the icon in the Icon Path as "RAM.info" or "Ram Disk.info". All functions will automatically be performed
sometimes cut into half or quarters when scrolled off screen or drawers moved - settings issue probably
Sometimes leaves initial drawer window imprint on desktop when moved - settings issue
Scalos AROS released a [https://github.com/deadwood2/contrib/tree/master/scalos new build V2022-07-21] with the following changes noted:
<pre>
Fixed:
Numerous crashes when working on 64-bit with 64-bit heap
Wrong background color of Scalos logo on Scalos splash window
Backgroung image of Scalos splash window and Scalos About window is not visible
Icon labels on desktop and in drawer windows are displayed using Topaz instead of Arial font
Font.prefs are not being loaded on 64-bit
Font.prefs are being wrongly saved on 64-bit
scalos.prefs are not being loaded on x86 and x86_64, scalos is using always default preference
scalos.prefs are being saved on x86 and x86_64 in format not compatible with m68k
NewPopupmenu.prefs is wrongly written
Plugins are not loading at Scalos startup
wbrexx.plugin is crashing at startup on 64-bit
Multiple controls missing on Scalos Prefs/Icons page
System crash when clicking on def icon image on FileTypes Prefs/Recognition page
Status bar, control bar, buttons sometimes don't have images displayed
Buttons in Scalos About window have white corners rendered where they should be transparent
Crash when leaving out an icon
Crash when adding a User-defined Button to Control bar without setting it's properties in Scalos Prefs
Crash when removing any button from Control bar in Scalos Prefs
Scalos Prefs allows editing TTEngine font properties when TTEngine is not present causing crash in Icons/Labels and Text Windows/Fonts pages
deficons.prefs are not being loaded on x86 and x86_64
Reset to default in FileType Prefs and Save does not save preferences
Won't fix:
Scrollbars visible on titles of TrueType Fonts, PopupMenu, Menu, FileTypes, Pallette and Pattern pages of Scalos Preferences
Not fixed:
Wrong rendering on DualPNG icons
Refreshing drawer windows is slow
Starting Prefs/Locale or Prefs/Input from Scalos causes other preferences to fail
Desktop wallpaper is damaged where Splay window was displayed
When started from Wanderer, after saving Scalos Prefs, reload does not re-open main Scalos window
Difference in behavior between Cleanup from popup menu and Cleanup from top menu - possibly due to missing plugin, check Cleanup association in Menu Prefs
</pre>
===DOpus 4 Directory Opus===
Copy DOpus4 app to WBStartup directory folder so it starts on boot up each time
Another method is add the below to the bottom of the user-startup script in SYS:S drawer/directory
<pre>
run DOPUS:DirectoryOpus -i >NIL
</pre>
makes DOpus starts up in Iconified state at the top of Wanderer's screen. Left click on this to highlight and right mouse click to open.
Just click on the sides of either outer edges of DOpus windows and it will display the parent device/volume list.
DOpus4 saves it features in a PROGDIR:s/DirectoryOpus.CFG file which can be edited to suit anyones' needs, '''C''' bottom right button in DOpus4 and by reading the [https://arosarchives.os4depot.net/index.php?function=browse&cat=utility/filetool Dopus4 guide Manual and Arexx calls].
*[https://www.youtube.com/watch?v=DCyXDs8baSE Pt1 Introduction]
*[https://www.youtube.com/watch?v=7fiVmopiK9I Pt2 Dopus Config]
*[]
*[]
*Button little rectangle with name inside
*Bank vertical stack of buttons
Buttons
*Workbench app {f} i.e. first use {F} for all selected items with app
*AmigaDos c type apps with arguments after
*Arexx
*Command c type apps with no arguments after
Flags (most used)
*CD Destination to extract etc
*Do all files
*Output window
*Run asynchronously
*Workbench to front
*Buffer above 100000 for 64bit
Filetypes
Defines how certain files are handled like '''default tool'''
Screen
Fonts, set each element to any font
Screenmode, Workbench Use (same screen like Windows), Workbench clone (like Linux workspaces)
System
Shell startup, set to SYS:s/shell-startup
===BoingIconBar===
User chooses the apps to add to the dock at the centre bottom of the screen but has to be done manually, please use Save afterwards
Or easier edit the text file of SYS:Prefs/Env-Archive/iconbar.prefs and save
<pre>
BOING_PREFS
;Tools
SYS:System/Shell
SYS:Tools/DOpus4/DOpus4
SYS:Utilities/Editor
SYS:System/SysMon
SYS:System/Scout
Work:Extras/Internet/OWB/OWB
Work:Extras/Graphics/Lunapaint
Work:Extras/Graphics/ZunePaint
AROS:Tools/MPlayer/MPlayer
Extras:Internet/AmiFox/AmiFox
</pre>
right mouse click on bottom edge of screen where boingiconbar shows - select settings which opens BoingIconBar Preferences to add apps
If no dock showing Add, to add apps click Add Program and search for the executable
another method is to drag icons to ends of the bar and move them on the Bar using the Prefs/BoingIconBar
===AmiStart===
On 32bit PCs only - auto generates the apps menu but scans the drive each time - AmiStart can choose apps you are not interested
* how to disable annoying zune/mui 'bubbles'?
try a right-click on AmiStart and release on Global settings. Then click on the bubbles gadget. Move the Show Bubbles slider all the way to the left.
===Fonts===
Install the #?.ttf files to SYS:Fonts/TrueType. Use SYS:System/FTManager to "Install Font" each #?.ttf file which will generate associated #?.otag and #?.font in SYS:Fonts. Use SYS:Prefs/Fonts to change system fonts and SYS:Prefs/Zune to change others.
To achieve our goal we will use the Setup Locale, Input, Zune and Fonts, as well as The FTManager.
Begin
The first step you should do is to get the system to know that we speak and write in another language. What you need to do is to open the setup program and choose Locale country, and list "preferred languages" to put it first and then English. If you want the tab "Time Zone" and select city of residence to set the clock correctly. Of course we save our changes and continue opening the setup program Input. This sets the keyboard language as our beginning. When the language layout was created there was no option to switch to Aros keyboard (layout switching), so to write in the language you had to hold down Alt, something you encounter in other functions. This time working with the team of Aros to create a new keyboard layout to replace the old so we can get rid of the button Alt. For now though let only selected this layout and do not turn the switch on the keyboard.
Custom Keyboard Layout
[http://repo.or.cz/w/AROS.git/tree/HEAD:/workbench/devs/keymaps keymaps are in place but unfortunately when they are not, then indeed things become a bit 'low-level' as it involves redefining some tables with values that match your keyboards]
only need to add your compiled table as new keymap.
So taking a little peek here shows that it should be possible to compile using
gcc -opc105_tr pc_105.c -nostdlib
where the pc105_gr/pc_105.c needs to be replaced with your own adjusted keymapname/c-file
[https://en.wikiversity.org/wiki/Enabling_Greek_Characters_on_Your_Keyboard General overview of Greek letters on keyboards]
Installing fonts
*[http://aminet.net/package/util/wb/EPAGrWb System jaggy]
*Outline resizable .font .otag
In this step you need to download some fonts that can support the encoding in our system. The easiest way is to run the script "Download Fonts" you'll find in the folder OWB. This script downloads from the Internet, and unpacks some fonts for OWB web browser, which is placed under the folder Fonts:TrueType. But as these can only be used by OWB and not the system, which unfortunately does not see. To make them available to the rest of the system, open the program FTManager, you will find the folder AROS: System /. From there select the field "Codepage" option "ISO-8859-7" and list the font "Arial" and "Regular" form in which you must double-click with the mouse. In the window that appears, select the bottom right the checkbox "Anti-aliasing" button and then "Install". Immediately folder Fonts: created files "arialregular.font" and "arialregular.otag", which are necessary in order to see the system font. Do the same steps if you wish for other fonts.
Final stages
After completing the above, open the folder AROS: Prefs / and run the program settings Fonts. In the new window, select the fields "Icons" and "Screen" as the font "ArialRegular" to the size you want. In the field "System" to give "s_courier", which, however, because it is not True Type Font support Antialising, and may seem a little broken. You can also use the CourierNew, if you have installed the above procedure. After you save the changes and open the Zune program settings. In this set the "ArialRegular" font fields in tabs "Windows" and "Groups", and save the changes. Reboot the system. To make sure that the above worked properly run NoWinED, which you will find under the folder AROS: Tools /. If that everything is working correctly you will see the menu and the settings window with Greek letters. You can also write in the language using the button Alt. Second program that you can try, which is fully localized, is WookieChat, which you will find in the folder AROS: Extras / Networking. And in this place all the menu and settings window works.
===Windows===
*Intuition
The window you position and resize, you right click on that windows title bar and in the dropdown menu you snapshot from there. Right click to show menu -> Window -> Snapshot Windows or All but it will NOT work if that folder has no icon (e.g. Disk.nfo) attached to it. You need a folder icon. The window information gets saved in it.
As for maximising the window using a shortcut key - Alt and up arrow key
The AROS-Shell windows can be moved, resized by editing sys:s/startup-sequence
<pre>
; run shell
run QUIET c:newshell >NIL:
</pre>
; slimmer right aros the screen
run QUIET c:newshell con:0/150//300/ >NIL:
; top right corner scr-x scr-y win-x win-y
run QUIET c:newshell con:600/150//300/ >NIL:
*EdgeSnap
Commodity EdgeSnap allows resize and position windows on your screen by dragging them to the edges but not corners of the screen and/or other windows
EdgeSnap Prefs (once pressed Use button) lets you arrange windows but not different applications in layouts half (left or right) or full size (top) and choose to adjust the border padding
There is outline to show shape taken to aid placement and space available
*Zune - AROS version of MUI
Magic Menu type functionality is implemented in IControl preferences editor: in the frame called Menus, switch type from Pull-Down to Pop-Up and/or iControl just tick the sticky menu option.
Windows outside screens causing a problem either uncheck "Offscreen move" for windows in IControl prefs editor. Or use FKey commodity and define two key shortcuts:
* the first using the command "cycle windows" (for example ALT TAB);
* the second using the command "rescue window" (for example ALT F5).
Now you can cycle windows until the one you want to rescue, and then "rescue" it: it will move back inside your screen.
How to save the window size on wanderer (snapshot all, snapshot windows)
Same for icon position on wanderer, can't save the position. Icon position cannot be saved yet, but you should be able to save the window position and size. sys:prefs - wanderer icon has option to save window size on exit but just for dh0. To get saving working on (DH1: Extras:) partitions try deleting the dh1 disk.info file, then reboot. The system should create a new dh1 icon.
* how to set up permanently 'view all files'?
As for viewing all files, removing disk.info for that disk did the job
* how to list and kill processes (xkill would be useful) ?
sys:Extras/System/Scout can kill apps
sys:Tools/Commodities/Exchange can remove available commodities
* how to restore 'go up' button in wanderer window? (it doesn't show up anymore).
If you're using Icaros, go to the theme prefs and make sure that decoration is checked. Also, some themes do not use a parent button, so try another theme. You may have to restart Aros before the theme will change.
* Is it really safe to turn off (hardware button) computer at any time (worried about USB hard disk)
yes you can turn off the computer IF none of the drives are in progress (i.e. writing). Best to use Wanderer menu option Quit otherwise
===Say narrator===
Say "Hello World" for a simple robotic voice
SPEAK: is a write-only DOS device for text-to-speech abbreviated as tts.
To check if available, type assign into the shell and at the bottom in the Devices: section should be SPEAK
Examples of use
<pre>
Copy S:Startup-Sequence SPEAK:
Echo "Hello" >SPEAK:M/R/S150/P110
Echo "DH1 EH0 L OW1" >SPEAK:A1
</pre>
Classic options are M/F, R/N, S<rate>, P<pitch>, O0/O1, A0/A1, and D0/D1. O1 recognizes lines beginning with OPT/ as option changes. A1 treats input as narrator phonemes.
Long options select a speech engine:
Echo "Hello" >SPEAK:ENGINE=narrator/VOICE=female/STYLE=natural/LANGUAGE=en-US
Supported selectors are ENGINE=, VOICE=, STYLE=, and LANGUAGE=. Values are case-sensitive backend identifiers. ENGINE=DEFAULT selects the system default. Narrator-compatible selectors continue through the classic translator/narrator pair. Other engines use speech.device. Direct phonemes require a narrator-compatible selection.
===Printing===
This needs further [http://www.aminet.net/package/docs/help/PrinterGuide drivers written], we have postscript and write to file support only
;There are no individual drivers yet for HP's Photosmart, EPSON's EPL, CANON's, Lexmark, CUPS PPD, etc.
*Postscript
Best to set Printer Prefs in the Prefs drawer to print-to-file or parallel/USB port
Save document in postscript or convert picture/text to postscript
Print using compatible Postscript printer
*printer is simply not accepting IPP connections at the moment.
Please try the following steps:
Open the printer web interface in a browser:
http://192.168.1.x/
Look for the network or protocol settings.
Enable IPP / Internet Printing Protocol.
Make sure TCP port 631 is open/enabled.
Save the settings and reboot the printer if the web interface asks for it.
ipp://192.168.1.xx:631/ipp/print
ipp://192.168.1.xxx:631/ipp/
===Files===
====File endings and datatypes====
* Check if the file has his own .info icon file with a tool set to open it. IIRC this has higher priority over the def_XYZ.info file association.
* In ENVARC:SYS/def_Text.info or whatever def_ file needs changing, use Wanderer's menu Icon -> Information and change the def_XYZ.info there. If you're on ABIv0 and want it to be applied immediately, you might have to copy it to ENV:SYS/ (or to reboot).
* Identifying file types by file ending is only a fallback. Far better it is to search for magic words, for flac files this would be "flaC" according to this [http://flac.sourceforge.net/documentation_format_overview.html documentation].
For instance, to open PDFs with arospdf not localised in the default drawer of Icaros (Work:Extras/Applications/arospdf) but localised in a custom drawer in AROS. The default tools are defined in the icons in sys:prefs/env-archive/sys e.g. def_PDF.
File type identification is done by datatype descriptors which you can find in Devs/Datatypes. The AROS build system has a tool which creates such datatype descriptors.
'''Changing of default tools of existing icons is easy as shown above. Adding of new file types is not hard, but needs knowledge of the AROS build system.'''
The enduser way would be to download the attached file, which contained two executables:
1) createdtdesc, to make a new datatype description
2) examinedtdesc, to read/show existing datatype descriptions
use 2 to get an idea on how it things are currently done in aros by providing this executable a file from the drawer sys:devs/datatypes/ (alternatively you can find the original .dtd files here).
use 1 to make your new datatype. Use the accompanied FORMAT file (also here) to read how to make your own datatype descriptor. use 2 to get hints from other datatype descriptors.
Note:
When creating a new descriptor would advise against using the pattern property, but instead use the default pattern of #? and create a Mask that matches your filetype. This requires some research in order to discover how your filetype can be recognized properly. Of course with making something like a descriptor for an ascii textfile, you would fallback to using the pattern (e.g. #?.text as the filetype cannot be determined easily otherwise).
<pre >
# name - choose wisely and informative. also used for icon's name.
# version - choose as you like as long as it complies with version rules
# basename - the 'root' datatype class. be aware that e.g. it can influence behaviour. for example when choosing binary and using tool multiview in project icon, the file will be viewed as binary file (choosing sound would tell mulitview to view the file as a soundfile). So this can influence the underlying tool being used. Could become messy if users started to modify the tool manually.
# pattern - This is the file pattern match e.g. #?.text
# Mask - A mask to identify the file. Requires knowledge of the actual file structure. For example 'M' 'Z' for an msdos executable.
# GroupdID - not supported (AROS native) files - use syst as that would be the least intrusive in case an AROS tool/program tries to load such datatyped file.
# ID - In your case, the first four characters of the name at subchapter 1 (in lower case) (or less if name is shorter).
# flags - How the mask needs to be interpreted. In your case would be mostly DTF_BINARY in combination with (wanted or not) DTF_CASE (to tell if mask used letters are case sensitive or not)
# priority - the priority of how the type is handled so that on datatype could have precedence over another? In any case, document tells it to be mostly 0.
</pre >
Now that you know each field and what it does (more or less), you write this fields in a text file for your own invented datatype, save it and create the actual dt with the tool in 1. in the end the created dt must reside in sys:devs/datatypes/ drawer.
Then you would create a default icon in sys:prefs/Env-archive/SYS drawer. Don't forget to reboot or copy .info file to ram:env/sys in order to test. also don't forget to set which tool to start f.e. c:lx or dh4:emulators/mycoolemulator
To test, open Wanderer then show all files and doubleclick on a file of type you just created. Alternatively you could use the 'open' command from shell (with file of datatype you just created as parameter).
And as a last note. it would perhaps be welcome to have a program like xicon and/or runprglist for AROS (unfortunately both without source, but something similar could be created for AROS).
Sounds complicated ?
Perhaps... but OS like windows needs a complete registry to be able to do things like this. And yes, i am aware windows has gui tools that does it (more or less) for you (by manipulating the registry). Same could be done for AROS (without integrating a registry in AROS that is ).
Would that suffice ?
red1+2: typos, reformatting.
disclaimer: please note that using these tools can screw up your currently installed support for datatypes when used incorrectly. Do not use if you do not understand what you are doing. Use at own risk.
==Network Connection==
AROS currently only has one real choice for TCP/IP networking - AROSTCP. This is a port of the AmiTCP package from AmigaOS (TM), with a number of enhancements/fixes from AROS developers.
===Wired===
Use Network Prefs to setup
=====IPv6=====
Some support
128bit IPv6 address packet
<pre>
Local FD::/8
Global 2000::/3
64:ff9b::/96
</pre>
NAT64 translates IPv6 to IPv4
DNS64
OS routing works with
<pre>
MacOS Ventura
Windows 11 with cloud account
Ubuntu Jammy Jellyfish
Android 10 (block google dns)
</pre>
====IPv4====
The top half of the IPv4 Configuration tab on the Network Prefs deals with the network card/USB and the lower half the router part.
[[File:AROS Wanderer Network Prefs DHCP.png|thumb|DHCP Settings]]
'''Upper part of IPv4 tab'''
* Click Add on the top right of the Prefs which opens a window called '''Interface'''
* Enter Name as net0 (but can be anything as long as it is consistently used in other sections)
* check mark on Active
* select device to be used using the '''right hand-side gadget''' of the box where the device name will go
* set Unit to 0
* IP Mode is default set to '''Get address from DHCP'''
* IP Mode set to Manual if DHCP does not work automatically
From the shell CLI, ifconfig -a
Under net0: section, inet starting 192.168.x.xxx
* inet or '''Address''' of network card
* netmask convert to decimal so 0x'''ffffff7f''' becomes 255.255.255.247 which is used to adjust the above '''Address''' into
* broadcast 192.168.xxx.xxx
click OK
[[File:AROS Wanderer Network Prefs Manual.png|thumb|Manual Settings]]
'''Lower part of IPv4 tab'''
* IP Mode Get address from DHCP (default)
* or changing to Manual if automatic DHCP set up does not work
* '''Gateway''' (Router Internal LAN-IP) (Default Route) = 192.168.0.1 (D-Link Netgear), 192.168.1.1 (Linksys 3com), 192.168.2.1 (SMC Microsoft), 192.168.1.254 (Belkin), 192.168.123.254 (USRobotics) else check with your router manual
* first DNS = use 208.67.222.222 (opendns) or Gateway number above (to test web browser access to router) or 212.50.160.100 (google) i.e. or whatever your ISP needs you to set
* second DNS = use 208.67.220.220 (opendns) or Gateway number above (to test web browser access to router) or 213.249.130.100 (google) i.e. or whatever your ISP needs you to set
* At the bottom of IPv4 tab, check mark the '''Start networking during system boot''' option
* Save and reboot (sometimes Network restart fails, so reboot every time to be sure)
'''an alternative way''' to AROS ifconfig -a, other OSs have similar for the same internet connection. Another connection will have different settings.
e.g. From [http://www.ncsu.edu/resnet/windows/ipconfig/ Windows], '''ipconfig /all'''
and note down the IP, subnet mask, default gateway, and DNS servers values and put these values in "manually" into AROS Network prefs.
e.g. From Linux via dhcp router have a look at etc./dhcpc/dhcpcd-eth0.info
* for manual input look at /etc/networks (IP or Gateway) and /etc/resolv.conf (DNS)
Please note that all in one routers (wired+wireless) or separate routers may need different settings
IPv4 involves routing (192,168.x.x), firewall, NAT
===Wireless===
You may have a Wifi Prefs to use for wireless setup
[[File:MyArosWirelessSetup.png|thumb|Setting up]]
[[File:MyArosWirelessTCP.png|thumb|Shell commands to work out what is happening]]
We must first make certain you have a Atheros 5k chip inside acting as the wireless wifi option. Open PCITool in Tools directory. Down left hand side are a series of numbers 0.00.0 etc. Click on some at the bottom and hopefully one of them will say Atheros AR5??? or AR242?.
or a Realtek RTL8187B, we can check using Prefs/Trident as this one is USB based
There are many similarities with the above Wired set up so please read the above section as well
* open Network/Prefs
* In '''IPv4 Configuration''' tab - click Add - enter net0 / active tick / #?.device / Unit 0 / IP Mode = manual (important if default DHCP does not work automatically)
Make sure that any extra network names (e.g. eth1 or net1) should be deleted. If net0 already st previously, change net0 so that it shows associated with the appropriate device name like atheros5000.device or realtek8180.device. Having two entries here will cause sub-net problems.
* Go to '''Wireless''' tab and click on "Add" button.
* Insert network name (SSID your wireless network name use wirelessmanager to get it), select right "encyption" that is most likely "WPA".
* Key Type set as "Passphrase". i.e. type in your password for your router (aka access key).
* Unselect (no tick) "hidden" if it is selected, then apply. You may have to tick it if wireless does not work.
* Finally, Save and '''reboot'''.
For the best chance of success, set networking to start at boot, and then reboot with the USB adapter plugged in.
===USB Ethernet===
Open SYS:Prefs/Network and in the IPv4 Configuration tag (top table covers your usb stick)
* click Add button
* set Name as net0
* Tick Active box
* enter the usb-ethernet.device e.g. dm9601eth.device, usbpegasus.device or usbasixeth.device use SYS:c/devlist, '''Scout''' or trident prefs to get the correct spelling
* set Unit to 0 (which is usual but check the messages from the bottom of the Trident prefs whilst plugging the device in to determine the unit number otherwise)
* IP Mode is set to Get address from DHCP (make sure your router is set right for that)
'''or manual'''
* IP Address of network card, i.e. 192.168.0.xx or 192.168.1.xx (xx being greater than 1)
* Subnet netmask = 255.255.255.0
* click OK
There can be sometimes be boot failures when using USB ethernet - plug the USB device in after boot and save the network prefs to make it work again.
Lower part of IPv4 tab covers the router information
* IP Mode Get address from DHCP
'''or if manual settings'''
* Gateway (IP Address of router) = usually 192.168.0.1 or 192.168.1.1 but see router manual to make sure.
* first DNS = use 8.8.8.8, 208.67.222.222 (opendns) or 212.50.160.100
* second DNS = use 8.8.4.4, 208.67.220.220 (opendns) or 213.249.130.100
===USB Tethering via Android smartphone===
Go to AROS Network Prefs (IPv4 configuration tab) and write type in "usbrndis.device" in the "device" textfield of "Interface" sub-window, which appears when you add a new device (or modify an existing one). Select "Start Network during system boot" and saved the configuration, the Connection is immediate no reboot is needed.<br>
usbrndis.device is a resident device (virtually always there) in fact, a driver is not present in DEVS:Networks <br><br>
Plug in USB cable, go to Android settings and enable "USB Tethering" <br>
A reboot should not be necessary.
When restarting AROS, the Smartphone deactivates the connection and to access the network again have to reactivate it before starting the browser.
===Solving Issues===
[[File:MyArosTCP.png|thumb|Aros network setup diagnostics - why does it not work?]]
* In Network Preferences, have '''only one''' item in the IPv4 Configuration tab
* If using manual settings, make sure all numbers are correct, especially for IP address of the card/usb (changing the last number in chain of four)
* For any USB based networking, it is often necessary to save in Prefs/Network, reboot AROS and network support can begin
* For wired, make sure that the LAN-cable is plugged in before starting the computer
* If wireless, try getting closer to the router.
* Switch off the encryption option from your router then try wifi, if successful then your ip/dns is ok. If not then your ip/dns settings are most probably wrong or need to use one or more opendns numbers
* Replace detachable wireless antenna (best wireless option to buy if you can) with a stronger antenna ie. 5 dBi or 7 dBi
* Try with another computer/laptop/machine
Program Error C:WirelessManager
* Test with another OS
* Check that Wifi works before changeover (if possible)
* Check that socket and card are working
* Check if card is too new for laptop (date code on card MMYY blue askey date 2005-2007 etc)
Are you connecting with the Router ?
Check with protection off e.g. wps and wep to see if it makes a difference.
For USB wireless - stopping and starting may be needed...
<pre>
; $VER: AROSTCP-startnet 1.0 (01/08/06)
; AROSTCP-startnet (c) The AROS Dev Team.
;
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
; stop and restart
execute "sys:system/network/AROSTCP/s/stopnet"
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
run <NIL: >NIL: wirelessmanager realtek8180.device
</pre>
What IRQ number is assigned to the device? You can check with Tools/PCITool?
It's possible the BIOS hasn't set the right IRQ number. If you have a Linux CD/DVD handy, could you check if it boots with the options "acpi=off noapic nolapic"?
If the following does nothing, this will help us figure out why networking doesn't start automatically at boot
open a shell and run the following commands:
<pre>
echo ${AROSTCP/AutoRun}
echo ${AROSTCP/WirelessAutoRun}
echo ${AROSTCP/WirelessDevice}
</pre>
Please report the output, typically it will look like this
# True (explanation this variable is related to the "Start networking during system boot" checkbox in network prefs)
# True ()
# Devs:networks/atheros5000.device unit 0
If there's a problem with the AROSTCP package. What's the output of this?
ENV:sys/packages/AROSTCP
should return a string = Sys:System/Network/AROSTCP
By the way, a quicker way to check networking is working would be to run some shell commands such as:
<pre>
ping www.google.com
ifconfig net0
</pre>
The best way to list the available networks and diagnose / troubleshoot problems with connecting to a wireless network is to run WirelessManager manually. First uncheck the "Start networking during system boot" box in the Network prefs app, then save and reboot. Then run this in a shell:
C:wirelessmanager atheros5000.device verbose
or
C:wirelessmanager realtek8180.device verbose
and capture the output
If the above does not help, could you edit the file SYS:System/Network/AROSTCP/S/Package-Startup, and change ">NIL:" to ">T:wifi.log" on the WirelessManager line and add this as well Wait 5?
<pre>
if ${AROSTCP/WirelessAutoRun} eq "True"
Run QUIET "C:WirelessManager ${AROSTCP/WirelessDevice} >T:wifi.log"
wait 5
EndIf
</pre>
Then save, reboot and post the log file (T:wifi.log) here.
<pre>
c:wirelessmanager atheros5000.device verbose
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7)
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
Then it just sits there. Not sure what a normal dump looks like, I don't see anything that looks wrong in the configuration.
</pre>
looks like the driver isn't working with that card. Has anyone else successfully used that exact model number (AR2413)?
<pre>
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7):
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
*** [wpa_sm_init] sm->pmksa=02c66fd4 ***
Own MAC address: 00:01:36:15:ae:0c
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
Added interface atheros5000.device:0
State: DISCONNECTED -> SCANNING
Started AP scan for wildcard SSID
MLME: starting scan
MLME: scan channel 1 (2412 MHz)
sana2: sending MLME frame
Then it stops. Does this mean the router is not authorizing this NIC?
IRQ 4 (A)
</pre>
apparently locking up when the first frame is sent (a scan request).
<pre>
Devs/Networks/atheros5000.device:0
Initializing interface 'Devs/Networks/atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=12):
41 69 72 4c 69 6e 6b 35 39 33 30 30 AirLink59300
PSK (ASCII passphrase) - hexdump_ascii(len=8): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='AirLink59300'
*** [wpa_sm_init] sm->pmksa=0224e444 ***
Own MAC address: 00:1f:e1:42:e3:7a
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
[eloop_reg_timeout] Timeout is at 1317686594.160000
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
[eloop_reg_timeout] Timeout is at 1317686595.060000
[eloop_reg_timeout] Timeout is at 1317686604.060000
Added interface Devs/Networks/atheros5000.device:0
[eloop_run] Starting
State: DISCONNECTED -> SCANNING
Starting AP scan for wildcard SSID
MLME: starting scan
[eloop_reg_timeout] Timeout is at 1317686594.160001
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.233000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.373000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.513000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.553000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.693000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.013000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.073000
EAPOL: disable timer tick
EAPOL: Supplicant port status: Unauthorized
MLME: scan channel 14 (2484 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.113000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.153000
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.213000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.353000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.493000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.533000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.673000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.993000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686596.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686596.073000
MLME: scan completed
</pre>
Is your network hidden? If so, did you enable the 'Hidden' checkbox in the network prefs? What distro version are you using?
<pre>
"ENV:sys/wireless.prefs" looks like this:
network={
ssid="testadhoc"
key_mgmt=NONE
wep_key0="12345"
wep_tx_keyidx=0
}
</pre>
If your router doesn't broadcast its SSID (hidden), you need to add this option to the network block of the wpa_supplicant.conf on your aros machine and make changes after # Example blocks:
scan_ssid=1
Here's a full description of all the [http://hostap.epitest.fi/gitweb/gitweb.cgi?p=hostap.git;a=blob_plain;f=wpa_supplicant/wpa_supplicant.conf config file options].
<pre>
ap_scan=1
network={
ssid="YOURESSID"
scan_ssid=1
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP
group=CCMP
psk=YOURPASSWORD
}
</pre>
<pre>
filter_ssids=1
ap_scan=2
network={
ssid="REMOVED"
scan_ssid=1
bssid=REMOVED
priority=100
mode=0
proto=RSN
key_mgmt=WPA-PSK
auth_alg=OPEN
pairwise=CCMP
group=CCMP
psk=REMOVED
}
</pre>
Error 6: Couldn't resolve host name.
Check Scout -> Devices and look at the device that you are using, in the OCnt column it should state 2 which means AROSTCP and Wirelessmanager are both accessing this driver. If 0 or 1, then uncheck the checkbox in Network prefs for starting networking at boot, save and reboot. Then run this is the shell:
C:WirelessManager realtek8180.device unit 0
some quirks setting up the wireless network as well
1) it's far better setting up either the wired OR the wireless network adapter as net0:, or weird things happen
2) it's better using fixed IP on the local network instead of DHCP
3) network setting must be placed in network setting panel in /prefs, using the wirelessmanager helped me finding available SSIDs, but not actually connecting to them
once done, reboot.
If previous setup is proving problematic
<pre >
SYS:Prefs/Env-Archive/Wireless.prefs
SYS:Prefs/Env-Archive/Zune/OWB.config
SYS:Prefs/Env-Archive/Zune/global.config
SYS:Prefs/Env-Archive/AROSTCP/WirelessDevice
SYS:Prefs/Env-Archive/AROSTCP/db/Interfaces
</pre >
Make a copy of these files and restore in case of problems.
Please try this test to check if you can connect to your router, ie established that the WiFi layer is working
̊̊̊̊Boot with networking disabled, by make sure that "Start networking at boot" in Network Prefs is unchecked (no tick).
̊ Run this in a shell: C:WirelessManager atheros5000.device VERBOSE
̊If the output of that command is too long to summarise here, you can redirect it to a file by adding >RAM:wifi.log to the end, then attach or paste that file here.
try running "status" in the shell and check that AROSTCP is listed/running
If AROStcp is not showing, then AROSTCP is not running. attempted to start it by clicking Use or Save in network prefs, or checking the "start networking at boot" box or typing into a shell.
Execute SYS:System/Network/AROSTCP/s/startnet
(run Status again afterwards).
The "cannot resolve hostname" will appear if you are blocked on the wifi network by the router as well as aros not being able to assign correct network address.
One way of testing this might be to disable the firewall in the router. you might also check the router how it sees the attempts aros do to speak to it. The easiest way to do that would be to manually give aros an IP number in the routers accepted range. and see if it shows up at all within the router.
Tests that can be undertaken to determine correct settings and functions
pciinfo
sanautil -d broadcom4400.device status
<pre >
ping <router-address> e.g. 192.168.0.1 (aka inet) or 80.237.146.33 (www.amiganews.de)
ifconfig net0
ifconfig net0 up
extras:networking/utils/sanautil/sanautil -d atheros5000.device status
WirelessManager atheros5000.device verbose >RAM:wifi.log
;to send the log to RAM disk to be read easier or if detected,
Run WirelessManager atheros5000.device >NIL:
Run WirelessManager atheros5000.device ssid="mynet1" >NIL:
C:WirelessManager realtek8180.device unit 0
</pre >
Please look at the task list in Scout, and check if WirelessManager and AROSTCP are running. Also look at the device list in Scout to check if realtek8180.device is open.
start tools/debug/sashimi, maybe it shows some debug messages when disconnection happens.
Firstly, let's take a look at what your setup most likely looks like, assuming you use a router. See diagram below:
<pre>
Internet <---------> home router <---------> computer
-----------external IP------------------internal IP-------------
</pre>
Okay, so what am I trying to show you with that diagram. A few things. Firstly, the IP address that connects you to the Internet is not the same one that connects you to your router. What happens is that your computer doesn't have a direct connection to the Internet, instead your router connects to the Internet, and your computer connects to the router.
You can see the external and internal IP addresses in these example settings...
* Default Gateway : 76.91.64.1 (external IP for ISP/Internet host)
* IP Address : 76.91.71.184 (external IP for home router)
* IP Address : 192.168.0.1 (internal IP for home router)
* Address = 192.168.0.161 (internal IP for computer)
As you can see, there are two internal IP addresses and two external IP addresses. This is because there is a client/server relationship, effectively one address is for the service (server) and one address is for the device trying to access that service (client).
The server addresses in your case are 76.91.64.1 (your ISP's address, serving the Internet), and 192.168.0.1 (your home router's address, serving your home network). The term gateway applies here, they are your gateway to those services.
Subnet masks are used along with IP addresses to determine which IP addresses are allowed access to a network. I did learn the more in-depth rules about subnet masks once (watched a CCNA vid), but I've forgotten about it. The basic level of understanding you'll need is easy to remember though. A subnet mask value of 255 means that portion of the IP address must stay constant, whereas a subnet value of 0 means any unassigned value up to 255 is allowed in the IP address.
By far the most common subnet value is 255.255.255.0. What this means is that the first three parts of the IP address you use to connect to a service must stay the same as the server/gateway address, and only the last section can change.
So if your router's internal IP address is 192.168.0.1, and the subnet mask is 255.255.255.0, the only addresses that will be allowed to be used on that network are between 192.168.0.2 and 192.168.0.255 (I think 192.168.0.0 is reserved for other uses).
Final point to make is about DHCP (a.k.a. dynamic IP) vs static IP. A server/router using DHCP gives a device that connects to it an address within the acceptable range. It usually starts with the lowest numbered free address, so with your router it'll give the first device that connects to it 192.168.0.2, the next device 192.168.0.3, and so on. Static IP addresses are where you set the IP address you want to connect with in advance.
When using static IP addresses on a router where DHCP is active, it's good to use a high number to avoid conflicts with other devices that are connected to your network, to reduce the risk that both devices will try using the same IP. That's why your current choice of 192.168.0.161 is good, unless you have over 159 devices connected on your current network!
Okay, so what's the next step. Well, if you can use ping, I'd suggest pinging 192.168.0.1. If you get a positive response it means you're connected to your router, if you don't get a response it means the connection between your router and your computer is at fault.
Documentation on configuring the AROSTCP environment further can be found [http://en.wikibooks.org/wiki/Aros/User/Networking here]
===File Sharing===
As AROS knows only a few filesystems (FFS, OFS, SFS, PFS (amiga only), FAT12, 16, 32, Microsoft NTFS (windows), UDF (Blu-ray)).
The others in regular use like MacOSX hfs+, Linux ext2/ext3 and ext4, Haiku BeFS provide a problem in transferring files.
Linux can access SFS partitions but it needs to be compiled. The latest full source are [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ here]. It compiled fine with a 2.6.30 kernel in Puppy Linux 4.31.
An alternative, is to use a FAT32 partition to share. Setup a 4G FAT32 partition using HDToolbox for sharing, and the rest of the space as SFS for an Aros install. It works very well.
Files could be transferred via TCP internet network.
====SMB2/3====
With Windows you can share one folder or all folders of the "Public" user.
On Windows what is important is to enable sharing (Network and Sharing Center).
AROS Mountlist should look lke this
<pre>
Handler = L:smb2-handler
StackSize = 65536
Priority = 5
GlobVec = -1
ACTIVATE=1
Startup = "smb://UserAcc:password@PCShare/Sharefolder"
</pre>
which could also be
"smb://UserPC:password@192.168.x.x/Public"
or
"smb://UserPC:password@Name-PC/Public"
so
"smb://UserPC:password@192.168.1.158/Folder"
or
"smb://UserPC:password@Name-PC/Folder"
After you have configured a share generates a DOSDrivers it is named "SMB0" which includes the setting, and at each reboot it is Mounted. You can still delete the DOSDriver by hand, is located in Storage/DOSDrivers, the file "ServerAutoMounts", in ENV:AROSTCP which indicates the DOSDriver to be mounted, should also be deleted.
The per-mount files are written to ENV:SMB or SYS:Storage/DOSDrivers. There is also additional file ENV:AROSTCP/ServerAutoMounts which states what will be presented to the end user.
====Old SMBFS====
e.g. to connect to a NAS share such as \\NASBOX\Shared use -:
SMBFS WORKGROUP=<YOUR WORKGROUP NAME> VOLUME=<AROS volume name to use>: SERVICE=<UNC Path to connect to>
SMBFS WORKGROUP=MYNET VOLUME=Shared: SERVICE=//NASBOX/Shared
And you will then have an icon appear on your desktop for the volume name you have chosen.
You can put the above script into wbstartup or
give it an icon, change it to a 'project' and give it the default tool c:iconx
Open a shell and type copy sys:script.info "sys:wbstartup/YOURSCRIPTNAME.info"
This should create an icon for your script file.
Now right-click on your script and select 'information'.
Change 'tool' to 'project', put 'c:iconx' into the 'default tool' box, click save
The reason being that scripts need to be opened with 'execute SCRIPTNAME' (or 'iconx') whereas the programs started from wbstartup are opened using 'run PROGRAMNAME'. It's the same as trying to start a command-line tool from the workbench by double-clicking it.
====Setup ISO images within AROS====
Use [http://archives.aros-exec.org/index.php?function=browse&cat=driver/storage DiskImage] which supports many cd image formats ISO, CCD, MDF/MDS, CUE/BIN, NRG and UIF. To mount CD or DVD images use below....
<pre >
# Rename your iso 'Unit0' (note no extension).
# Do 'View/All files' on you Aros partition. You should now see a folder called 'Diskimages'. Copy your renamed iso to there.
(Alternatively, you could type at the shell 'assign FDSK: xxx', where xxx is the location of your iso.)
# From the shell, type 'mount CD0:' and the iso should appear on the Wanderer desktop. You can now access it like a real disk.
</pre >
assign devname: dismount
Assign DOSVOLUME: remove
[http://aminet.net/package/disk/misc/unmount-0.1 unmount] most filesystems work but SFS lacks support for ACTION_DIE packet
If you are using an IcAros install, the startup scripts are set up to wipe the Diskimages directory on boot, so its worth keeping a second copy of the iso somewhere else. Alternatively, you could set up extra mountlists for additional iso images. I've made a file called iso1 in the Aros:devs directory that contains the following text:
<pre>
/* Entry for ISO image */
ISO1:
FileSystem = cdrom.handler
Device = fdsk.device
Unit = 1
LowCyl = 0
HighCyl = 0
Surfaces = 1
BlocksPerTrack = 1
DOSType = 0x41434400
Activate = 1
#
</pre>
Then I just need an iso called 'Unit1' (corresponding to the 'Unit = 1' entry in the mountlist) in Diskimages (or wherever I assign FDSK: to) and to mount I type in at the shell:
Mount iso1: from devs:iso1
Of course, if you create mountlists for ISO2, ISO3:, etc. (with the corresponding change to the 'Unit = ' line) you can have as many isos mounted as you wish. I just call mine ISO1: etc. to distinguish them from the real CD drives
==Video Guides==
Video demonstrations and tutorials covering:
:00. '''Introduction'''
::[https://www.youtube.com/@jamesmattson6813/videos Various Aros Installs],
::[https://www.youtube.com/embed/j8EmSEby0Rg AROS repo in gource, view of AROS dev commits from 1997 to 2025], [http://www.youtube.com/watch?v=Vx_zqlBow40&feature=related Gource view of AROS 1997 up to 2009],
::[http://www.youtube.com/watch?v=s1RsvEm7UrU Why an Amiga OS in 2011],
::[https://www.youtube.com/watch?v=1W886mheV74&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Johan Grip on early days of AROS x86], [https://www.youtube.com/watch?v=mXaKDhtTTqQ&t=14s&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Michel Schulz on Aros and PiStorm],
:01. '''Installation'''
::[https://www.youtube.com/watch?v=M7YjufrJqDs Aros One install], [https://www.youtube.com/watch?v=iIMguHTdC5E Aros One USB install], [https://www.youtube.com/watch?v=ZNXauy5m5Wc Aros One install], [http://vimeo.com/11013489 Modify Grub boot],
::[http://www.youtube.com/watch?v=wyQVeyXIywc&feature=channel iMica Silent Pt3], [http://www.youtube.com/watch?v=o2AnkoflY14 Wipe whole drive and Install - warning loss of data on drive],
::[http://www.youtube.com/watch?v=OVXm6_-witQ VirtualBox install], [ VMware install],
::[http://www.youtube.com/watch?v=0k2PEmT8I14 Broadway AROS Install],
::[https://www.youtube.com/watch?v=PtDiXhjSIfs Is Aros Icaros a choice?],
::[ driver install],
::[http://www.vimeo.com/10491104 HDAudio install but needs account], [],
:02. '''Amiga Basics'''
::[http://www.youtube.com/watch?v=TY8mWxwzH5o Screens tutorial],
::[https://m.youtube.com/user/AMIGASYSTEM/videos General], [ Dos Scripts tutorial], [http://www.youtube.com/watch?v=hPT7SmVEpjc OS 1.2], [http://www.youtube.com/watch?v=n6kX3FqH8Ww&feature=related OS 1.3],
:03. '''Customisation demos'''
::[https://www.youtube.com/@AMIGASYSTEM/videos Prefs tutorial], [ Decoration tutorial], [http://www.youtube.com/watch?v=Dn5C8G3aDXU Scalos],
:04. '''Setting up''' internet access and surfing the web, FTP, IRC and Mail apps
::[ Network Prefs], [ AirCOS tutorial], [ jabberwocky tutorial],
:05. '''Native bundled Games and Applications'''
::[http://www.youtube.com/watch?v=aYlFv2B-VXc 3D Games], [http://www.youtube.com/watch?v=MXK7wwhd-R0 Latest Games], [http://www.youtube.com/watch?v=RUgiVThv23Q&feature=mfu_in_order&list=UL PrBoom GL], [http://www.youtube.com/watch?v=0s7u8TPy7V4 Assault Cubes], [http://www.youtube.com/watch?v=fih6aCXKeqs Cube 2], [http://www.youtube.com/watch?v=-X0ay0MGOms DosBox on Aros], [http://www.youtube.com/watch?v=7nKduDjf14k Oct 2010],
::[http://www.youtube.com/watch?v=FziV2z_uxnQ Apps Pt 1], [http://www.youtube.com/watch?v=xs37_nfa5CI Apps Pt 2], [http://www.youtube.com/watch?v=Bn59_VvbQR0&feature=related Apps Pt 3],
::DOpus4 [http://www.youtube.com/watch?v=aSRybWjrrME DOpus 4],
::Milkytracker [http://www.youtube.com/watch?v=VxBOEPzpdKg&feature=related Laying Down Base Tracks],
::[http://www.youtube.com/watch?v=k2uKQ0-ieOE Audio Evolution 4 in action], [http://www.youtube.com/watch?v=Zq4r9k0_jZI Quick Videos],
::[http://www.youtube.com/watch?v=gGKCFZcIc0I&feature=related ScreenRecorder], [http://www.youtube.com/watch?v=974c2e-Fqak&feature=related TV out Tests],
::[http://www.youtube.com/watch?v=fjq8ct5d5IY AmiFIG], [http://www.youtube.com/watch?v=h0rHvPhYJo4&feature=youtu.be ZuneFIG],
::[http://wiki.povray.org/content/Documentation:Tutorial_Section_1 POVray Tutorial 1],
::[http://www.youtube.com/watch?v=Jk-ZNLfJsvQ pt 1, jan. 2008], [http://www.youtube.com/watch?v=nWRy33g1R7Y pt 2, feb. 2009], [http://www.youtube.com/watch?v=r5PbhCtm4vE pt 3, feb. 2010],
::[https://www.youtube.com/watch?v=G7_FJUoQ89o Hollywood programming], [], [], [],
::[], [], [],
::[], [], [],
::[], [], [],
:06. '''Commercial software available'''
::[http://www.youtube.com/watch?v=fKXY9B4R43s AntiryadGX 3D Game Editor],
::[http://www.youtube.com/watch?v=TMS9NDzwm5U BOH indie Game],
:07. '''Running classic amiga apps and games'''
:: Amiberry [], [],
::[http://vmwaros.blogspot.com/2008/11/introducing-amibridge.html Intro Amibridge], [http://www.youtube.com/watch?v=ee2PWvCZeLo Old Amiga Apps], [http://www.youtube.com/watch?v=ee2PWvCZeLo Why Janus UAE is good],
::[https://www.youtube.com/watch?v=VhlsNSYSuDg DPaint tutorial]
::[http://vmwaros.blogspot.com/2009/11/can-icaros-play-my-amiga-games-and-why.html Play Amiga Games], [https://www.youtube.com/watch?v=XTaZCNOvCnE],
::[http://www.youtube.com/watch?v=tMehS77LXQ4 Pagestream Introduction], [http://www.youtube.com/watch?v=284-w3hTzII Pagestream Tutorial 1], [http://www.youtube.com/watch?v=mlwEGwhZzl4 Pagestream Tutorial 2],
::[http://www.youtube.com/watch?v=iIcrIjPOctc Catweasel Mk4 PCI Part 1] and [http://www.youtube.com/watch?v=BaitHeL6bEA Part 2],
:08. '''Misc and History'''
::[http://www.youtube.com/watch?v=d6mDXKU29w0 Mum uses old AmigaOS Workbench 1.1 (1986)], [http://www.youtube.com/watch?v=DaRkacQ-YMg Why an Amiga 500 (1987)], [http://www.youtube.com/watch?v=k5CYsgVCzYY an Amiga 2000 (1987)],
:09. '''Misc Shows and Events'''
::[http://www.youtube.com/watch?v=klgVSWKs4kE VCF 2010], [https://www.youtube.com/watch?v=eQ3d5qR-Hv8 24:06 Jason McMullan at amiwest 2012 about AROS], [https://www.youtube.com/watch?v=jpQO7XSfAv4 Aros SMP multi core amiwest 2013], [], [https://www.youtube.com/watch?v=gFRtAAmiFbE], [https://www.youtube.com/watch?v=DjdUEyjx8GM], [https://www.youtube.com/watch?v=ydYDqZQpim8], [], [https://www.youtube.com/@uminekoshouten/featured], [https://www.youtube.com/shorts/NfoY023w-vE],
:10.
::[https://www.youtube.com/shorts/6qJTNW4-6GY]
===History===
The project was originally started by a small group of Amiga [http://www.amigahistory.co.uk/aros.html enthusiasts] in 1995. These individuals were mainly computer-based college university students at the start, though that student trend has diminished since. An interview with Aaron Digulla [http://arosshow.blogspot.com/2006/12/interview-with-aaron-digulla-who.html here]
* 1992 Commodore folds
* 1996-1998 much of the early years was concerned with exec, dos and intuition libraries.
* Early 1999, Haage & Partner used parts of the AROS code in AmigaOS 3.9.
* March 2001, floppy disk images of AROS became available.
* Early 2002, AROS changed its name from Amiga Replacement Operating System to Amiga Research Operating System
* June 2002, AROS devs decided to use Zune (MUI 3.8 rewrite) as the GUI system.
* November 2002, Eric Schwartz drew Kitty for AROS usage.
* Early 2003, AROS.org underwent a graphics facelift.
* Late 2003, GCC C compiler arrived.
* Early 2004, Aros-Exec opened.
* Early 2005, Aros Max bootable CD arrived.
* Late 2005, SFS filesystem ported and allowed fast access to apps and network support arrived
* Early 2007, AROS.org underwent another graphics facelift.
* Mid-2007, AROS changed to AROS Research Operating System after A.Inc. sued Hyperion with a trademark violation.
* Late 2007, the hard disk installer added and VmwAROS (later called Icaros Desktop) distro launched.
* Early 2009, Our first usable web browser (OWB)
* September 2010, first wireless support appears and AspireOS started as a distro
* Early 2012, the first paper-cut bugfix and Fab's Odyssey Web Browser ported
* Early 2017, work started on utilising the addition cores on modern CPUs starting with the 64bit x86 PC version
* Mid-2017, m68k port optimized for the Vampire 2 / Apollo accelerators (68080 AMMX FPGA)
* 2018 The old AROS Exec website closed and a new one opened
* 2019 AROS One x86 32bit distribution started and now with USB install version
* Early 2021, backport of more features of 32bit PC ABIv1 into 32bit PC ABIv0 (Aros One 1.5 and above)
* 2025 year of 64bit pc builds and porting 32bit applications to 64bit ABIv11
* 2026 update of [https://www.youtube.com/watch?v=6FKTL068ULM&pp=ygUPYXJvcyBhbWlnYSAyMDI2 nvidia nouveau driver for 64bit PC]
===Bounties===
To help inspire developers with both ideas and monetary incentives, rewards are offered for the successful completion of "bounties" (requests for missing/new functionality) chosen by the community and handled by [http://power2people.org power2people] (formerly done by TeamAROS). A monthly option is [http://www.power2people.org/funds/aros/ here].
Future goals for AROS include expanding its underlying retargetability to support even more diverse architectures, provide memory protection features and user level file security, SMP and many other wonderful features missing from AmigaOS — while still providing as much source level compatibility as is possible (however it is accepted that to achieve some goals code certain things may require a little recoding).
[http://www.ohloh.net/p/aros/contributors Developers] come and go as with any open source effort and we would like to thank them for their efforts...
;1996-2000:In DigullaA (coordinator), GripJ, TempletonI (BSD), SchulzM, RittauS, voordenDagL, HolmM, JohanssonT, VanIngelgomH, SteigerwaldM, BortasP, deJongK, AlfredssonJ, InnocentiB,
;2001-2005:In [http://chodorowski.com/adam/aros.html ChodorowskiA], StegerG, BergerS, HeutlingS, AlemagnaF (gcc), VerhaegenS (rexx), KielH, MatheussenKS (CAMD), SzczygielskiP, ErikssonP, LeCorfecD (Zune), BauerS (Zune), FurlongW, GustafssonJ, AndrewsN, CafferkeyN, GierichM (jpeg), PattonJ, ParsonsM, DietrichJ, SeilerT, BischoffL, LorentzenNH, AdamO, BerglundH, SmithP, HolmenD, BlomM,
;2006-2010:In FedinP, RusslerM, SzymczykS (owb), SmiechowiczK (openGL), WeissM, NorrisR, BrunnerO, WiszkowskiT, GreppinA, [http://www.fukt.bsnet.se/~bearsoft/ Bearsoft Björn Screwelius], ErbY, CharletF, HodgesC, [http://aros-exec.org/modules/newbb/viewtopic.php?topic_id=4819&forum=18&post_id=43103#forumpost43103 HokstadV], McMullanJ (m68k), WilenT (m68k),
;2011- :In MuijzenbergPHvanden, ALB42, JonesEM, weiju, DizzyofCRN, wawa, miker,
* 1996 - The linux hosted version for i386 was the first to arrive
* 1998 - i386, The native version for i386-based PC AT computers and compatibles.
* 2004 - x86/64, The native version for 64-bit (x86_64, amd64) PC computers.
* 2008 - sam440/ppc, The native version for Sam440EP, Sam440EP Flex and Sam460ex computers.
* 2009 - efika, The native version for PowerPC Efika computers.
* 2010 - m68k, The native version for m68k Amigas or WinUAE
* 2013 - raspi/armfh, early native version for ARMv6 based Raspberry Pi computers.
* 2017 - x86/64bit smp
Debugging capture serial debug at all (especially with sysdebug=all or --sysdebug=all) to see it displayed on screen
* yes, usb -> rs232 adapters can work most of the time, some of the cheapest ones are not fully compatible with all rs232 devices to capture to another device
* you will need a null modem cable (or a null modem adapter usually female to female) in addition to the usb -> rs232 adapter (usb adapter is a normal modem ie. the pins are not crossed over)
Normal modem cable - straight connection DCE
<pre>
Pin 2 -> Pin 2 RXD
Pin 3 -> Pin 3 TXD
Pin 5 -> Pin 5 GND
</pre>
Null modem cable connections DTE
<pre>
Pin 2 -> Pin 3
Pin 3 -> Pin 2
Pin 5 -> Pin 5
</pre>
(9pole SUB-D)
<pre>
serial ser: (amiga/aros) tty2 tty1USB0 (linux) COM1 (windows) (depends on the os being used)
speed baud transfer rate 9600 38400 lower baud might be more successful
data bits 8
stop bits 1
parity none
handshaking flow control - none xon/xoff (most likely) rts/cts dsr/dtr (pins not connected so should not work)
</pre>
*You cannot use compiled aros X86-64 bit software (when ready) on aros X86 32bit. PPC compiled software on X86 and so on.
*68k is tested with the UAE emulator (WinUAE) but some tests are done on native 68000 based Amigas and others.
*PPC support is very limited to certain devices.
If you use the WBStartup, you have to delete the other icons in the folder (readme etc..) and you have to add in the Icon Tooltype the parameter DONOTWAIT
If you use user-startup instead, you need to add the attached command "after assignment to LUA"
C:WBRun DH1:Extras/Utility/WeatherBar/WeatherBar >NIL:
Change the command to match your WeatherBar path.
<pre>
PATH sys:Utilities/WeatherBar ADD
run >nil: lua:amilua weatherforecast.lua
</pre>
To enter data your Country or City, ist with city_id numbers can be found [http://bulk.openweathermap.org/sample/city.list.json.gz here] or you need to go to [https://www.bbc.com/weather BBC Weather], once you type the name of your city or town in the appropriate tab, and press enter, the 7 numbers to be added in the "WeatherBar" will appear on the Browser url address bar above
Unicode v16.0 emojis are not supported but [https://github.com/jens-maus/libcodesets codesets.library] provides
<pre>
internally supported (hardcoded) charsets/codesets are: (conversions are possible from and to each codeset):
AmigaPL – Polish (Amiga)
Amiga-1251 – Cyrillic (Amiga)
ISO-8859-1 – Western European
ISO-8859-1+Euro – West European (with EURO)
ISO-8859-2 – Central/East European
ISO-8859-3 – South European
ISO-8859-4 – North European
ISO-8859-5 – Slavic languages
ISO-8859-9 – Turkish
ISO-8859-15 – West European II
ISO-8859-16 – South-Eastern European
KOI8-R – Russian
UTF-8 – Unicode
In addition, external charset table files can be stored in LIBS:Charsets or loaded by an application from PROGDIR:Charsets. The charset files included with this distributions are:
IBM866 – Cyrillic (cp866)
ISO-8859-7 – Greek (LatinGreek)
ISO-8859-10 – Nordic (Latin 6)
windows-1250 – Central/East Europe (Windows)
windows-1251 – Cyrillic (Windows)
windows-1252 – West European (Windows)
</pre>
Icaros 2.3 USB image needs a header stripped so it can work correctly
dd bs=512 skip=1 status=progress if=icaros_light_2-3-0_pendrive.bin of=/dev/sdxy && sync
Scalos
<pre>
-------------------------------
{ "STRING", "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K",
HALIGN LEFT | CENTER | RIGHT
VALIGN TOP | CENTER | BOTTOM
STYLE NORMAL | BOLD | ITALIC | BOLDITALIC
FONT // font specification - format: "fontname.font/size"
-------------------------------
arguments for STRING SRC
"diskstate",
"diskusage",
"diskusagefree",
"diskusageinuse",
"diskusagepercent",
"fibfilename",
"filecomment",
"filedate",
"fileprotection",
"filesize",
"filetime",
"filetypestring",
"iconname",
"linktarget",
"plugin" pluginname <optional plugin arguments>
"versionstring",
"volumecreateddate",
"volumecreatedtime",
"volumeordevicename",
-------------------------------
arguments for HIDE
"novolumenode",
"isempty" (some STRING)
-------------------------------
all internal commands:
"about",
"backdrop",
"cleanup",
"cleanupbyname",
"cleanupbydate",
"cleanupbysize",
"cleanupbytype",
"clearselection",
"clone",
"close",
"copy",
"cut",
"delete",
"emptytrashcan",
"executecommand",
"formatdisk",
"iconify",
"iconinfo",
"lastmsg",
"leaveout",
"makedir",
"open",
"parent",
"paste",
"putaway",
"quit",
"redraw",
"redrawall",
"rename",
"reset",
"selectall",
"showallfiles",
"showonlyicons",
"shutdown",
"sizetofit",
"snapshot",
"snapshotall",
"snapshotwindow",
"unsnapshot",
"update",
"updateall",
"viewbydate",
"viewbyicon",
"viewbysize",
"viewbytype",
"viewbytext",
</pre>
{{status|50%}}
{{BookCat}}
dqlovksyodhjpu8jjzay81qq5p0wl05
4675858
4675856
2026-10-13T14:39:07Z
Jeff1138
301139
4675858
wikitext
text/x-wiki
{{ArosNav}}
==What is AROS==
Google translation
[http://translate.google.com/translate?hl=en&sl=auto&tl=de&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs German], [http://translate.google.com/translate?hl=en&sl=auto&tl=nl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Dutch], [http://translate.google.com/translate?hl=en&sl=auto&tl=fr&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs French], [http://translate.google.com/translate?hl=en&sl=auto&tl=it&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Italian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=da&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Danish],
[http://translate.google.com/translate?hl=en&sl=auto&tl=es&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Spanish], [http://translate.google.com/translate?hl=en&sl=auto&tl=hi&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Hindi], [http://translate.google.com/translate?hl=en&sl=auto&tl=zh-CN&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Chinese],
[http://translate.google.com/translate?hl=en&sl=auto&tl=ru&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Russian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Polish], [http://translate.google.com/translate?hl=en&sl=auto&tl=ja&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Japanese], [http://translate.google.com/translate?hl=en&sl=auto&tl=ko&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Korean],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pt&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Portuguese],
*Computer Hardware
*AROS (operating system)
*Applications and Games
*User
[http://www.osnews.com/story/15819 AROS] is one of the intermediate levels between the computer hardware and the user. It is an open-source, clean-room implementation of AmigaOS 3.x that can be run on many different computer architectures. It runs primarily on PC x86 32bit and 64bit but also on amiga motorola 68k and compatibles, some ARM like the Pi and Apple Silicon, RISC-V and some old PowerPC.
This page will cover enough to be able to write the downloaded image to your preferred media, to run a LiveUSB, LiveCD or LiveDVD on your office/home PC (Live meaning you can test without changing your existing setup) and, ultimately, to use it.
Intel / AMD PC hardware support mostly covers the years 2000 to 2024. At the moment, AROS is '''not''' recommended to be '''installed''' on a working vital data holding machine. Instead, writing to and booting from a '''USB stick''' could be a much better option.
AROS is an hobby OS and can co-exist with Windows(TM), MacOSX(TM), Android(TM) or Linux(TM) and act as an alternative.
Unfortunately, Aros has few developers so upgrades and improvements can take [https://sourceforge.net/p/aros/mailman/aros-cvs/ time to appear].
AROS core is now [http://en.wikibooks.org/wiki/Aros/Developer/IncompleteAPIs ~80%] finished and is usable, so keep in mind that the software is still considered ALPHA/BETA and in constant development. Currently AROS is fun to play with on a curiosity level, but it is also interesting to program. AROS has some multimedia features and has internet access.
Most importantly, use AROS to its maximum potential as it stands now, find ways to have fun with it and share your experiences.
Good Sites to visit
: [https://www.arosworld.org/home.php Aros World User forum]
: [https://arosnews.github.io/ AROS News]
: [https://www.facebook.com/ArosWorkshop/ Aros Workshop],
: [https://www.osnews.com/topic/amiga-aros/ OSNews]
: [https://www.reddit.com/r/aros/ Reddit]
: [https://archives.arosworld.org Aros Archives]
: [https://aminet.net/ Aminet]
: [http://www.amiga-news.de/en/ English translation of German site]
: [https://aros.sourceforge.io AROS] with [https://aros.sourceforge.io/download.html ABIv1 downloads]
: [https://github.com/aros-development-team/AROS Aros ABIv1 Codebase]
: [https://github.com/aros-development-team/AROS/issues register ABIv1 issues] and [https://sourceforge.net/p/aros/bugs/ old defunct bugs notification site]
: [https://sites.google.com/view/arosone Aros One x86, x64]
: [https://tinyarosdistro.flazio.com/ Tiny Aros x86 and x64]
: [https://arosnews.github.io/aros-portable/ AROS portable USB3 stick images of hosted Aros One x86 and x64 on debian]
: [http://vmwaros.blogspot.com Icaros Desktop x86 now on sabbatical, very old edition]
: [https://sites.google.com/site/arosaspireone AspireOS, of the netbook Aspire One, very old edition]
: [https://github.com/deadwood2 Deadwood's builds], [https://www.axrt.org/download/aros/v11/ v11 64bit PC builds], [https://axrt.org/downloads-aros Updated i386 32bit PC builds],
: [https://github.com/ezrec Ezrec x86 m68k mirror of old svn version]
: [http://arosalive.blogspot.co.uk/p/10-basic-aros-how-tos-tutorials.html Basic How To guides]
: [http://arosgamer.blogspot.co.uk/ AROS Playground], [http://thewetmachine.net/tag/aros/ Jess Wet Machine], [https://aroshacking.wordpress.com/ Jon Robertson's AROS Experiences and FPC Free Pascal], [],
:[http://www.apollo-accelerators.com/ Apollo Accelerators m68k], [http://www.amigablogs.net/ Amiga Blogs], [http://blog.a-eon.biz/blog/ Trevor Dickinson blog],
: [https://forum.amiga.org/ Amiga OS AOS 3.x forum]
: [http://eab.abime.net/ EAB Amiga]
: [http://www.amigaworld.net/ AmigaWorld]
: [http://www.ppa.pl/ Polish Amiga Like News]
: [http://www.apollo-core.com/ Apollo Forum]
: [https://amigaalive.blogspot.com/ AmigaAlive]
: [https://www.amigalove.com/software Disk Mags]
: [https://amigachristmastree.ultimateamiga.com/ Xmas Amiga Game Jam]
: [https://www.reddit.com/r/amiga/ Amiga]
== Distributions aka Distros ==
For end users there are distributions (ready made with selected apps aiming to be easy to use), mostly created and maintained by one person in their own workflow/style. They reuse the nightly boot compiles to suit their needs and possibly other end users. You are free to create your own if required.
* For native 64bit Intel/AMD: [https://sites.google.com/view/arosone Aros One x64], [https://tinyarosdistro.flazio.com/ Tiny Aros],
* For native 32bit Intel/AMD which will run on 64bit machines: [https://sites.google.com/view/arosone Aros One x86], [https://www.tinyaros.it/ Tiny Aros],
* For native 68k [https://sites.google.com/view/arosone Aros One m68k], [http://www.aros-platform.de/ AROS Vision],
'''Please, keep in mind that the distros listed above use a different ABI (abi v11) , which is NOT binary compatible with the official ABI V1.'''
* For hosted Linux usb drive image [https://arosnews.github.io/aros-portable/ x64 Debian hosted version of Aros One],
* For hosted ARM there is [https://github.com/jonx/AROS-AArch64/releases alpha for Apple Silicon] and [https://aros.sourceforge.io/nightly1.html RaspberryPi Pi3, Pi4, Pi400, Pi5, 500+ raspi-aarch64-system native 64bit]
AROS was originally developed on Linux but can run on an Intel-based Linux distro as an app. As time has gone on, it can be run as an app on many more operating systems (Windows, FreeBSD, Linux and limited on MacOS). This may sound strange: an OS running on top of another OS.
Basically, this is to take advantage of drivers (audio, internet, graphics, etc.) and compiler environments, in the existing OS, with which people may be already familiar. The term we use for what AROS does is "Hosted".
AROS Native is the term coined to describe AROS being run without any OS underneath it. It runs alone just like AmigaOS(TM) did. As this version does not benefit from "Hosted" drivers, dedicated ones have to be ported/written. Hence the smaller range of supported hardware / peripherals. We have other pages highlighting this support
AROS is open source so basically everyone can take part. The source is public on github and there are new commits most days. AROS is automatically compiled daily, result are the nightly builds hosted on Sourceforge. The nightly builds are only used for testing changes, testing software and the starting point for distribution maintainers or even your own distribution. They are very basic, miss some functionality and apps like web browsers and generic general appearance which can be changed.
* The [https://sourceforge.net/projects/aros/files/nightly2/ Nightly2], [http://aros.sourceforge.net/download.php nightly builds File Release Service] or [http://aros.sourceforge.net/downloads/ Sourceforge Project Web builds] are made automatically every night directly from the Github and in the past, SVN (Subversion) tree and contain the latest code for the AROS operating system. It should be noted that the builds have not been tested in any way and can be horribly broken but usually are not.
*ABIv1 standard for most nightly builds, it is where the most work is done by developers
*ABIv11 offspring aka fork of 64bit PC ABIv1 i.e. another PC 64bit build
*ABIv0 standard for PC 32bit intel / amd PC distributions for historic reasons
==Media==
AROS media tends to boot in this tier list of media types, first internal HDD SSD, CD DVD drive, and finally usb drive (last two can depend on bios boot order)
* USB .VHD
[https://sites.google.com/view/arosone Aros One x86 and x64], with md5 below
<pre>
0a656d53a9c902e9934000d8392e30ec *ArosOne-USB-1.3-64Bit.zip
7dd7119ab3e56d75ee852c137226b4d7 *ArosOne-USB-v1.2-x86_64-v11.zip
cf906eeaad4a83b3520b1896bdc6b0d3 *ArosOne-USB-v1.1-x86_64-v11.zip
e2eb8fe8cfd61c567b0152a61cf85251 *ArosOne-x86-v2.8-USB-IMG.zip
559909c75c2f56472c74267a7d075355 *ArosOne-x86-v2.7-USB-IMG.zip
93da5898508c1a8c05bb8991ab7bd117 *AROS One Image-USB-2.4.zip
59fcabd7090e47f12d54f7eb78cf0f45 *ArosOne-x86-v2.2-USB-Image.zip
24fb8de726ae8fc5fe5bac6d30f03dc5 ArosOne-x86-v2.0-USB-Image.zip
f3d725e990072edce633b59747911b6b ArosOne-x86-v1.8-USB-IMG.zip
e089a24ae310e92fcc407a0125602ce8 Aros-One x86-IMG-USB-v1.6.zip
</pre>
[https://tinyaros.flazio.com/ Tiny AROS]
22bc993625b7c75b17263c0cc7e7baaa *Tiny Aros_copy.vhd (March 2024)
There is usually a vhd image inside the zip that can be written to USB sticks which is so much faster than the old ISO written to physical CD DVD method. This .vhd can be written to an USB stick / ssd with these pieces of software below but it will erase the previous contents from the usb
Windows - [https://www.raspberrypi.com/software/ RPi Raspberry Imager, use custom and see all files], [https://hddguru.com/software/HDD-Raw-Copy-Tool/ HDD-Raw-Copy-Tool], [https://rufus.ie/ Rufus up to version 3.20 may work with VirtualBox HD vhd images with Win7 but not some Rufus 4.x versions], [https://etcher.balena.io/ Balena Etcher but may spy on you],
Linux - [https://www.raspberrypi.com/software/ Raspberry Imager Ubuntu], Suse Image / Multi writer, dd,
Mac -
* Virtual Machine .ISO or CDs DVDs
The native iso images are currently not compatible with Ventoy, Yumi, MultiBootUSB, Easy2Boot E2B, or similar
<pre>
617a905b1665128c5e05f94dcc48e7f1 *AROS-One-v1.3-64Bit-v11.zip
11c8a147fcad7ecf52ae3a43e1934b69 *ArosOne-DVD-v1.2-x86_64-v11.zip
f93053d3b9ccf304d7e6ac3389e1987b *ArosOne-DVD-v1.1-x86_64-v11.zip
86d808a40dc7be389a758799a9b4f595 *ArosOne-x86-v2.0-ISO-DVD.zip
f1fc8599ef6a39e5df394e0f41d55526 *AROS-One-x86-ISO-DVD-v1.6.zip
</pre>
You can use a virtual emulator like VirtualBox, VMWare to mount the iso image which can then be used to boot and/or install to USB.
No current software can write an AROS ISO to a Pendrive. The author of ‘Rufus’ (who used an Amiga 500 as a child) once tried, but when he saw the system composition, he said he was unable to do it.
The solution is to boot the ISO from a VM (WMware, VBox), then install the AROS build on the Pendrive, which will eventually become a Live Pendrive that can be booted on a PC.
The only precaution is that in some cases it is necessary to thoroughly clean the Pendrive of any partitions and remove any bootloader that is not AROS. The Pendrive must remain raw without any partitions.
You can clean the USB stick on a PC with a program that manages hard disks. You need to do a partition wipe. On some USB sticks, you can clean it with InstallAROS.
For some USB pendrives, please use a reputable partition editor to remove any and all partitions from a usb pendrive as HDToolbox cannot do this task sometimes with a wipe all option.
Previously the only installation option was CD-RW or DVD-RW, since the whole system can be burnt onto a single disk and can be reused when the next version is released. Good branded discs like Taiyo Yuden (later JVC) or Verbatim should be used to reduce frustration later. The days for this media is gone but kept here for information
Since nobody currently sells AROS on any other media, you will need access to a CD/DVD burner to create the installation disk yourself. After it is on a CD or DVD, then access and writing to USB pendrives becomes available (this should be viewed as an outdated or last resort alternative method now), as well as using good USB manufacturers like Sandisk, Kingston, etc. rather than some other no-names.
Try burning it to a CD-RW or DVD-RW using your CD/DVD burning program (most burning software have a burn iso option). The ideal writing speed is 2x or 4x, higher speeds can give errors and problems. Check the writing integrity of your CD or DVD if your software has an option to do so before going any further.
Standalone portable usb cd dvd drives do not boot physical burnt discs, please use an internal ide sata drive instead.
* SD-card
For [https://aros.sourceforge.io/nightly1.html ARM Pi Aros 64bit], copy the files onto a FAT32 formatted micro SD card.
==Booting==
The LiveUSB, and in the past LiveCD LiveDVD, is designed to trial (test drive) various operating systems without having to install them to your working system.
Since 2011, UEFI was introduced to replace the original PC BIOS which made booting media more confusing. Some changes in the UEFI/bios may be needed
*go into the bios using esc, f2 or f? and disable the Security -> Secure Boot and maybe apply option for Legacy IDE mode
*you may have to press F9, F10 or F12 or p on boot up to present a device boot options like USB or CD/DVD
*disable the Fast Boot config so it would recognize portable DVD-drive and changed the Boot-sequence
Secure boot was introduced by Microsoft and later consortium, control what operating systems work with Secure Boot via shims.
For Aros, it is best to disable and save the turn off change to Secure Boot (if you dual boot with Windows this will cause issues with further Window boots)
For the best experience, it is advised to install to another SSD than the one Windows resides on.
The grub part of the boot should be fully automatic, and you should see a multiple choice graphic card screen after 10 seconds for USB or 40 seconds CDs and DVDs.
If boot does not occur within a minute, please reboot and choose the VGA boot option as it relays a message stream so you can see where the issue lies.
After the grub graphics choice, AROS takes over the booting and any issues can arise here
If possible please use a branded usb pen drive as most of the time when we get reports of "crashes right after grub boot selection" it is mostly due to the recorded pendrive as they are made, notoriously on a will it work / will it fail nature, every time it is used.
<pre>
So one usb drive written may stop at a System halted. Reset the machine.
Or another pendrive will show give errors Smart Filesystem request - Volume 'Aros Live Drive' (DU0: usbscsi.device unit 0) There was an error while accessing this volume:
Or if a FAT32 partition present - FAT filesystem - Device USBSCSI0P1 has a read error on block xxxxxxxx -
</pre>
Sadly, no drive even branded are resistant or totally reliable, so the only solution is to try another pendrive, and possibly to repeat, until no errors.
It will give an indication on how reliable the usb drive could be.
=====Advice for various machines=====
Some of the stages involved and shown on the display in a typical AROS boot start up
<pre>
[MultiLoader]
[ELF Loader]
[Boot]
[HPET]
[Kernel:ACPI]
[Kernel:APIC-IA32]
[Kernel:SMP APIC]
[HiddStorage]
ACPI: ????
ACPI Error
[ACPI]AcpiOs????
[BattClock] Got RTC century offset 0x32 from ACPI
[PCI] Scanning bus ?
[AHCI] Sata
[Vesa] only if vesa is chosen as graphics option
[ATA] detect hd & cd drives
[ATA0?] ata-identity
[packet] fat.handler be.handler, etc.
[DOS]
[Storage:Bus]
[Storage:Controller]
[MSS] USB setup
[ehciInit] Port ? maps to controller ?
[I2C]
[ATI]
[drm] nouveau
[AROSTCP] if you have network driver prefs set up to start when booting
</pre>
; If boot fails, please give us some indication (pictures or videos) where the boot stops and the message(s) on screen.
AROS's native SATA/AHCI driver doesn't always work. If you get errors related to ahci.device, try disabling it. At your chosen boot entry in the GRUB menu, Press E, scroll down to the ahci.device entry, and add a # or ; at the start of that line or delete it with Ctrl-K. Then press Ctrl-X or F10 to boot.
If your disk isn't accessible at all with this change, you might need to change the SATA controller to IDE legacy mode in the BIOS: however, making this change will likely cause problems booting Windows on the same machine (if it's already installed). To disable ahci.device permanently, edit the text file "SYS:Arch/pc/grub/grub.cfg", and remove the ahci.device line from all boot entries you intend to use.
SATA AHCI Timeout while waiting for device to complete operations with BIOS SATA entry set to AHCI mode stops at "waiting for bootable media" screen, changing BIOS SATA setting back to IDE mode may allow it to continue booting
The ATA driver doesn't always work. If you get errors related to ata.device, try using the alternative in sys:devs/alt which is an older version. Press E when your chosen boot entry is highlighted in the GRUB menu, scroll down to the ata.device entry, and change it to read "module /Devs/Alt/ata.device". Then press Ctrl-X to boot. To make this change permanent, edit the text file "SYS:Arch/pc/grub/grub.cfg", and change the path to ata.device in all boot entries you intend to use.
Further options (removing the " ") to add to the GRUB menus to disable certain other components for debugging:
<pre>
Disable AHCI "AHCI=disable"
Disable NVME "NVME=disable"
Disable ATA: "ATA=disable"
Disable ATA: "ATA=nopci,nolegacy"
ATA safe mode: "ATA=nodma,32bit"
Disable IDE from SATA: "ATA=32bit,nosata2pata"
VIA / SIS with cdrom read io errors "ATA=nodma,nopoll"
noacpi all [PCI] devices to be invisible to AROS. disk drives work but network, sound won't
acpi=strict if there are issues with sound after boot
noioapic alternative to no acpi
Set AHCI "AHCI=force150/force300/force600"
Disable AHCI/SATA: comment out with a # ; or remove ahci.device line with Ctrl-K
Disable USB: comment out # ; or remove pciusb.device and poseidon.library lines with Ctrl-K
Disable native graphics: "nomonitors"
USB3 "USB=xhci"
</pre>
Other useful grub command line options - nomonitors, noacpi, vesahack, nopoll
Press Ctrl and X together (or F10) to exit and boot with the new options. Just experiment with different variations until successful. Those working options will need to be reused with every reboot of AROS until you can edit the grub.cfg and make it permanent i.e. install to hard disk or USB.
* If you use VESA mode, you can see the debug log if you add 'vesahack' to the command line. This will set up split-screen mode. In the upper half you'll see AROS screen, in the bottom - debug log.
* ACPI ie. PCI hardware - If you get crashes at early boot, try adding 'NOACPI' to the command line
If you're having boot issues and have a null modem cable and a spare pc, a boot log is always useful. Edit your grub line to include debug=serial but would try with an with sysdebug=all in the line later as it can cause issues booting on machines with sysdebug=all enabled (corrupts the cpu initialization).
However, if you feel you have found a genuine bug/fault in AROS that needs attention, please use the [http://sourceforge.net/tracker/?atid=439463&group_id=43586&func=browse bug submission form] to record as much information about what happened, why, and what hardware etc. you have so that people may try to assist you
For Virtual machines VMWare VirtualBox, etc., attach and press play to start the ISO image
If booting hasn't worked then it could be down to Bios/UEFI settings
=====nvme.device=====
Since 2018, nvme drives are standard on most machines
The requirement is that a PC can boot with legacy mode/BIOS at the moment - Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
This is still in testing and its' use should not be on or near precious own data
=====AHCI=====
Starting taking over since 2011 on a lot of machines
* Check that UEFI (replacement for PC BIOS) has options set to remove UEFI SecureBoot option and apply CSM
* SATA drive is set for Legacy or a mixture AHCI/IDE and not AHCI
AHCI sata can be very difficult to get working
Most Windows installs are already set to AHCI sata, changing this to a legacy IDE mode setting can help but please check if Windows will still boot. Some hardware like Lenovo laptops do not always like being set in legacy mode so only use as a last resort and aware of issues that can be caused.
Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
With a 16C/32T chip machine, disable SMT and it should boot.
=====ata.device for old BIOS's =====
Pre 2010 this was the de facto standard method of providing settings to the computer at a lower level
Some adjustments to the BIOS setup options are necessary (usually by pressing a key like DEL, F1, F2, F12 or ESC, p on the very early boot up of the computer).
*Adjust booting options like moving USB hdd, CDROM higher as it is quite often disabled or placed lower by default, i.e. USB hdd, CD/DVD are placed at the top above the hard drive. Try looking here [http://www.windowsreinstall.com/articles/bios/ Windows] or [http://www.hiren.info/pages/bios-boot-cdrom Bios] or [http://www.wikihow.com/Set-Bios-to-Boot-from-a-CD-ROM Boot] or web search "BIOS BOOT CDROM"
* At the '''SAME''' time, check if the SATA/AHCI option is set to Emulate or IDE Legacy, though this can have '''issues''' with any OS already on the hard disk. If in doubt, do nothing and seek advice.
* check that under BIOS settings you '''DO NOT''' have plug&play OS selected as Aros at this point is unable to route interrupts on its own and needs the BIOS to do that.
'''Save''' options changed at the end.
PCITool can show if the motherboard chipset is in IDE mode.
Class = 0x01 means STORAGE, Subclass = 0x01 means IDE. Also ProductID 0x3a20 resolves to non-AHCI mode in Intel ICH10 documentation.
==Installing==
We have a separate section [https://en.wikibooks.org/wiki/Aros/Platforms/x86_installing here]
We have a specific section for each CPU platform under the Specific platforms in the NavBar navigation bar on the right hand side menu
error code (-6) when using the ahci.device (has writing to disk problem but not reading) is enabled. change this line in your grub and reboot
<pre>
#module /Devs/ahci.device << disable
module /Devs/Alt/ata.device << add this line instead
</pre>
==File structure overview==
AROS' directory structure is mostly identical to AmigaOS directory structure, with some additions.
AROS: or SYS: also known as DH0: (i.e. the drive partition with AROS system) has the following simplified list of the main drawers (Amigas term for directories/folders).
{| class="wikitable"
|boot:
| grub bootloader
|----
|C:
| small apps, where AROS looks first for applications/games but will look at Tools, System afterwards
|----
|Classes:
| .class as well as datatypes
|----
|Devs:
| .device .resource and in their own drawers (folders) .audio, .hidd, network, graphics
|----
|L:
| where .handler files go
|----
|Libs:
| where .library files go
|----
|Locale:
| where help guide txt readme files go
|----
|Prefs:
| applications that adjust or setup AROS functions and capabilities
|----
|S:
| startup scripts (for the aros boot process '''not''' grub) are stored here
|----
|Storage:
| place to keep old or alternative device drivers
|----
|System:
| applications associated with AROS operating system
|----
|Tools:
| extra applications
|----
|Utilities:
| extra applications
|----
|WBStartup:
| copy applications here to autostart with needed icons, drawers, data etc
|----
|}
See [[Aros/User/DOS#Drives.2C_Files.2C_Assigns.2C_Directories|DOS manual: Drives, Files, Assigns, Directories]]
=== Filesystem ===
Whilst the kernel is the heart, the filesystem is the blood of the system they are split into two categories (only a few are supported)
<pre>
Journalling - SFS PFS3 but also NTFS ZFS XFS ext4
Non-journaling - FFS FAT32(VFAT) but also exFAT BtrFS ext2
</pre>
Filesystem options for AROS to install
* SFS default
* Professional File System PFS3 [http://eab.abime.net/showthread.php?t=52234&highlight=pfs3+free&page=13 only on motorola 68k at the moment]
* FFS very old now but left in for legacy usage
Other [https://archives.arosworld.org/index.php?function=browse&cat=driver/filesystem filesystems] for storage purposes
* FAT32 favorite as most OSs support
* NTFS (can lock AROS)
* exFAT
The only filesystems that really NEED defragging (i.e. disk tidy up) are from Microsoft(TM) - exFAT/VFAT/NTFS
*SFS tries to do exactly the same thing, but in certain cases it doesn't do as well as PFS. But you can defrag SFS
*PFS *minimises* the amount of fragmentation, but does not automatically defrags as it saves files to the drive
The setup of the below filesystems is usually done by the distro maintainer but if not....
<pre>
Copy L/exfat-handler L:
DOSDriver or Mountlist entry for an exFAT partition make sure that the FileSystem and Handler are set as follows:
FileSystem = exfat-handler
DosType = 0x46415458
</pre>
<pre>
Copy L/ntfs3g-handler L:
DOSDriver or Mountlist entry for an NTFS partition make sure that the FileSystem and Handler are set as follows:
FileSystem = ntfs3g-handler
DosType = 0x4e544653
Also to make a read-only mount you can set:
Control = ro
</pre>
The Smart File System (SFS) is a journaling filesystem used on Amiga computers and AmigaOS-derived operating systems. It is designed for performance, scalability and integrity, offering improvements over standard Amiga filesystems as well as some special or unique features.
SFS is written in C and was originally created and released as freeware in 1998 by John Hendrikx. After the original author left the Amiga scene in 2000, the source code to SFS was released and its development continued by Ralph Schmidt in MorphOS.
Its development has now forked; as well as the original Amiga version, there are now versions for MorphOS, AROS, AmigaOS 3, and a version for AmigaOS 4, which have different feature sets but remain compatible to each other. Versions for AROS, AmigaOS and MorphOS are based on different branches.
In addition, there is a driver for Linux to read Amiga SFS volumes, GRUB natively supports it and there are free drivers to use it from UEFI. The Linux version is [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ independent code].
SFS (Smart File System) partially defragments itself while the filesystem is in use. The defragmentation process is almost completely stateless
AROS SFS version has a 120GB partition size limit on hard disks and DVDs current 4gig size limit.
The sources for the MorphOS 64-bit version of SFS were available but no porting to AROS has happened so far due to endian issues, etc.
SFS Tools
* GUI - arSFSDoctor,
* CLI - sfscheck , [http://www.portacall.org/ sfsundelete], sfsformat, setcache hits a usability ceiling around the 10GB / 100,000 file mark,
sfscheck dh0: seek purge fraglist defragment
If there are two simultaneous file writes in progress and you reboot machine (or it locks up or crashes) you may end up with a corrupted filesystem. Although arSFSDoctor may help, you might have to copy the files to another partition, format the partition with the errors on and copy the files back.
PFS / SFS are way more advanced and much much faster than the FFS. FFS is supported for legacy reasons only.
The Professional File System (PFS) is a filesystem originally developed commercially for the Amiga and now distributed on Aminet with a 4-clause BSD license. It is a compatible successor of AmiFileSafe (AFS), with an emphasis on added reliability and speed compared to standard Amiga filesystems. It also features multi-user abilities like the older MuFS.
PFS has so many advantages including the important things, speed, the ability to recover all deleted files even simply same name by typing the command ". Deldir" convenient if done in Directory Opus, virtually deleted files are copied normally as if they had never been deleted, other convenience is to not ever invalidate the filesystem, just put it on top of the startup-sequence command "diskvalid", which automatically corrects any irregularities in the system startup; PFS also provides a device for floppy which makes them very fast and takes advantage of the full capacity of the floppy including the area dedicated to the bootloader.
The device is split into two main areas. At the beginning of the device is the metadata section, which consists of a root block, and a generic array of blocks that can be allocated to store metadata. The rest of the device is another contiguous generic array of blocks that can be allocated to store data. The metadata section usually uses a few percent of the device, depending on the size of the device.
The metadata is stored as a tree of single blocks in the metadata section. The entire directory structure is recorded in the metadata, so the data section purely contains data from files. The metadata describes the location of data in files with extents of blocks, which makes the metadata quite compact.
When a metadata update occurs, the system looks at the block containing the metadata to be changed, and copies it to a newly allocated block from the metadata section, with the change made, then it recursively changes the metadata in the block that points to that block in the same way. This way, eventually the root block needs to be changed, which causes the atomic metadata update.
The filesystem is reasonably good at keeping files unfragmented, although there is a defragmentation tool available which will work on an online filesystem ie whilst being used.
It was the first filesystem to introduce the concept of the Recycle Bin natively at filesystem-level to the Amiga, holding the last few deleted files in a hidden directory on the disk root.
PFS version 5.3 was developed in C and a small portion of assembly code by Michiel Pelt. There are endian issues to be overcome and adapting the small amount of m68k to C before use on intel based machines, etc.
Autoupdate of files in a directory is already implemented in Wanderer, but not all file systems handle dos.library/StartNotify() in its full extent. It seems to work correctly in Ram Disk (thanks to AmberRAM handler), and it also works on SFS formatted devices. Other file systems might not yet have it implemented correctly though.
The PC equivalent of the Amiga's RDB is the master boot record (MBR).
===Installing Applications===
The typical means to install applications under AROS/AmigaOS involves simply copying/extracting the archive (.zip .lha .rar .tar.gz) file containing the applications files to your own desired location i.e. drawer/folder. Once extracted, launching it by double clicking on an icon (recommended) or using the shell (alternative). Generally, this is on a separate partition from your AROS system files, however in reality it can be any location - including RAM: if you don't want it staying around too long especially when you switch off.
At some time in the future it may be desirable for AROS to have a package-manager like subsystem able to retrieve information online about packages available for AROS and whether they update anything you currently have installed, however at the moment no such ability exists.
===User Data files===
AmigaOS has no notion of a default location to store user data files, and presently neither does AROS - though it may be desirable at some time to provide a common start location.
Some people, have extra small FAT32 partition(s) using HDToolbox, and not Qparted, to store data especially if a reinstall is ever needed. And then setup the usual Sys: (DH0:) and maybe Work: (DH1:) / Live USB (DU0:) and maybe Briefcase (DU1:) partitions.
===User Environment configuration files===
AmigaOS/AROS stores persistent system configuration data in directory assigned to ENVARC:. This, by default, points to SYS:Prefs/EnvArc.
During boot a copy is made to another assign, ENV:, which is for runtime usage. Changes to the files here will not survive a reboot.
Setting the env variables is generally done by applications themselves, or when necessary by the user using the SetEnv command. SetEnv has a SAVE switch to force the persistent copy in ENVARC: to be written also for when you are sure the change should be permanent.
Under the standard installation of AmigaOS style OSs, ENVARC: is copied to ENV: upon startup, which, if you have a hard drive installation, is in RAM:, hence, ENV: ends up being RAM:Env.
ENVARC: is the Environment Archive, which is the permanent copy of ENV:, which is the Environment. It's roughly like the Registry in Windoze.
Most programs do (and all should) store their settings in ENVARC: somewhere, and load them from ENV:. The effect of this can be seen in the Preference editors. If you Save your preferences, they go in ENVARC: and ENV:. If you click Use, they only go in ENV:. If you reboot, normally, anything saved to ENV: is lost, and is replaced with a copy of what is in ENVARC:.
you can set the default public screen for any tool started from a cli with the PUBSCREEN variable. So open the pubscreen, set PUBSCREEN to the name and start newcli for example, then the new cli window (and all following windows opened from that window) will appear on that public screen.
===Drivers===
For certain hardware, e.g audio, networking and , there is no auto setup. Just like the original Amiga OS.
For audio, use AHI in the Prefs folder to set Music and at least Unit 0 with the appropriate driver and press Save. For ethernet and wifi, please use SYS:Prefs/Network
All hardware support is placed in the Devs drawer (folder/directory). The network drivers <something.device> go in the Networks sub-drawer. Audio drivers <something.audio> are put in the AHI sub-drawer. Graphics drivers <something.hidd> are put in the Drivers sub-drawer.
==Configuring==
AROS has mainly decided on a MUI-like requester&menu clone called Zune so changing the background, icons, font, menus can be done with SYS:Prefs/Zune
AROS has several desktop GUI front ends like
* DOpus5 Magellan II, Wanderer and Scalos (medium)
* AROS Workbench, Workbook (smaller)
File / Directory managers like Dopus4, MCAmiga,
App Launch Shortcuts like FKey, BoingIconBar, right mouse click on magellan, wanderer desktop, Amistart, etc.
General usability decisions - Prefs/IControl, Prefs/Locale, Prefs/Input, Prefs/Fonts,
Select an icon with left mouse button and then right click the mouse button and selecting Icon -> Information gains access to the tooltypes tab where information can be edited
CLI in icon's tooltypes means 'run it as if it was run from shell'
If, on the other hand, the WB parameter (or no parameter) is present in Tooltypes, Wanderer will execute the binary and, if provided, the options included in Tooltypes.
WBxCLI is very useful for adding options to DOS Commands.
Important: AROS has a different way of managing icons. If you have an executable file, you will never be able to add a project icon. AROS will automatically recognise that it is an executable file and will transform the icon into a tool icon.
Icons are typically now .png pictures renamed as .info e.g. so Office application name would have a Office.png renamed as Office.info or MyApp.png as MyApp.info, etc.
Leave Out menu option to leave app icon on desktop
To select multiple icons and save their positions, click on the first icon and after while you hold the Shift key down select further icons and don't release it before SnapShot is finished. You can also select a whole group of icons by pressing the LMB at the top left of the icons and while keeping the LMB down moving the power towards the bottom right. A expanding bounding box will appear and all the icons within it will be selected.
Clean Up menu option (right mouse button -> Icons) rearranges icons in a drawer or disk window into a neater condition. To use, open the window to rearrange and select Clean Up. To keep the icons in the new positions, select all the icons (shift key or mouse selection) and select 'Snapshot' and then Window and then again with All.
In DOpus5, Scalos, wanderer, most files have an icon file associated with it. To change the default tool, select Icon menu, Information, and change the default tool string. For example, you could use Multiview, Editor and so on for most text, graphics and some sound files as long as the appropriate Datatype classes are installed. For scripts, set the tool to C:IconX
We have new Icon edit tools in progress but if you need to...
C:Join Image1.png Image2.png TO MyFile.info
is enough to make a dual state icon from two png images. You can then use Wanderer's menu Icon/Information on it to edit its fields and tooltypes.
[https://archives.arosworld.org/index.php?function=browse&cat=graphics/icon AISS toolbar images] unpack unarc them into RAM: and copy Images directory to SYS:Prefs/Presets/ AISS icons are looked for in PROGDIR:, PROGDIR:Images, SYS:Prefs/Presets/Images and then in TBImages: according to Open Amiga guidelines.
there is Demos/iconscale which could be launched from S:User-Startup with two arguments, telling it the horizontal and vertical size. IE something like
Demos/iconscale 40 40
It will shrink icons... not sure if it will be very nice though. it doesn't work for the icons on the main desktop.
there is an option to scale an icon to a bounding box afair, try iconsize followed by two numbers, like:
iconsize 32 32
Is there any way in AROS to change an icon type from Project to Tool or vice versa?
Either the SIT option of [ ProcessIcon], or the TYPE option of HandleInfo (not sure if this one works at all, please test with care).
processicon sys:pathoftheicon SIT=Project
SIT Set type of ICON. Allowed types are: "Disk", "Drawer", "Tool", "Project", "Garbage", "Device", "Kick" and "AppIcon".
Btw, are your icons, the #?.info files, writable, is the W flag set ?
'''Decoration''' is Aros' way to provides a way to hide the old Workbench 3.1 style of windows and screens. In Prefs/Appearance some decorative theming elements need work
Themes - SYS:Prefs -> Appearance
The default content of Prefs/Env-Archive/SYS/themes.var should be "themes:ice" but can be changed via the Appearance prefs, please do NOT click the Use button. Its useless. As you know, it will ask for the theme volume. Just pick the theme you want, click on Save, then reboot.
* Decoration is on. Any time trying to change theme, you get: "Please insert volume Theme: in any drive"?
You could check if you find SYS:System/Themes or if it is missing. Then you could open startup-sequence which you can find in drawer "S". There should be a line:
Assign THEMES: SYS:SYSTEM/THEMES >Nil:
This does the trick.
Open a shell and run:
Assign THEMES: SYS:SYSTEM/THEMES
Than start the Theme prefs again... this should work
* The theme is the only thing that could slow the system a bit, but it's not that performance impacting on most uses, and you can switch it off completely. Remove C:Decoration from the bottom of the file sys:s/startup-sequence.
In each theme directory is
*Env-Archive -> Zune -> global.prefs
*images -> Gadgets -> 20x20 pngs for Down etc
*menu -AmigaKey - Background - Checkmark - SubMenu and config
*system - Arrowdown, Arrowleft, Arrowright, Arrowup, etc
There is an [https://archives.arosworld.org/index.php?function=browse&cat=graphics/theme ALua/Zulu script] built for faster Wanderer skin management. You can modify config files, install new (wdz format/zipped skin files) and delete skins via the Theme Manager. This has not been updated in a long time and may not work.
Certain features are added if from Tools/Commodities like Blanker screensaver, ClickToFront and DepthMenu with .info icons are selected and dragged to /WBStartup folder
Most apps can be autostarted by copying into SYS:WBStartup directory folder
e.g. WeatherBar.zip can be downloaded, unzip and the contents of the zip copied to wbstartup folder
ClicktoFront and .info to SYS:WBStartup so always be activated when turning on the computer
or add a text line to user-startup is SYS:S (scripts version of wbstartup)
e.g. standard Amiga / AROS does not allow clicking of background windows to come to the front to make it easy to get to the window you need but it has the ability if these apps are copied again to WBStartUp or are added to SYS:S/user-startup script
run QUIET sys:Tools/Commodities/ClickToFront >Nil:
run QUIET sys:Tools/Commodities/DepthMenu >Nil:
run QUIET sys:Tools/Commodities/Blanker seconds=300 >Nil:
Exchange controls Commodities and can be opened with alt, ctrl, h
*AltKeyQ uses left Alt key to add strange letters
*AutoPoint
*Blanker screensaver
*ClickToFront allows windows to be easily brought to the front
*DepthMenu adds menu to select window easily
*NoCapsKey
*Opaque
*FKey - Although there are heaps of docks, menus and other launcher programs on the Amiga like OSs, FKey has got to be one of the quickest once learnt ways to launch programs, and it comes with the OS. In SYS:Tools/Commodities, the FKey commodity (Ctrl Alt F) allows you to make actions assigned to some combinations of keys
<pre>
ALT TAB Cycle Windows
Cycle Screens
Enlarge Window
Shrink Window
Toggle Window Size
Insert Text
Run Program
Run Arexx Script
</pre>
e.g.
<pre>
LAmiga F1 = Avail Flush
LAmiga F2 = Open Prefs
LAmiga F3 = Finder
Alt Tab = Cycle Windows
LAmiga Tab or M = Cycle Screens
Alt Up arrow = Enlarge Window
Alt Down arrow = Shrink Window
Alt Home = Toggle Window Size
= Insert Text
LAmiga e = Run Program
= Run Arexx Script
</pre>
If your FKey GUI pops up when you start your Workbench up and you don't want it to, click once on the icon, go to the Icons-Information in the menu and make sure it has the tooltype set "CX_POPUP=NO".
Now let's launch it and assign the locale switching. After you double-click on FKey icon, launch the Exchange, choose the FKey from list and click the Show button. This will invoke the FKey window. You can see the ALT TAB in list assigned to window switching. Now enter the first key combination, say, ALT Z and go to the right panel. Choose Launch the program from pulldown menu and enter SYS:Prefs/Input as an argument. Append the USE switch and english preset name to the string as shown:
SYS:Prefs/Input USE SYS:Prefs/Presets/english
Click on the New Button to add the another combination. Now set the combination for your locale as shown above, replacing English name with your preset name. Click New button again and then Save Settings. Now you can use defined combinations to switch the layouts.
There is a system wide ARexx script capability (based on regina) that can manage many file manipulation task(s) but this would work only with those program that support [https://en.wikibooks.org/wiki/Aros/Developer/Docs/Rexx ARexx] like
*Desktop - DOpus5, Scalos
*Dock - FKey,
*Files - Multiview, DOpus4,
*Internet Apps - Odyssey, WookieChat,
*General Apps -
the shell can be modified with escape strings but not needed in most cases
Common Keyboard Shortcuts
<pre>
RAlt Right Alt Key
LAlt Left Alt Key
RWinKey Right Windows Key
LWinKey Left Windows Key
RAmiga Right Amiga Key (if one)
LAmiga Left Amiga Key (if one)
</pre>
;Bootup Options
:Spacebar during boot, enters the bootmenu which allows a boot without startup sequence, etc
;Left Click
:LAmiga = LWinKey = F11
;Right Click
:RAmiga = Help = F12
;Mark
:RAmiga and B
;Cut
:RAmiga and X
;Copy
:RAmiga and C
;Paste
:RAmiga and V
;Search
:RAmiga and S
;Mouse Movement
LAmiga and together with arrow keys - shift as well at the same time as well to move faster
;Mouse Selection
LAmiga and LAlt to select
;Screen Switching
LAmiga and M or N
;HELP key
Can sometimes be mapped to F11 but can be changed via FKey
ComKeyRemapper or AmigaKeyremapper could swap RAmiga to another key press
===DOpus 5 Directory Opus Magellan II===
Dopus 5.x is a whole desktop replacement on the Amiga Workbench (Desktop)
DirectoryOpus app will assign DOpus5: to it's PROGDIR: automatically but if not add the below (edit SYS:System to suit where Dopus5 was installed) to your startup-sequence
<pre>
Assign DOpus5: SYS:System/DOpus5
DOpus5:DirectoryOpus
;DOpus5:C/LoadDB
</pre>
Left mouse button clicked twice on the desktop background brings up the Device List window.
Green strip notifies SRCE (source) and if another is open it will be red for DEST (destination). clicking on the red strip changes to green
Word list of actions with a left mouse click on the DOWN Arrow and directory stuff with < button which mirrors the icons at the top of each lister
single-key hotkeys? exactly the same as in dopus4, edit your functions (button bank, toolbar, menus etc.) and under the flags gadget is a key gadget, just click in it and press the key you want to use.
As for the extra text field... try turning off Extended lister key selection in environment / miscellaneous.
Shift and click on the icon - runs the icon
DOpus5 Magellan 2 Directory folder drawer structure
<pre>
ARexx - Arexx scripts .rexx and .dopus5 to perform tasks
Buttons -
Commands -
Desktop -
Environment - two environment files bundled:
default gets loaded if you run DOpus as a normal app
workbench gets loaded if you run DOpus as a WB Replacement (with LoadDB on startup)
Filetypes -
Groups -
Icons -
Images -
Modules - compiled tasks
Settings -
Sounds -
Themes -
WBStartup - Use this if standard SYS:WBStartup gives cannot wait error messages
</pre>
Settings -> Environment -> Display -> Workbench (Use)
*Settings -> Clock (add to title bar as well as the date)
*Toolbar -> Editor (Right Win Key together with 1) for Copy, Move, Delete, etc above the Device List
*Menu -> (Right Win Key together with 2)
*Buttons -> Editor (Right Win Key together with 3)
*Settings -> Environment (Right Win key together with 4) for Backgrounds, etc
*File Types -> (Right Win key together with 5)
*User Menus -> (Right Win key together with 6)
*Hotkeys -> Setup for quick shortcut keypresses (Right Win Key together with 7)
*Scripts -> (Right Win key together with 8)
*Icon Positioning -> (Right Win key together with 9)
Each Dopus5 theme are stored in a separate directory, named appropriately, which contains further sub directories
* Font (amiga bitmap fonts)
* Screens (jpg or any picture supported by datatypes but not animations)
* Sounds (wav but not iff 8svx )
* Icons (png newicons glowicons )
* Patterns (iff jpg png )
Just use wildcards in background filenames and you get a different picture every reboot
For example, configure in Environment -> Backgrounds -> Desktop something like this:
<pre>
Work:Pictures/Backgrounds/#?
...or
Work:Pictures/back#?.iff
...etc...
</pre>
[https://aminet.net/util/dopus arcdir and themes]
If you want to change the backdrop pic after a period of time, paste below into a text file called dopusrandbg.rexx and place in DOPus5:ARexx
<pre>
/* Changes DOpus background image forever
Start with:
Run >NIL: RX dopusrandbg.rexx
*/
if ~show("L", "rexxsupport.library") then do
if ~addlib("rexxsupport.library", 0, -30,0) then exit 10
end
/* Configure these two lines for your needs: */
minutes=1
picpath="Work:Pics/#?.iff"
address DOPUS.1
do forever
call delay 3000*minutes
dopus set background '"'picpath'"' desktop center custom
dopus refresh background custom
end
</pre>
If you don't want to use/open rexxsupport.library just for DELAY() then use the DOS Wait command
<pre>
/* random diropus backdrop changer */
/* by paul trauth, 1999 */
/* to do: non-repeatable randomness? */
options results
parse arg path
address DOPUS.1
/* get current backdrop pattern so it actually changes */
dopus query background desktop custom
currentpatt=result
lastslash=lastpos('/',currentpatt)
currentpatt=substr(currentpatt,lastslash+1,(pos('"',currentpatt,2)-lastslash-1))
dir=showdir(path,'FILE','/')
num=0
do while dir~=''
where=pos('/',dir)
if where>0 then do
file=left(dir,where-1)
dir=right(dir,length(dir)-where)
end
else do
file=dir
dir=''
end
if left(file,1) ~='.' & file~=currentpatt then
do
pics.num=file
num=num+1
end
end
which=random(0,num-1,time(s))
newbg='"'||path||'/'||pics.which||'"'
dopus set background newbg desktop tile precision exact
dopus set background on
dopus refresh background
</pre>
Clock format commands available are defined by locale. They are:
<pre>
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
</pre>
like %a %d-%b-%y %H:%M or
A WB ARexx interface, you could enter a cli command as a menu item to open a WB drawer like this...
RX "address WORKBENCH;WINDOW 'device:drawer' OPEN"
Where device:drawer is replaced by the path of the drawer to open.
The ARexx script would be capable to manage such a task but this would work only with those program that support ARexx
<pre>
dopus addappicon
dopus addtrap
dopus back
dopus checkdesktop
dopus clear
dopus command
dopus desktoppopup
dopus error
dopus front
dopus getdesktop
dopus getfiletype
dopus getstring
dopus matchdesktop
dopus progress
dopus query background, font, palette, pens
dopus read
dopus refresh all, background, icons, lister
dopus remappicon
dopus remtrap
dopus request
dopus script
dopus screen
dopus send
dopus set background, font, palette, pens
dopus setappicon
dopus version
</pre>
<pre>
lister add
lister addstem
lister copy
lister clear value
lister clearcaches
lister close
lister empty
lister findcache
lister getstring
lister iconify
lister new
lister query active all, dest source
lister query abort, busy, case, dirs, display, entries, entry, files, flags, handler, header, hide
lister query label, lock, mode, namelength, numdirs, numentries, numfiles, numseldirs, numselfiles
lister query path, proc, position, seldirs, selentries, selfiles, separate, show, sort,
lister query title, toolbar, value, visible, window
lister read
lister refresh
lister reload
lister remove
lister request
lister set busy, case, dest, display, field, flags, handler, header, hide, label, lock, mode
lister set namelength, newprogress, off, path, position, progress, separate, show, sort, source
lister set title, toolbar, value, variable
lister select
lister wait
</pre>
The '''command''' allows you to call internal DOpus commands from an ARexx script
<pre>
command all
command wait copy
command read s:startup-sequence
command source 12345 makedir name noicon
</pre>
*SFTP secure encrypted comms over internet using libssh2 and zlib (different protocol to the two below) on port 22
*FTPS secured with https like security on port 21
*FTP not secure and unencrypted protocol over internet on port 21 (should not be used today on the internet but for your own server)
===Wanderer ===
Wanderer prefs in the prefs drawer - Appearance tab and Workbench icon allows backgrounds (wallpapers) icon text sizes, colors, etc but cannot use #? or *.* in the backgrounds file entry to randomly choose pictures - [https://developers.google.com/speed/webp/docs/riff_container webp riff container] issues with this format but Multiview has none.
Enable the bar, you need to edit the text file ‘statusbar.prefs’. The change is simple: just change “False” to ‘True’.
Prefs/Env-Archive/SYS/Wanderer/statusbar.prefs
===Scalos===
[https://web.archive.org/web/20180922220139/http://scalos.noname.fr/ Scalos] is not an OS replacement, it's a Workbench replacement. It replaces the desktop and graphical file management components.
Scalos is 100% Workbench replacement with most functions working like the original Workbench ones. Undo and Redo available for most window and icon operations. Fully multitasking so every window has its own task. While loading icons, any window function (e.g. Drag&Drop) is available.
24bit color support with window patterns - Unlimited and easily configurable via tooltypes. Optimised backgroundpatterns routine so patterns can be tiled, centred or even scaled to fit into the windows. Live updating window scrolling - Supports middle mouse button panning and drawer (folder) windows can be iconified on the desktop.
Icon imagetypes with all types are supported such as backfill or complement. Configurable surrounding iconborder. Icon support also visually highlights files which are soft-links in the file system. Icon dragging is more stable and far less flickery on graphics cards. Whilst dragging, icons are displayed with text and they can become transparent over anything where they can be dropped.
Single-window lasso mode, with scrolling window contents invoked by dragging mouse with configurable qualifier key. Text icon lasso selection used to ignore "Name column selects text icons" flag. Support for backfilled thumbnail icons, with selectable color and transparency. Added option to always generate square thumbnail icons with preview icons for images - Thumbnails can be permanently saved in icons.
Supports PNG icons with alpha channel and real transparency and displays OS3.5 GlowIcons and are all scalable. Iconborders with variations (normal, shadowed, outlined).
Completely configurable, filetype-specific user-definable popup menus and tooltips. Plugin system to exchange or add features and can enhance the Workbench and make it more configurable.
Filetype plugins to display filetype-specific information. - Currently, EXIF information viewer for JPEG images is included. Plugin included for 100% support of OS3.9 Workbench features. Plugin included for AREXX API compatible to OS3.9 Workbench.
Online update with updater.module
Scalos works also as a Workbench replacement. In this case the 'emulation mode' has to be set by using Scalos' own version of LoadWB and offers
* Scalos uses the Workbench Screen for its windows instead opening a new one
* AppIcon, AppMenuItem, AppWindow functions are redirected to Scalos
* all Programs placed in "WBStartup" should start
* The Screen will be reopened in case of changes in ScreenMode and Palette settings
<pre>
v1.0 (V39.201) - November 1999
v1.1 (V39.212) - December 1999
v1.2b (39.220) - June 6, 2000
v1.2d (39.222) - 2000 (latest public beta executable)
v1.3 (40.7) (beta) - August 2, 2001
v1.3 (40.22) - September 25, 2002
v1.4 (40.32) (beta) March 31, 2005
v1.6 (41.4) - March 27, 2007
v1.7 (41.5) - August 12, 2007
v1.8 (41.6) - March 12, 2009
v1.9 (41.7) (beta) - March 15, 2010
v1.9 (41.8) (RC1) - August 25, 2012 open source
v1.9.2 (41.10) Deadwoods' AROS late 2022 32bit and 64bit build unifying the code base of ` for AROS x86 ABIv0, AROS x86_64 ABIv11 and AROS m68k
</pre>
Distros may have Scalos files under SYS:System/Scalos or Extras:Scalos. Known [https://github.com/deadwood2/AROS/issues/75 bug list],
Certain files like Menu13.prefs, Palette13.prefs, Pattern.prefs and scalos.prefs need to be in SYS:Prefs/Env-Archive/Scalos they can be found in Scalos:Storage/envarc and country drawer
or run the "Scalos Menu" preferences program. Note if already setup with sub-menu entries and then re-save your menu prefs as it will now generate a new/overwrite prefs file called "Menu13.prefs" in "envarc:scalos/". The same is also required for the new Palette prefs update, click 'Save' and a "Palette13.prefs" file will be saved in to "envarc:scalos/" directory.
<pre>
ASSIGN Scalos: SYS:xxx/xxx DEFER
ASSIGN Libs: Scalos:Libs add
;ASSIGN SYS:Devs/Datatypes Scalos:Devs/Datatypes add
Assign Theme: Scalos:Themes/Default_Theme add
Assign Locale: Scalos:Locale add
Protect Scalos:Tools/browse.script s add quiet
Protect Scalos:Tools/OpenShell s add quiet
Protect Scalos:Tools/run.script s add quiet
run Scalos:Tools/LoadWB
;Scalos:Scalos
</pre>
Add the above to SYS:S/startup-sequence or SYS:S/user-startup '''before any Wanderer entries'''
In the prefs drawer (folder) is the big prefs app Scalos_Prefs which covers these user setup areas
<pre>
About Scalos
Paths - should be preset
Startup - WBStartup drawer contents should auto run on each startup
Desktop - edit titlebar, icon layout and in misc, auto leave-out (drag icon to desktop)
Icons -
Drag and Drop -
Windows -
Text Windows - in misc, drawer sorting at start of listing if needed
TrueType Fonts - use Truetype fonts rather than system ones
Miscellaneous -
Plugins - after adding oop/title_clock.plugin %ti %da does not work, maybe needs ASCII .prefs added
Modules - ??
Menu - setup for MainMenu and PopupsMenu with New Menu, RE Name, Key: shortcut, Command Properties
FileTypes - already added def_Project icons and def_Disk (hdd sdd cd dvd etc) support
PopupMenu - tweak how popups appear
Pattern - Wallpaper backgrounds with Type DE, each pattern in the list can be edited, Save as Pattern.pre
Palette - change the color of things , Save as Palette.pre
</pre>
Scalos_Prefs - Pattern - Minimum options to be changed are
*DE Desktop/Background
*SC Screen
*TW Window/TextBackground ie Text listing showing if icon type not recognised
*IW Window/Background ie Icons showing
Workflow - In "Pattern List" tab, select New - choose a picture, highlight in list, click in number box under New button and slide to another number, click on "Defaults" tab and adjust Pattern numbers slider to choose right picture for each of the above options - Click "Pattern List" tab to check eveything is OK and click Save
Pattern List tab on Patterns Page - Allows you to compile a list of pictures (one at a time rather than a whole folder e.g. with #? or *.*), assigning a number Nr to one or more of them for easy reference. Using this number you will be able to assign the pictures to specific windows on the Defaults tab Page. If multiple pictures have the same number, one of the pictures will be chosen randomly. This will allow you to have random desktop pictures, random window backdrops etc.
Defaults tab on Patterns Page - Here you can set the defaults for the background pictures for the Desktop, Screen, Window and/or Text Mode throughout Scalos.
Randomize every time [check box] - Usually Pictures with the same number will be randomly selected as soon as the configuration loads. If this option is set, the picture will be selected as soon as a window with the same number assignment is opened.
*Fit size: The picture will be resized to the dimension of the new window.You *MUST* have set GUIGfx on. asyncron layout: Pictures will be loaded and rendered while the windows opens (Like original Workbench). If this function is 'off', pictures will always be loaded before opening the windows.
*Use friendbitmap : The picture is present twice in memory for best speed. This option has no effect if V43 picture.datatype or GUIGfx are used. Always relayout: If "Fit size" is set, the picture will be scaled everytime the window's dimensions change.
*Randomize everytime: Usually Pictures with the same number will be randomly selected as soon as the If more pictures have the same number, one of them will be chosen randomly.
Patternlist New/Delete : Add a new picture. After that you should assign a number to it. The picture will be rendered as tiles. configuration loads. If this option is set, the picture
Asyncron-Task priority: You can set the CPU priority for the Task if "asyncron layout" is set.
<pre>
Desktop: Number of the Picture for the main window.
Screen: Number of the picture for the Scalos-Screen.
Window: Number of the picture for the Scalos-windows.
TextMode: Number of the picture for the Scalos-windows in Text Mode.
</pre>
Popup Menu preferences fully configurable menus (includes ToolsDaemon and ParM launch apps import), including support for context-sensitive Popup menus configs for top pull down menus for apps, etc.
Workflow - Scalos_Prefs then Menu, New Item, New Command add name at top then in Command Properties e.g. add Workbench and location e.g. DOpus:DOpus4 for apps Command for c apps or Rexx for scripts or Plugin for or AmigaDos for modules
<pre>
DESCRIPTION NAME/A This is the title that is displayed in the top line of any popup menu
INCLUDE NAME/A Name of file to be included. Path can be relative to "Scalos:FileTypes"
POPUPMENU Starts the popup menu description section for this filetype.
</pre>
The following Subcommands are allowed inside popup menus:
<pre>
SUBMENU "NAME/A"
ENDSUBMENU
MENUENTRY "NAME/A,KEY/K,DEFAULTACTION/S"
ENDMENUENTRY
INTERNALCMD "NAME/A"
WBCMD "NAME/A,STACK/K/N,WBARGS/S,PRI=PRIORITY/K/N"
AREXXCMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
CLICMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
ICONWINDOWCMD "NAME/A"
PLUGINCMD
MENUSEPARATOR
ENDPOPUPMENU
TOOLTIP
ENDTOOLTIP
</pre>
<pre>
Starts the tooltip description section for this filetype. The following Subcommands are allowed inside popup menus:
GROUP "ORIENTATION/K"
ENDGROUP
MEMBER "HIDE/K"
ENDMEMBER
HBAR
STRING "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K"
SPACE "SIZE/N/A"
DTIMAGE "FILENAME/A"
</pre>
Each theme drawer (folder) has these further folders
<pre>
About -
Desktop -
FileTrans -
FileType -
Icons -
Menu -
Modules -
PointerIcons -
Prefs -
Sound -
Window -
</pre>
*Plugins
<pre>
devicefilter.plugin
persist.plugin should a crash or reboot occur - next time Scalos started, all windows re-opened
title_clock.plugin add digital clock to title see more below
title_envvar.plugin %ev, which can be used to display the value (a string) of the variable in the titlebar
title_freepens.plugin
volumegauge.plugin
wb39.plugin
wbrexx.plugin plugin adds a Workbench 3.5+ compatible AREXX interface to Scalos internals
xtwindows.plugin left or right ALT or left or right SHIFT keys when open/close windows
filetype.plugin then run FileTypes-prefs and customize the filetypes (eg import from a DefIcons-brainfile)
menu.plugin
</pre>
*Modules - delete, empty_trashcan, execute, find, format_disk, information, iconproperties, newdrawer, reboot, rename, systeminfo, windowproperties
*Tools - scripts like LoadWB, quit.rexx, open_volume.rexx,
In Scalos_Prefs->Filetype->Recognition you can define the filetypes and on "Action" you define specific context menu for all filetypes defined in recognition (similar to magellan)
there is the same you must show all first (list is only limited) so you created a file type AAABBB, you need to have def_AAABBB icon
Associating files with "Scalos_FileTypes" is very simple, practically it is very similar to Dopus4, first you create the Def_icons to assign to the file type (will be seen automatically ), then run "Scalos_FileTypes" you add the extension, fill in the descriptor (MATCH or PATTERN etc..) and save
then you create an appropriate entry in the list and rename it, if def icon exists it is shown. Below you can define how files are identified. Use "pattern", similar to magellan to identify file by ending. Then you click on the shown icon and define in it what program is used when you double-klick on it and save it. On the tab action you can define popup menu for it.
defined all archive types from XAD in "filetypes". If you change to "action" and click on "archive" you can define the context menu that is shown if you do not define a specific context menu for a filetype
Reset to Default in Scalos_Prefs resets all settings so '''BEWARE'''
<pre>
The Scalos desktop screen titlebar may be configured using the main Scalos Preference program. This oop/time_clock plugin adds some additional placeholders:
%ti, displays the current time in the default Locale format. e.g. "10:43:37"
%da, displays the date in the default Locale format. e.g. "Saturday 14 July 2001"
Using the supplied prefs program for the plugin, or editing the ASCII file ENVARC:Scalos/title_clock.prefs you can use the following standard Amiga Locale values to change the formatting
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%C - same as "%a %b %e %T %Z %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%n - insert a linefeed
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%t - insert a tab character
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
like %d %m %y or %a %d %B %Y %p
</pre>
Shutdown -> right mouse button Scalos, About, Reboot, Shutdown
ToolTypes can be added to the Scalos.info icon like
*SCALOS_PATTERNNO=<number> : background image matching the number
*SCALOS_NOTEXT : The Icon will be drawn without Text.
*SCALOS_NODRAG : The Icon will not be draggable. Its position will be fixed.
*Module iconproperties - Added SCALOS_BROWSERMODE tooltype support
runcommand parameters... in which case:
<pre>
%p = parameters
%w = directory path
%d = device-name
%% = literal percentage token
</pre>
With the help of the wbrexx.plugin Scalos gains support for more of the compatible arexx API
If an arexx command produces an error you will find the error code placed in the WORKBENCH.LASTERROR variable.
ACTIVATEWINDOW
<pre>
/* Activate the root window */
ADDRESS workbench
ACTIVATEWINDOW root
/* Activate the "Work:" partition's window if already open*/
ACTIVATEWINDOW "Work:"
</pre>
CHANGEWINDOW
<pre>
/* Change the root window; move it to position 10,30. * and change its size to 200100 pixels */
ADDRESS workbench
CHANGEWINDOW root LEFTEDGE 10 TOPEDGE 30 WIDTH 200 HEIGHT 100
/* Change the currently active window */
CHANGEWINDOW active 20 40 200 100
</pre>
Most of Scalos' issue are due to the flexibility of its' user configuring nature but if
The sort menu plugin needs to be ported from ASM to C.
IIRC Scalos has a command line option to fully replace Workbench/Wanderer.
The Theme: assign is used by both Wanderer and Scalos but I didn't have any problems using both at the same time.
The Program will be started from the Shell.
If "WB Args" is set, with the Argument "%p" will be replaced by the path of the activated Icons. The Program will started with the specified Stack value.
IconWindow: Scalos opens the window of the specified path.
PlugIn: Starts a Scalos Menu-PlugIn.
If a Menu Item with empty name is specified, Scalos displays a separator line.
It's possible to Drag&Drop an Icon in the Configuration Window. All values will be set accordingly. Entries may be dragged across the list.
Mac-like selection : This function activates a multiselection method used on MacOS or Win95. Don't have to hold down shift to drag them. Clicking on an already activated icon will
not deselect all other icons.
MMB move: The window contents may be moved using the middle mouse button.
WindowPopup title only: PopupMenu for windows can be opened only on window's title bars.
FullBench: Screen-Titles removed and Main Window set Full Size.
Scalos Prefs. Go to Settings->Scalos->Prefs and then the Misc section. Remove the tick against Full Bench. If you've enabled it, the titlebar will disappear when you select backdrop.
Default Icons saveable : The icons which Scalos generates if "show all files" is enabled, can now be saved
using "snapshot" menu option. load DefDisk first : Try to read the icons first from the DefIcons Path before using disk info.
Hide hidden files : If this function is activated all files or directories where the "hide" flag is set will not be shown.
Many of my Icons display more than once on the screen, while on the workbench all seems ok.
The Workbench filters double displayed icons, Scalos does not. Solution: please edit the ".backdrop" file and clear double lines.
Background images not scaled. GUIGfx option not set or guigfx.library and/or render.library not installed.
If working with CD's causes crashs or Scalos doesn't work correctly.
Most Filesystems doesn't support the ExAll function correctly. Disable "Use ExAll" in Scalos prefs.
Scalos doesn't start any program in the WBStartup. WBStartup Path may be set wrongly or Scalos was not started in Emulation Mode (LoadWB etc)
Some programs will not startup with error message "has not returned, wait some more"? and "unable to open your tool"
need a def_icon with the same name predefined, then create an appropriate entry in the list and rename it, if def icon exists it is shown. Below this can define how files are identified.
* either "pattern", similar to magellan to identify file by ending
* or
Then click on the shown icon and define in it what program is used when you double-click on it and save it. On the tab action you can define popup menu for it. All in all handling is of course different to magellan but can do similar
For the RAM Icon, to obtain this you have only to copy the icon in the Icon Path as "RAM.info" or "Ram Disk.info". All functions will automatically be performed
sometimes cut into half or quarters when scrolled off screen or drawers moved - settings issue probably
Sometimes leaves initial drawer window imprint on desktop when moved - settings issue
Scalos AROS released a [https://github.com/deadwood2/contrib/tree/master/scalos new build V2022-07-21] with the following changes noted:
<pre>
Fixed:
Numerous crashes when working on 64-bit with 64-bit heap
Wrong background color of Scalos logo on Scalos splash window
Backgroung image of Scalos splash window and Scalos About window is not visible
Icon labels on desktop and in drawer windows are displayed using Topaz instead of Arial font
Font.prefs are not being loaded on 64-bit
Font.prefs are being wrongly saved on 64-bit
scalos.prefs are not being loaded on x86 and x86_64, scalos is using always default preference
scalos.prefs are being saved on x86 and x86_64 in format not compatible with m68k
NewPopupmenu.prefs is wrongly written
Plugins are not loading at Scalos startup
wbrexx.plugin is crashing at startup on 64-bit
Multiple controls missing on Scalos Prefs/Icons page
System crash when clicking on def icon image on FileTypes Prefs/Recognition page
Status bar, control bar, buttons sometimes don't have images displayed
Buttons in Scalos About window have white corners rendered where they should be transparent
Crash when leaving out an icon
Crash when adding a User-defined Button to Control bar without setting it's properties in Scalos Prefs
Crash when removing any button from Control bar in Scalos Prefs
Scalos Prefs allows editing TTEngine font properties when TTEngine is not present causing crash in Icons/Labels and Text Windows/Fonts pages
deficons.prefs are not being loaded on x86 and x86_64
Reset to default in FileType Prefs and Save does not save preferences
Won't fix:
Scrollbars visible on titles of TrueType Fonts, PopupMenu, Menu, FileTypes, Pallette and Pattern pages of Scalos Preferences
Not fixed:
Wrong rendering on DualPNG icons
Refreshing drawer windows is slow
Starting Prefs/Locale or Prefs/Input from Scalos causes other preferences to fail
Desktop wallpaper is damaged where Splay window was displayed
When started from Wanderer, after saving Scalos Prefs, reload does not re-open main Scalos window
Difference in behavior between Cleanup from popup menu and Cleanup from top menu - possibly due to missing plugin, check Cleanup association in Menu Prefs
</pre>
===DOpus 4 Directory Opus===
Copy DOpus4 app to WBStartup directory folder so it starts on boot up each time
Another method is add the below to the bottom of the user-startup script in SYS:S drawer/directory
<pre>
run DOPUS:DirectoryOpus -i >NIL
</pre>
makes DOpus starts up in Iconified state at the top of Wanderer's screen. Left click on this to highlight and right mouse click to open.
Just click on the sides of either outer edges of DOpus windows and it will display the parent device/volume list.
DOpus4 saves it features in a PROGDIR:s/DirectoryOpus.CFG file which can be edited to suit anyones' needs, '''C''' bottom right button in DOpus4 and by reading the [https://arosarchives.os4depot.net/index.php?function=browse&cat=utility/filetool Dopus4 guide Manual and Arexx calls].
*[https://www.youtube.com/watch?v=DCyXDs8baSE Pt1 Introduction]
*[https://www.youtube.com/watch?v=7fiVmopiK9I Pt2 Dopus Config]
*[]
*[]
*Button little rectangle with name inside
*Bank vertical stack of buttons
Buttons
*Workbench app {f} i.e. first use {F} for all selected items with app
*AmigaDos c type apps with arguments after
*Arexx
*Command c type apps with no arguments after
Flags (most used)
*CD Destination to extract etc
*Do all files
*Output window
*Run asynchronously
*Workbench to front
*Buffer above 100000 for 64bit
Filetypes
Defines how certain files are handled like '''default tool'''
Screen
Fonts, set each element to any font
Screenmode, Workbench Use (same screen like Windows), Workbench clone (like Linux workspaces)
System
Shell startup, set to SYS:s/shell-startup
===BoingIconBar===
User chooses the apps to add to the dock at the centre bottom of the screen but has to be done manually, please use Save afterwards
Or easier edit the text file of SYS:Prefs/Env-Archive/iconbar.prefs and save
<pre>
BOING_PREFS
;Tools
SYS:System/Shell
SYS:Tools/DOpus4/DOpus4
SYS:Utilities/Editor
SYS:System/SysMon
SYS:System/Scout
Work:Extras/Internet/OWB/OWB
Work:Extras/Graphics/Lunapaint
Work:Extras/Graphics/ZunePaint
AROS:Tools/MPlayer/MPlayer
Extras:Internet/AmiFox/AmiFox
RAM Disk:Amelinium/Amelinium
</pre>
right mouse click on bottom edge of screen where boingiconbar shows - select settings which opens BoingIconBar Preferences to add apps
If no dock showing Add, to add apps click Add Program and search for the executable
another method is to drag icons to ends of the bar and move them on the Bar using the Prefs/BoingIconBar
===AmiStart===
On 32bit PCs only - auto generates the apps menu but scans the drive each time - AmiStart can choose apps you are not interested
* how to disable annoying zune/mui 'bubbles'?
try a right-click on AmiStart and release on Global settings. Then click on the bubbles gadget. Move the Show Bubbles slider all the way to the left.
===Fonts===
Install the #?.ttf files to SYS:Fonts/TrueType. Use SYS:System/FTManager to "Install Font" each #?.ttf file which will generate associated #?.otag and #?.font in SYS:Fonts. Use SYS:Prefs/Fonts to change system fonts and SYS:Prefs/Zune to change others.
To achieve our goal we will use the Setup Locale, Input, Zune and Fonts, as well as The FTManager.
Begin
The first step you should do is to get the system to know that we speak and write in another language. What you need to do is to open the setup program and choose Locale country, and list "preferred languages" to put it first and then English. If you want the tab "Time Zone" and select city of residence to set the clock correctly. Of course we save our changes and continue opening the setup program Input. This sets the keyboard language as our beginning. When the language layout was created there was no option to switch to Aros keyboard (layout switching), so to write in the language you had to hold down Alt, something you encounter in other functions. This time working with the team of Aros to create a new keyboard layout to replace the old so we can get rid of the button Alt. For now though let only selected this layout and do not turn the switch on the keyboard.
Custom Keyboard Layout
[http://repo.or.cz/w/AROS.git/tree/HEAD:/workbench/devs/keymaps keymaps are in place but unfortunately when they are not, then indeed things become a bit 'low-level' as it involves redefining some tables with values that match your keyboards]
only need to add your compiled table as new keymap.
So taking a little peek here shows that it should be possible to compile using
gcc -opc105_tr pc_105.c -nostdlib
where the pc105_gr/pc_105.c needs to be replaced with your own adjusted keymapname/c-file
[https://en.wikiversity.org/wiki/Enabling_Greek_Characters_on_Your_Keyboard General overview of Greek letters on keyboards]
Installing fonts
*[http://aminet.net/package/util/wb/EPAGrWb System jaggy]
*Outline resizable .font .otag
In this step you need to download some fonts that can support the encoding in our system. The easiest way is to run the script "Download Fonts" you'll find in the folder OWB. This script downloads from the Internet, and unpacks some fonts for OWB web browser, which is placed under the folder Fonts:TrueType. But as these can only be used by OWB and not the system, which unfortunately does not see. To make them available to the rest of the system, open the program FTManager, you will find the folder AROS: System /. From there select the field "Codepage" option "ISO-8859-7" and list the font "Arial" and "Regular" form in which you must double-click with the mouse. In the window that appears, select the bottom right the checkbox "Anti-aliasing" button and then "Install". Immediately folder Fonts: created files "arialregular.font" and "arialregular.otag", which are necessary in order to see the system font. Do the same steps if you wish for other fonts.
Final stages
After completing the above, open the folder AROS: Prefs / and run the program settings Fonts. In the new window, select the fields "Icons" and "Screen" as the font "ArialRegular" to the size you want. In the field "System" to give "s_courier", which, however, because it is not True Type Font support Antialising, and may seem a little broken. You can also use the CourierNew, if you have installed the above procedure. After you save the changes and open the Zune program settings. In this set the "ArialRegular" font fields in tabs "Windows" and "Groups", and save the changes. Reboot the system. To make sure that the above worked properly run NoWinED, which you will find under the folder AROS: Tools /. If that everything is working correctly you will see the menu and the settings window with Greek letters. You can also write in the language using the button Alt. Second program that you can try, which is fully localized, is WookieChat, which you will find in the folder AROS: Extras / Networking. And in this place all the menu and settings window works.
===Windows===
*Intuition
The window you position and resize, you right click on that windows title bar and in the dropdown menu you snapshot from there. Right click to show menu -> Window -> Snapshot Windows or All but it will NOT work if that folder has no icon (e.g. Disk.nfo) attached to it. You need a folder icon. The window information gets saved in it.
As for maximising the window using a shortcut key - Alt and up arrow key
The AROS-Shell windows can be moved, resized by editing sys:s/startup-sequence
<pre>
; run shell
run QUIET c:newshell >NIL:
</pre>
; slimmer right aros the screen
run QUIET c:newshell con:0/150//300/ >NIL:
; top right corner scr-x scr-y win-x win-y
run QUIET c:newshell con:600/150//300/ >NIL:
*EdgeSnap
Commodity EdgeSnap allows resize and position windows on your screen by dragging them to the edges but not corners of the screen and/or other windows
EdgeSnap Prefs (once pressed Use button) lets you arrange windows but not different applications in layouts half (left or right) or full size (top) and choose to adjust the border padding
There is outline to show shape taken to aid placement and space available
*Zune - AROS version of MUI
Magic Menu type functionality is implemented in IControl preferences editor: in the frame called Menus, switch type from Pull-Down to Pop-Up and/or iControl just tick the sticky menu option.
Windows outside screens causing a problem either uncheck "Offscreen move" for windows in IControl prefs editor. Or use FKey commodity and define two key shortcuts:
* the first using the command "cycle windows" (for example ALT TAB);
* the second using the command "rescue window" (for example ALT F5).
Now you can cycle windows until the one you want to rescue, and then "rescue" it: it will move back inside your screen.
How to save the window size on wanderer (snapshot all, snapshot windows)
Same for icon position on wanderer, can't save the position. Icon position cannot be saved yet, but you should be able to save the window position and size. sys:prefs - wanderer icon has option to save window size on exit but just for dh0. To get saving working on (DH1: Extras:) partitions try deleting the dh1 disk.info file, then reboot. The system should create a new dh1 icon.
* how to set up permanently 'view all files'?
As for viewing all files, removing disk.info for that disk did the job
* how to list and kill processes (xkill would be useful) ?
sys:Extras/System/Scout can kill apps
sys:Tools/Commodities/Exchange can remove available commodities
* how to restore 'go up' button in wanderer window? (it doesn't show up anymore).
If you're using Icaros, go to the theme prefs and make sure that decoration is checked. Also, some themes do not use a parent button, so try another theme. You may have to restart Aros before the theme will change.
* Is it really safe to turn off (hardware button) computer at any time (worried about USB hard disk)
yes you can turn off the computer IF none of the drives are in progress (i.e. writing). Best to use Wanderer menu option Quit otherwise
===Say narrator===
Say "Hello World" for a simple robotic voice
SPEAK: is a write-only DOS device for text-to-speech abbreviated as tts.
To check if available, type assign into the shell and at the bottom in the Devices: section should be SPEAK
Examples of use
<pre>
Copy S:Startup-Sequence SPEAK:
Echo "Hello" >SPEAK:M/R/S150/P110
Echo "DH1 EH0 L OW1" >SPEAK:A1
</pre>
Classic options are M/F, R/N, S<rate>, P<pitch>, O0/O1, A0/A1, and D0/D1. O1 recognizes lines beginning with OPT/ as option changes. A1 treats input as narrator phonemes.
Long options select a speech engine:
Echo "Hello" >SPEAK:ENGINE=narrator/VOICE=female/STYLE=natural/LANGUAGE=en-US
Supported selectors are ENGINE=, VOICE=, STYLE=, and LANGUAGE=. Values are case-sensitive backend identifiers. ENGINE=DEFAULT selects the system default. Narrator-compatible selectors continue through the classic translator/narrator pair. Other engines use speech.device. Direct phonemes require a narrator-compatible selection.
===Printing===
This needs further [http://www.aminet.net/package/docs/help/PrinterGuide drivers written], we have postscript and write to file support only
;There are no individual drivers yet for HP's Photosmart, EPSON's EPL, CANON's, Lexmark, CUPS PPD, etc.
*Postscript
Best to set Printer Prefs in the Prefs drawer to print-to-file or parallel/USB port
Save document in postscript or convert picture/text to postscript
Print using compatible Postscript printer
*printer is simply not accepting IPP connections at the moment.
Please try the following steps:
Open the printer web interface in a browser:
http://192.168.1.x/
Look for the network or protocol settings.
Enable IPP / Internet Printing Protocol.
Make sure TCP port 631 is open/enabled.
Save the settings and reboot the printer if the web interface asks for it.
ipp://192.168.1.xx:631/ipp/print
ipp://192.168.1.xxx:631/ipp/
===Files===
====File endings and datatypes====
* Check if the file has his own .info icon file with a tool set to open it. IIRC this has higher priority over the def_XYZ.info file association.
* In ENVARC:SYS/def_Text.info or whatever def_ file needs changing, use Wanderer's menu Icon -> Information and change the def_XYZ.info there. If you're on ABIv0 and want it to be applied immediately, you might have to copy it to ENV:SYS/ (or to reboot).
* Identifying file types by file ending is only a fallback. Far better it is to search for magic words, for flac files this would be "flaC" according to this [http://flac.sourceforge.net/documentation_format_overview.html documentation].
For instance, to open PDFs with arospdf not localised in the default drawer of Icaros (Work:Extras/Applications/arospdf) but localised in a custom drawer in AROS. The default tools are defined in the icons in sys:prefs/env-archive/sys e.g. def_PDF.
File type identification is done by datatype descriptors which you can find in Devs/Datatypes. The AROS build system has a tool which creates such datatype descriptors.
'''Changing of default tools of existing icons is easy as shown above. Adding of new file types is not hard, but needs knowledge of the AROS build system.'''
The enduser way would be to download the attached file, which contained two executables:
1) createdtdesc, to make a new datatype description
2) examinedtdesc, to read/show existing datatype descriptions
use 2 to get an idea on how it things are currently done in aros by providing this executable a file from the drawer sys:devs/datatypes/ (alternatively you can find the original .dtd files here).
use 1 to make your new datatype. Use the accompanied FORMAT file (also here) to read how to make your own datatype descriptor. use 2 to get hints from other datatype descriptors.
Note:
When creating a new descriptor would advise against using the pattern property, but instead use the default pattern of #? and create a Mask that matches your filetype. This requires some research in order to discover how your filetype can be recognized properly. Of course with making something like a descriptor for an ascii textfile, you would fallback to using the pattern (e.g. #?.text as the filetype cannot be determined easily otherwise).
<pre >
# name - choose wisely and informative. also used for icon's name.
# version - choose as you like as long as it complies with version rules
# basename - the 'root' datatype class. be aware that e.g. it can influence behaviour. for example when choosing binary and using tool multiview in project icon, the file will be viewed as binary file (choosing sound would tell mulitview to view the file as a soundfile). So this can influence the underlying tool being used. Could become messy if users started to modify the tool manually.
# pattern - This is the file pattern match e.g. #?.text
# Mask - A mask to identify the file. Requires knowledge of the actual file structure. For example 'M' 'Z' for an msdos executable.
# GroupdID - not supported (AROS native) files - use syst as that would be the least intrusive in case an AROS tool/program tries to load such datatyped file.
# ID - In your case, the first four characters of the name at subchapter 1 (in lower case) (or less if name is shorter).
# flags - How the mask needs to be interpreted. In your case would be mostly DTF_BINARY in combination with (wanted or not) DTF_CASE (to tell if mask used letters are case sensitive or not)
# priority - the priority of how the type is handled so that on datatype could have precedence over another? In any case, document tells it to be mostly 0.
</pre >
Now that you know each field and what it does (more or less), you write this fields in a text file for your own invented datatype, save it and create the actual dt with the tool in 1. in the end the created dt must reside in sys:devs/datatypes/ drawer.
Then you would create a default icon in sys:prefs/Env-archive/SYS drawer. Don't forget to reboot or copy .info file to ram:env/sys in order to test. also don't forget to set which tool to start f.e. c:lx or dh4:emulators/mycoolemulator
To test, open Wanderer then show all files and doubleclick on a file of type you just created. Alternatively you could use the 'open' command from shell (with file of datatype you just created as parameter).
And as a last note. it would perhaps be welcome to have a program like xicon and/or runprglist for AROS (unfortunately both without source, but something similar could be created for AROS).
Sounds complicated ?
Perhaps... but OS like windows needs a complete registry to be able to do things like this. And yes, i am aware windows has gui tools that does it (more or less) for you (by manipulating the registry). Same could be done for AROS (without integrating a registry in AROS that is ).
Would that suffice ?
red1+2: typos, reformatting.
disclaimer: please note that using these tools can screw up your currently installed support for datatypes when used incorrectly. Do not use if you do not understand what you are doing. Use at own risk.
==Network Connection==
AROS currently only has one real choice for TCP/IP networking - AROSTCP. This is a port of the AmiTCP package from AmigaOS (TM), with a number of enhancements/fixes from AROS developers.
===Wired===
Use Network Prefs to setup
=====IPv6=====
Some support
128bit IPv6 address packet
<pre>
Local FD::/8
Global 2000::/3
64:ff9b::/96
</pre>
NAT64 translates IPv6 to IPv4
DNS64
OS routing works with
<pre>
MacOS Ventura
Windows 11 with cloud account
Ubuntu Jammy Jellyfish
Android 10 (block google dns)
</pre>
====IPv4====
The top half of the IPv4 Configuration tab on the Network Prefs deals with the network card/USB and the lower half the router part.
[[File:AROS Wanderer Network Prefs DHCP.png|thumb|DHCP Settings]]
'''Upper part of IPv4 tab'''
* Click Add on the top right of the Prefs which opens a window called '''Interface'''
* Enter Name as net0 (but can be anything as long as it is consistently used in other sections)
* check mark on Active
* select device to be used using the '''right hand-side gadget''' of the box where the device name will go
* set Unit to 0
* IP Mode is default set to '''Get address from DHCP'''
* IP Mode set to Manual if DHCP does not work automatically
From the shell CLI, ifconfig -a
Under net0: section, inet starting 192.168.x.xxx
* inet or '''Address''' of network card
* netmask convert to decimal so 0x'''ffffff7f''' becomes 255.255.255.247 which is used to adjust the above '''Address''' into
* broadcast 192.168.xxx.xxx
click OK
[[File:AROS Wanderer Network Prefs Manual.png|thumb|Manual Settings]]
'''Lower part of IPv4 tab'''
* IP Mode Get address from DHCP (default)
* or changing to Manual if automatic DHCP set up does not work
* '''Gateway''' (Router Internal LAN-IP) (Default Route) = 192.168.0.1 (D-Link Netgear), 192.168.1.1 (Linksys 3com), 192.168.2.1 (SMC Microsoft), 192.168.1.254 (Belkin), 192.168.123.254 (USRobotics) else check with your router manual
* first DNS = use 208.67.222.222 (opendns) or Gateway number above (to test web browser access to router) or 212.50.160.100 (google) i.e. or whatever your ISP needs you to set
* second DNS = use 208.67.220.220 (opendns) or Gateway number above (to test web browser access to router) or 213.249.130.100 (google) i.e. or whatever your ISP needs you to set
* At the bottom of IPv4 tab, check mark the '''Start networking during system boot''' option
* Save and reboot (sometimes Network restart fails, so reboot every time to be sure)
'''an alternative way''' to AROS ifconfig -a, other OSs have similar for the same internet connection. Another connection will have different settings.
e.g. From [http://www.ncsu.edu/resnet/windows/ipconfig/ Windows], '''ipconfig /all'''
and note down the IP, subnet mask, default gateway, and DNS servers values and put these values in "manually" into AROS Network prefs.
e.g. From Linux via dhcp router have a look at etc./dhcpc/dhcpcd-eth0.info
* for manual input look at /etc/networks (IP or Gateway) and /etc/resolv.conf (DNS)
Please note that all in one routers (wired+wireless) or separate routers may need different settings
IPv4 involves routing (192,168.x.x), firewall, NAT
===Wireless===
You may have a Wifi Prefs to use for wireless setup
[[File:MyArosWirelessSetup.png|thumb|Setting up]]
[[File:MyArosWirelessTCP.png|thumb|Shell commands to work out what is happening]]
We must first make certain you have a Atheros 5k chip inside acting as the wireless wifi option. Open PCITool in Tools directory. Down left hand side are a series of numbers 0.00.0 etc. Click on some at the bottom and hopefully one of them will say Atheros AR5??? or AR242?.
or a Realtek RTL8187B, we can check using Prefs/Trident as this one is USB based
There are many similarities with the above Wired set up so please read the above section as well
* open Network/Prefs
* In '''IPv4 Configuration''' tab - click Add - enter net0 / active tick / #?.device / Unit 0 / IP Mode = manual (important if default DHCP does not work automatically)
Make sure that any extra network names (e.g. eth1 or net1) should be deleted. If net0 already st previously, change net0 so that it shows associated with the appropriate device name like atheros5000.device or realtek8180.device. Having two entries here will cause sub-net problems.
* Go to '''Wireless''' tab and click on "Add" button.
* Insert network name (SSID your wireless network name use wirelessmanager to get it), select right "encyption" that is most likely "WPA".
* Key Type set as "Passphrase". i.e. type in your password for your router (aka access key).
* Unselect (no tick) "hidden" if it is selected, then apply. You may have to tick it if wireless does not work.
* Finally, Save and '''reboot'''.
For the best chance of success, set networking to start at boot, and then reboot with the USB adapter plugged in.
===USB Ethernet===
Open SYS:Prefs/Network and in the IPv4 Configuration tag (top table covers your usb stick)
* click Add button
* set Name as net0
* Tick Active box
* enter the usb-ethernet.device e.g. dm9601eth.device, usbpegasus.device or usbasixeth.device use SYS:c/devlist, '''Scout''' or trident prefs to get the correct spelling
* set Unit to 0 (which is usual but check the messages from the bottom of the Trident prefs whilst plugging the device in to determine the unit number otherwise)
* IP Mode is set to Get address from DHCP (make sure your router is set right for that)
'''or manual'''
* IP Address of network card, i.e. 192.168.0.xx or 192.168.1.xx (xx being greater than 1)
* Subnet netmask = 255.255.255.0
* click OK
There can be sometimes be boot failures when using USB ethernet - plug the USB device in after boot and save the network prefs to make it work again.
Lower part of IPv4 tab covers the router information
* IP Mode Get address from DHCP
'''or if manual settings'''
* Gateway (IP Address of router) = usually 192.168.0.1 or 192.168.1.1 but see router manual to make sure.
* first DNS = use 8.8.8.8, 208.67.222.222 (opendns) or 212.50.160.100
* second DNS = use 8.8.4.4, 208.67.220.220 (opendns) or 213.249.130.100
===USB Tethering via Android smartphone===
Go to AROS Network Prefs (IPv4 configuration tab) and write type in "usbrndis.device" in the "device" textfield of "Interface" sub-window, which appears when you add a new device (or modify an existing one). Select "Start Network during system boot" and saved the configuration, the Connection is immediate no reboot is needed.<br>
usbrndis.device is a resident device (virtually always there) in fact, a driver is not present in DEVS:Networks <br><br>
Plug in USB cable, go to Android settings and enable "USB Tethering" <br>
A reboot should not be necessary.
When restarting AROS, the Smartphone deactivates the connection and to access the network again have to reactivate it before starting the browser.
===Solving Issues===
[[File:MyArosTCP.png|thumb|Aros network setup diagnostics - why does it not work?]]
* In Network Preferences, have '''only one''' item in the IPv4 Configuration tab
* If using manual settings, make sure all numbers are correct, especially for IP address of the card/usb (changing the last number in chain of four)
* For any USB based networking, it is often necessary to save in Prefs/Network, reboot AROS and network support can begin
* For wired, make sure that the LAN-cable is plugged in before starting the computer
* If wireless, try getting closer to the router.
* Switch off the encryption option from your router then try wifi, if successful then your ip/dns is ok. If not then your ip/dns settings are most probably wrong or need to use one or more opendns numbers
* Replace detachable wireless antenna (best wireless option to buy if you can) with a stronger antenna ie. 5 dBi or 7 dBi
* Try with another computer/laptop/machine
Program Error C:WirelessManager
* Test with another OS
* Check that Wifi works before changeover (if possible)
* Check that socket and card are working
* Check if card is too new for laptop (date code on card MMYY blue askey date 2005-2007 etc)
Are you connecting with the Router ?
Check with protection off e.g. wps and wep to see if it makes a difference.
For USB wireless - stopping and starting may be needed...
<pre>
; $VER: AROSTCP-startnet 1.0 (01/08/06)
; AROSTCP-startnet (c) The AROS Dev Team.
;
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
; stop and restart
execute "sys:system/network/AROSTCP/s/stopnet"
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
run <NIL: >NIL: wirelessmanager realtek8180.device
</pre>
What IRQ number is assigned to the device? You can check with Tools/PCITool?
It's possible the BIOS hasn't set the right IRQ number. If you have a Linux CD/DVD handy, could you check if it boots with the options "acpi=off noapic nolapic"?
If the following does nothing, this will help us figure out why networking doesn't start automatically at boot
open a shell and run the following commands:
<pre>
echo ${AROSTCP/AutoRun}
echo ${AROSTCP/WirelessAutoRun}
echo ${AROSTCP/WirelessDevice}
</pre>
Please report the output, typically it will look like this
# True (explanation this variable is related to the "Start networking during system boot" checkbox in network prefs)
# True ()
# Devs:networks/atheros5000.device unit 0
If there's a problem with the AROSTCP package. What's the output of this?
ENV:sys/packages/AROSTCP
should return a string = Sys:System/Network/AROSTCP
By the way, a quicker way to check networking is working would be to run some shell commands such as:
<pre>
ping www.google.com
ifconfig net0
</pre>
The best way to list the available networks and diagnose / troubleshoot problems with connecting to a wireless network is to run WirelessManager manually. First uncheck the "Start networking during system boot" box in the Network prefs app, then save and reboot. Then run this in a shell:
C:wirelessmanager atheros5000.device verbose
or
C:wirelessmanager realtek8180.device verbose
and capture the output
If the above does not help, could you edit the file SYS:System/Network/AROSTCP/S/Package-Startup, and change ">NIL:" to ">T:wifi.log" on the WirelessManager line and add this as well Wait 5?
<pre>
if ${AROSTCP/WirelessAutoRun} eq "True"
Run QUIET "C:WirelessManager ${AROSTCP/WirelessDevice} >T:wifi.log"
wait 5
EndIf
</pre>
Then save, reboot and post the log file (T:wifi.log) here.
<pre>
c:wirelessmanager atheros5000.device verbose
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7)
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
Then it just sits there. Not sure what a normal dump looks like, I don't see anything that looks wrong in the configuration.
</pre>
looks like the driver isn't working with that card. Has anyone else successfully used that exact model number (AR2413)?
<pre>
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7):
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
*** [wpa_sm_init] sm->pmksa=02c66fd4 ***
Own MAC address: 00:01:36:15:ae:0c
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
Added interface atheros5000.device:0
State: DISCONNECTED -> SCANNING
Started AP scan for wildcard SSID
MLME: starting scan
MLME: scan channel 1 (2412 MHz)
sana2: sending MLME frame
Then it stops. Does this mean the router is not authorizing this NIC?
IRQ 4 (A)
</pre>
apparently locking up when the first frame is sent (a scan request).
<pre>
Devs/Networks/atheros5000.device:0
Initializing interface 'Devs/Networks/atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=12):
41 69 72 4c 69 6e 6b 35 39 33 30 30 AirLink59300
PSK (ASCII passphrase) - hexdump_ascii(len=8): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='AirLink59300'
*** [wpa_sm_init] sm->pmksa=0224e444 ***
Own MAC address: 00:1f:e1:42:e3:7a
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
[eloop_reg_timeout] Timeout is at 1317686594.160000
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
[eloop_reg_timeout] Timeout is at 1317686595.060000
[eloop_reg_timeout] Timeout is at 1317686604.060000
Added interface Devs/Networks/atheros5000.device:0
[eloop_run] Starting
State: DISCONNECTED -> SCANNING
Starting AP scan for wildcard SSID
MLME: starting scan
[eloop_reg_timeout] Timeout is at 1317686594.160001
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.233000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.373000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.513000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.553000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.693000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.013000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.073000
EAPOL: disable timer tick
EAPOL: Supplicant port status: Unauthorized
MLME: scan channel 14 (2484 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.113000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.153000
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.213000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.353000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.493000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.533000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.673000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.993000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686596.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686596.073000
MLME: scan completed
</pre>
Is your network hidden? If so, did you enable the 'Hidden' checkbox in the network prefs? What distro version are you using?
<pre>
"ENV:sys/wireless.prefs" looks like this:
network={
ssid="testadhoc"
key_mgmt=NONE
wep_key0="12345"
wep_tx_keyidx=0
}
</pre>
If your router doesn't broadcast its SSID (hidden), you need to add this option to the network block of the wpa_supplicant.conf on your aros machine and make changes after # Example blocks:
scan_ssid=1
Here's a full description of all the [http://hostap.epitest.fi/gitweb/gitweb.cgi?p=hostap.git;a=blob_plain;f=wpa_supplicant/wpa_supplicant.conf config file options].
<pre>
ap_scan=1
network={
ssid="YOURESSID"
scan_ssid=1
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP
group=CCMP
psk=YOURPASSWORD
}
</pre>
<pre>
filter_ssids=1
ap_scan=2
network={
ssid="REMOVED"
scan_ssid=1
bssid=REMOVED
priority=100
mode=0
proto=RSN
key_mgmt=WPA-PSK
auth_alg=OPEN
pairwise=CCMP
group=CCMP
psk=REMOVED
}
</pre>
Error 6: Couldn't resolve host name.
Check Scout -> Devices and look at the device that you are using, in the OCnt column it should state 2 which means AROSTCP and Wirelessmanager are both accessing this driver. If 0 or 1, then uncheck the checkbox in Network prefs for starting networking at boot, save and reboot. Then run this is the shell:
C:WirelessManager realtek8180.device unit 0
some quirks setting up the wireless network as well
1) it's far better setting up either the wired OR the wireless network adapter as net0:, or weird things happen
2) it's better using fixed IP on the local network instead of DHCP
3) network setting must be placed in network setting panel in /prefs, using the wirelessmanager helped me finding available SSIDs, but not actually connecting to them
once done, reboot.
If previous setup is proving problematic
<pre >
SYS:Prefs/Env-Archive/Wireless.prefs
SYS:Prefs/Env-Archive/Zune/OWB.config
SYS:Prefs/Env-Archive/Zune/global.config
SYS:Prefs/Env-Archive/AROSTCP/WirelessDevice
SYS:Prefs/Env-Archive/AROSTCP/db/Interfaces
</pre >
Make a copy of these files and restore in case of problems.
Please try this test to check if you can connect to your router, ie established that the WiFi layer is working
̊̊̊̊Boot with networking disabled, by make sure that "Start networking at boot" in Network Prefs is unchecked (no tick).
̊ Run this in a shell: C:WirelessManager atheros5000.device VERBOSE
̊If the output of that command is too long to summarise here, you can redirect it to a file by adding >RAM:wifi.log to the end, then attach or paste that file here.
try running "status" in the shell and check that AROSTCP is listed/running
If AROStcp is not showing, then AROSTCP is not running. attempted to start it by clicking Use or Save in network prefs, or checking the "start networking at boot" box or typing into a shell.
Execute SYS:System/Network/AROSTCP/s/startnet
(run Status again afterwards).
The "cannot resolve hostname" will appear if you are blocked on the wifi network by the router as well as aros not being able to assign correct network address.
One way of testing this might be to disable the firewall in the router. you might also check the router how it sees the attempts aros do to speak to it. The easiest way to do that would be to manually give aros an IP number in the routers accepted range. and see if it shows up at all within the router.
Tests that can be undertaken to determine correct settings and functions
pciinfo
sanautil -d broadcom4400.device status
<pre >
ping <router-address> e.g. 192.168.0.1 (aka inet) or 80.237.146.33 (www.amiganews.de)
ifconfig net0
ifconfig net0 up
extras:networking/utils/sanautil/sanautil -d atheros5000.device status
WirelessManager atheros5000.device verbose >RAM:wifi.log
;to send the log to RAM disk to be read easier or if detected,
Run WirelessManager atheros5000.device >NIL:
Run WirelessManager atheros5000.device ssid="mynet1" >NIL:
C:WirelessManager realtek8180.device unit 0
</pre >
Please look at the task list in Scout, and check if WirelessManager and AROSTCP are running. Also look at the device list in Scout to check if realtek8180.device is open.
start tools/debug/sashimi, maybe it shows some debug messages when disconnection happens.
Firstly, let's take a look at what your setup most likely looks like, assuming you use a router. See diagram below:
<pre>
Internet <---------> home router <---------> computer
-----------external IP------------------internal IP-------------
</pre>
Okay, so what am I trying to show you with that diagram. A few things. Firstly, the IP address that connects you to the Internet is not the same one that connects you to your router. What happens is that your computer doesn't have a direct connection to the Internet, instead your router connects to the Internet, and your computer connects to the router.
You can see the external and internal IP addresses in these example settings...
* Default Gateway : 76.91.64.1 (external IP for ISP/Internet host)
* IP Address : 76.91.71.184 (external IP for home router)
* IP Address : 192.168.0.1 (internal IP for home router)
* Address = 192.168.0.161 (internal IP for computer)
As you can see, there are two internal IP addresses and two external IP addresses. This is because there is a client/server relationship, effectively one address is for the service (server) and one address is for the device trying to access that service (client).
The server addresses in your case are 76.91.64.1 (your ISP's address, serving the Internet), and 192.168.0.1 (your home router's address, serving your home network). The term gateway applies here, they are your gateway to those services.
Subnet masks are used along with IP addresses to determine which IP addresses are allowed access to a network. I did learn the more in-depth rules about subnet masks once (watched a CCNA vid), but I've forgotten about it. The basic level of understanding you'll need is easy to remember though. A subnet mask value of 255 means that portion of the IP address must stay constant, whereas a subnet value of 0 means any unassigned value up to 255 is allowed in the IP address.
By far the most common subnet value is 255.255.255.0. What this means is that the first three parts of the IP address you use to connect to a service must stay the same as the server/gateway address, and only the last section can change.
So if your router's internal IP address is 192.168.0.1, and the subnet mask is 255.255.255.0, the only addresses that will be allowed to be used on that network are between 192.168.0.2 and 192.168.0.255 (I think 192.168.0.0 is reserved for other uses).
Final point to make is about DHCP (a.k.a. dynamic IP) vs static IP. A server/router using DHCP gives a device that connects to it an address within the acceptable range. It usually starts with the lowest numbered free address, so with your router it'll give the first device that connects to it 192.168.0.2, the next device 192.168.0.3, and so on. Static IP addresses are where you set the IP address you want to connect with in advance.
When using static IP addresses on a router where DHCP is active, it's good to use a high number to avoid conflicts with other devices that are connected to your network, to reduce the risk that both devices will try using the same IP. That's why your current choice of 192.168.0.161 is good, unless you have over 159 devices connected on your current network!
Okay, so what's the next step. Well, if you can use ping, I'd suggest pinging 192.168.0.1. If you get a positive response it means you're connected to your router, if you don't get a response it means the connection between your router and your computer is at fault.
Documentation on configuring the AROSTCP environment further can be found [http://en.wikibooks.org/wiki/Aros/User/Networking here]
===File Sharing===
As AROS knows only a few filesystems (FFS, OFS, SFS, PFS (amiga only), FAT12, 16, 32, Microsoft NTFS (windows), UDF (Blu-ray)).
The others in regular use like MacOSX hfs+, Linux ext2/ext3 and ext4, Haiku BeFS provide a problem in transferring files.
Linux can access SFS partitions but it needs to be compiled. The latest full source are [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ here]. It compiled fine with a 2.6.30 kernel in Puppy Linux 4.31.
An alternative, is to use a FAT32 partition to share. Setup a 4G FAT32 partition using HDToolbox for sharing, and the rest of the space as SFS for an Aros install. It works very well.
Files could be transferred via TCP internet network.
====SMB2/3====
With Windows you can share one folder or all folders of the "Public" user.
On Windows what is important is to enable sharing (Network and Sharing Center).
AROS Mountlist should look lke this
<pre>
Handler = L:smb2-handler
StackSize = 65536
Priority = 5
GlobVec = -1
ACTIVATE=1
Startup = "smb://UserAcc:password@PCShare/Sharefolder"
</pre>
which could also be
"smb://UserPC:password@192.168.x.x/Public"
or
"smb://UserPC:password@Name-PC/Public"
so
"smb://UserPC:password@192.168.1.158/Folder"
or
"smb://UserPC:password@Name-PC/Folder"
After you have configured a share generates a DOSDrivers it is named "SMB0" which includes the setting, and at each reboot it is Mounted. You can still delete the DOSDriver by hand, is located in Storage/DOSDrivers, the file "ServerAutoMounts", in ENV:AROSTCP which indicates the DOSDriver to be mounted, should also be deleted.
The per-mount files are written to ENV:SMB or SYS:Storage/DOSDrivers. There is also additional file ENV:AROSTCP/ServerAutoMounts which states what will be presented to the end user.
====Old SMBFS====
e.g. to connect to a NAS share such as \\NASBOX\Shared use -:
SMBFS WORKGROUP=<YOUR WORKGROUP NAME> VOLUME=<AROS volume name to use>: SERVICE=<UNC Path to connect to>
SMBFS WORKGROUP=MYNET VOLUME=Shared: SERVICE=//NASBOX/Shared
And you will then have an icon appear on your desktop for the volume name you have chosen.
You can put the above script into wbstartup or
give it an icon, change it to a 'project' and give it the default tool c:iconx
Open a shell and type copy sys:script.info "sys:wbstartup/YOURSCRIPTNAME.info"
This should create an icon for your script file.
Now right-click on your script and select 'information'.
Change 'tool' to 'project', put 'c:iconx' into the 'default tool' box, click save
The reason being that scripts need to be opened with 'execute SCRIPTNAME' (or 'iconx') whereas the programs started from wbstartup are opened using 'run PROGRAMNAME'. It's the same as trying to start a command-line tool from the workbench by double-clicking it.
====Setup ISO images within AROS====
Use [http://archives.aros-exec.org/index.php?function=browse&cat=driver/storage DiskImage] which supports many cd image formats ISO, CCD, MDF/MDS, CUE/BIN, NRG and UIF. To mount CD or DVD images use below....
<pre >
# Rename your iso 'Unit0' (note no extension).
# Do 'View/All files' on you Aros partition. You should now see a folder called 'Diskimages'. Copy your renamed iso to there.
(Alternatively, you could type at the shell 'assign FDSK: xxx', where xxx is the location of your iso.)
# From the shell, type 'mount CD0:' and the iso should appear on the Wanderer desktop. You can now access it like a real disk.
</pre >
assign devname: dismount
Assign DOSVOLUME: remove
[http://aminet.net/package/disk/misc/unmount-0.1 unmount] most filesystems work but SFS lacks support for ACTION_DIE packet
If you are using an IcAros install, the startup scripts are set up to wipe the Diskimages directory on boot, so its worth keeping a second copy of the iso somewhere else. Alternatively, you could set up extra mountlists for additional iso images. I've made a file called iso1 in the Aros:devs directory that contains the following text:
<pre>
/* Entry for ISO image */
ISO1:
FileSystem = cdrom.handler
Device = fdsk.device
Unit = 1
LowCyl = 0
HighCyl = 0
Surfaces = 1
BlocksPerTrack = 1
DOSType = 0x41434400
Activate = 1
#
</pre>
Then I just need an iso called 'Unit1' (corresponding to the 'Unit = 1' entry in the mountlist) in Diskimages (or wherever I assign FDSK: to) and to mount I type in at the shell:
Mount iso1: from devs:iso1
Of course, if you create mountlists for ISO2, ISO3:, etc. (with the corresponding change to the 'Unit = ' line) you can have as many isos mounted as you wish. I just call mine ISO1: etc. to distinguish them from the real CD drives
==Video Guides==
Video demonstrations and tutorials covering:
:00. '''Introduction'''
::[https://www.youtube.com/@jamesmattson6813/videos Various Aros Installs],
::[https://www.youtube.com/embed/j8EmSEby0Rg AROS repo in gource, view of AROS dev commits from 1997 to 2025], [http://www.youtube.com/watch?v=Vx_zqlBow40&feature=related Gource view of AROS 1997 up to 2009],
::[http://www.youtube.com/watch?v=s1RsvEm7UrU Why an Amiga OS in 2011],
::[https://www.youtube.com/watch?v=1W886mheV74&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Johan Grip on early days of AROS x86], [https://www.youtube.com/watch?v=mXaKDhtTTqQ&t=14s&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Michel Schulz on Aros and PiStorm],
:01. '''Installation'''
::[https://www.youtube.com/watch?v=M7YjufrJqDs Aros One install], [https://www.youtube.com/watch?v=iIMguHTdC5E Aros One USB install], [https://www.youtube.com/watch?v=ZNXauy5m5Wc Aros One install], [http://vimeo.com/11013489 Modify Grub boot],
::[http://www.youtube.com/watch?v=wyQVeyXIywc&feature=channel iMica Silent Pt3], [http://www.youtube.com/watch?v=o2AnkoflY14 Wipe whole drive and Install - warning loss of data on drive],
::[http://www.youtube.com/watch?v=OVXm6_-witQ VirtualBox install], [ VMware install],
::[http://www.youtube.com/watch?v=0k2PEmT8I14 Broadway AROS Install],
::[https://www.youtube.com/watch?v=PtDiXhjSIfs Is Aros Icaros a choice?],
::[ driver install],
::[http://www.vimeo.com/10491104 HDAudio install but needs account], [],
:02. '''Amiga Basics'''
::[http://www.youtube.com/watch?v=TY8mWxwzH5o Screens tutorial],
::[https://m.youtube.com/user/AMIGASYSTEM/videos General], [ Dos Scripts tutorial], [http://www.youtube.com/watch?v=hPT7SmVEpjc OS 1.2], [http://www.youtube.com/watch?v=n6kX3FqH8Ww&feature=related OS 1.3],
:03. '''Customisation demos'''
::[https://www.youtube.com/@AMIGASYSTEM/videos Prefs tutorial], [ Decoration tutorial], [http://www.youtube.com/watch?v=Dn5C8G3aDXU Scalos],
:04. '''Setting up''' internet access and surfing the web, FTP, IRC and Mail apps
::[ Network Prefs], [ AirCOS tutorial], [ jabberwocky tutorial],
:05. '''Native bundled Games and Applications'''
::[http://www.youtube.com/watch?v=aYlFv2B-VXc 3D Games], [http://www.youtube.com/watch?v=MXK7wwhd-R0 Latest Games], [http://www.youtube.com/watch?v=RUgiVThv23Q&feature=mfu_in_order&list=UL PrBoom GL], [http://www.youtube.com/watch?v=0s7u8TPy7V4 Assault Cubes], [http://www.youtube.com/watch?v=fih6aCXKeqs Cube 2], [http://www.youtube.com/watch?v=-X0ay0MGOms DosBox on Aros], [http://www.youtube.com/watch?v=7nKduDjf14k Oct 2010],
::[http://www.youtube.com/watch?v=FziV2z_uxnQ Apps Pt 1], [http://www.youtube.com/watch?v=xs37_nfa5CI Apps Pt 2], [http://www.youtube.com/watch?v=Bn59_VvbQR0&feature=related Apps Pt 3],
::DOpus4 [http://www.youtube.com/watch?v=aSRybWjrrME DOpus 4],
::Milkytracker [http://www.youtube.com/watch?v=VxBOEPzpdKg&feature=related Laying Down Base Tracks],
::[http://www.youtube.com/watch?v=k2uKQ0-ieOE Audio Evolution 4 in action], [http://www.youtube.com/watch?v=Zq4r9k0_jZI Quick Videos],
::[http://www.youtube.com/watch?v=gGKCFZcIc0I&feature=related ScreenRecorder], [http://www.youtube.com/watch?v=974c2e-Fqak&feature=related TV out Tests],
::[http://www.youtube.com/watch?v=fjq8ct5d5IY AmiFIG], [http://www.youtube.com/watch?v=h0rHvPhYJo4&feature=youtu.be ZuneFIG],
::[http://wiki.povray.org/content/Documentation:Tutorial_Section_1 POVray Tutorial 1],
::[http://www.youtube.com/watch?v=Jk-ZNLfJsvQ pt 1, jan. 2008], [http://www.youtube.com/watch?v=nWRy33g1R7Y pt 2, feb. 2009], [http://www.youtube.com/watch?v=r5PbhCtm4vE pt 3, feb. 2010],
::[https://www.youtube.com/watch?v=G7_FJUoQ89o Hollywood programming], [], [], [],
::[], [], [],
::[], [], [],
::[], [], [],
:06. '''Commercial software available'''
::[http://www.youtube.com/watch?v=fKXY9B4R43s AntiryadGX 3D Game Editor],
::[http://www.youtube.com/watch?v=TMS9NDzwm5U BOH indie Game],
:07. '''Running classic amiga apps and games'''
:: Amiberry [], [],
::[http://vmwaros.blogspot.com/2008/11/introducing-amibridge.html Intro Amibridge], [http://www.youtube.com/watch?v=ee2PWvCZeLo Old Amiga Apps], [http://www.youtube.com/watch?v=ee2PWvCZeLo Why Janus UAE is good],
::[https://www.youtube.com/watch?v=VhlsNSYSuDg DPaint tutorial]
::[http://vmwaros.blogspot.com/2009/11/can-icaros-play-my-amiga-games-and-why.html Play Amiga Games], [https://www.youtube.com/watch?v=XTaZCNOvCnE],
::[http://www.youtube.com/watch?v=tMehS77LXQ4 Pagestream Introduction], [http://www.youtube.com/watch?v=284-w3hTzII Pagestream Tutorial 1], [http://www.youtube.com/watch?v=mlwEGwhZzl4 Pagestream Tutorial 2],
::[http://www.youtube.com/watch?v=iIcrIjPOctc Catweasel Mk4 PCI Part 1] and [http://www.youtube.com/watch?v=BaitHeL6bEA Part 2],
:08. '''Misc and History'''
::[http://www.youtube.com/watch?v=d6mDXKU29w0 Mum uses old AmigaOS Workbench 1.1 (1986)], [http://www.youtube.com/watch?v=DaRkacQ-YMg Why an Amiga 500 (1987)], [http://www.youtube.com/watch?v=k5CYsgVCzYY an Amiga 2000 (1987)],
:09. '''Misc Shows and Events'''
::[http://www.youtube.com/watch?v=klgVSWKs4kE VCF 2010], [https://www.youtube.com/watch?v=eQ3d5qR-Hv8 24:06 Jason McMullan at amiwest 2012 about AROS], [https://www.youtube.com/watch?v=jpQO7XSfAv4 Aros SMP multi core amiwest 2013], [], [https://www.youtube.com/watch?v=gFRtAAmiFbE], [https://www.youtube.com/watch?v=DjdUEyjx8GM], [https://www.youtube.com/watch?v=ydYDqZQpim8], [], [https://www.youtube.com/@uminekoshouten/featured], [https://www.youtube.com/shorts/NfoY023w-vE],
:10.
::[https://www.youtube.com/shorts/6qJTNW4-6GY]
===History===
The project was originally started by a small group of Amiga [http://www.amigahistory.co.uk/aros.html enthusiasts] in 1995. These individuals were mainly computer-based college university students at the start, though that student trend has diminished since. An interview with Aaron Digulla [http://arosshow.blogspot.com/2006/12/interview-with-aaron-digulla-who.html here]
* 1992 Commodore folds
* 1996-1998 much of the early years was concerned with exec, dos and intuition libraries.
* Early 1999, Haage & Partner used parts of the AROS code in AmigaOS 3.9.
* March 2001, floppy disk images of AROS became available.
* Early 2002, AROS changed its name from Amiga Replacement Operating System to Amiga Research Operating System
* June 2002, AROS devs decided to use Zune (MUI 3.8 rewrite) as the GUI system.
* November 2002, Eric Schwartz drew Kitty for AROS usage.
* Early 2003, AROS.org underwent a graphics facelift.
* Late 2003, GCC C compiler arrived.
* Early 2004, Aros-Exec opened.
* Early 2005, Aros Max bootable CD arrived.
* Late 2005, SFS filesystem ported and allowed fast access to apps and network support arrived
* Early 2007, AROS.org underwent another graphics facelift.
* Mid-2007, AROS changed to AROS Research Operating System after A.Inc. sued Hyperion with a trademark violation.
* Late 2007, the hard disk installer added and VmwAROS (later called Icaros Desktop) distro launched.
* Early 2009, Our first usable web browser (OWB)
* September 2010, first wireless support appears and AspireOS started as a distro
* Early 2012, the first paper-cut bugfix and Fab's Odyssey Web Browser ported
* Early 2017, work started on utilising the addition cores on modern CPUs starting with the 64bit x86 PC version
* Mid-2017, m68k port optimized for the Vampire 2 / Apollo accelerators (68080 AMMX FPGA)
* 2018 The old AROS Exec website closed and a new one opened
* 2019 AROS One x86 32bit distribution started and now with USB install version
* Early 2021, backport of more features of 32bit PC ABIv1 into 32bit PC ABIv0 (Aros One 1.5 and above)
* 2025 year of 64bit pc builds and porting 32bit applications to 64bit ABIv11
* 2026 update of [https://www.youtube.com/watch?v=6FKTL068ULM&pp=ygUPYXJvcyBhbWlnYSAyMDI2 nvidia nouveau driver for 64bit PC]
===Bounties===
To help inspire developers with both ideas and monetary incentives, rewards are offered for the successful completion of "bounties" (requests for missing/new functionality) chosen by the community and handled by [http://power2people.org power2people] (formerly done by TeamAROS). A monthly option is [http://www.power2people.org/funds/aros/ here].
Future goals for AROS include expanding its underlying retargetability to support even more diverse architectures, provide memory protection features and user level file security, SMP and many other wonderful features missing from AmigaOS — while still providing as much source level compatibility as is possible (however it is accepted that to achieve some goals code certain things may require a little recoding).
[http://www.ohloh.net/p/aros/contributors Developers] come and go as with any open source effort and we would like to thank them for their efforts...
;1996-2000:In DigullaA (coordinator), GripJ, TempletonI (BSD), SchulzM, RittauS, voordenDagL, HolmM, JohanssonT, VanIngelgomH, SteigerwaldM, BortasP, deJongK, AlfredssonJ, InnocentiB,
;2001-2005:In [http://chodorowski.com/adam/aros.html ChodorowskiA], StegerG, BergerS, HeutlingS, AlemagnaF (gcc), VerhaegenS (rexx), KielH, MatheussenKS (CAMD), SzczygielskiP, ErikssonP, LeCorfecD (Zune), BauerS (Zune), FurlongW, GustafssonJ, AndrewsN, CafferkeyN, GierichM (jpeg), PattonJ, ParsonsM, DietrichJ, SeilerT, BischoffL, LorentzenNH, AdamO, BerglundH, SmithP, HolmenD, BlomM,
;2006-2010:In FedinP, RusslerM, SzymczykS (owb), SmiechowiczK (openGL), WeissM, NorrisR, BrunnerO, WiszkowskiT, GreppinA, [http://www.fukt.bsnet.se/~bearsoft/ Bearsoft Björn Screwelius], ErbY, CharletF, HodgesC, [http://aros-exec.org/modules/newbb/viewtopic.php?topic_id=4819&forum=18&post_id=43103#forumpost43103 HokstadV], McMullanJ (m68k), WilenT (m68k),
;2011- :In MuijzenbergPHvanden, ALB42, JonesEM, weiju, DizzyofCRN, wawa, miker,
* 1996 - The linux hosted version for i386 was the first to arrive
* 1998 - i386, The native version for i386-based PC AT computers and compatibles.
* 2004 - x86/64, The native version for 64-bit (x86_64, amd64) PC computers.
* 2008 - sam440/ppc, The native version for Sam440EP, Sam440EP Flex and Sam460ex computers.
* 2009 - efika, The native version for PowerPC Efika computers.
* 2010 - m68k, The native version for m68k Amigas or WinUAE
* 2013 - raspi/armfh, early native version for ARMv6 based Raspberry Pi computers.
* 2017 - x86/64bit smp
Debugging capture serial debug at all (especially with sysdebug=all or --sysdebug=all) to see it displayed on screen
* yes, usb -> rs232 adapters can work most of the time, some of the cheapest ones are not fully compatible with all rs232 devices to capture to another device
* you will need a null modem cable (or a null modem adapter usually female to female) in addition to the usb -> rs232 adapter (usb adapter is a normal modem ie. the pins are not crossed over)
Normal modem cable - straight connection DCE
<pre>
Pin 2 -> Pin 2 RXD
Pin 3 -> Pin 3 TXD
Pin 5 -> Pin 5 GND
</pre>
Null modem cable connections DTE
<pre>
Pin 2 -> Pin 3
Pin 3 -> Pin 2
Pin 5 -> Pin 5
</pre>
(9pole SUB-D)
<pre>
serial ser: (amiga/aros) tty2 tty1USB0 (linux) COM1 (windows) (depends on the os being used)
speed baud transfer rate 9600 38400 lower baud might be more successful
data bits 8
stop bits 1
parity none
handshaking flow control - none xon/xoff (most likely) rts/cts dsr/dtr (pins not connected so should not work)
</pre>
*You cannot use compiled aros X86-64 bit software (when ready) on aros X86 32bit. PPC compiled software on X86 and so on.
*68k is tested with the UAE emulator (WinUAE) but some tests are done on native 68000 based Amigas and others.
*PPC support is very limited to certain devices.
If you use the WBStartup, you have to delete the other icons in the folder (readme etc..) and you have to add in the Icon Tooltype the parameter DONOTWAIT
If you use user-startup instead, you need to add the attached command "after assignment to LUA"
C:WBRun DH1:Extras/Utility/WeatherBar/WeatherBar >NIL:
Change the command to match your WeatherBar path.
<pre>
PATH sys:Utilities/WeatherBar ADD
run >nil: lua:amilua weatherforecast.lua
</pre>
To enter data your Country or City, ist with city_id numbers can be found [http://bulk.openweathermap.org/sample/city.list.json.gz here] or you need to go to [https://www.bbc.com/weather BBC Weather], once you type the name of your city or town in the appropriate tab, and press enter, the 7 numbers to be added in the "WeatherBar" will appear on the Browser url address bar above
Unicode v16.0 emojis are not supported but [https://github.com/jens-maus/libcodesets codesets.library] provides
<pre>
internally supported (hardcoded) charsets/codesets are: (conversions are possible from and to each codeset):
AmigaPL – Polish (Amiga)
Amiga-1251 – Cyrillic (Amiga)
ISO-8859-1 – Western European
ISO-8859-1+Euro – West European (with EURO)
ISO-8859-2 – Central/East European
ISO-8859-3 – South European
ISO-8859-4 – North European
ISO-8859-5 – Slavic languages
ISO-8859-9 – Turkish
ISO-8859-15 – West European II
ISO-8859-16 – South-Eastern European
KOI8-R – Russian
UTF-8 – Unicode
In addition, external charset table files can be stored in LIBS:Charsets or loaded by an application from PROGDIR:Charsets. The charset files included with this distributions are:
IBM866 – Cyrillic (cp866)
ISO-8859-7 – Greek (LatinGreek)
ISO-8859-10 – Nordic (Latin 6)
windows-1250 – Central/East Europe (Windows)
windows-1251 – Cyrillic (Windows)
windows-1252 – West European (Windows)
</pre>
Icaros 2.3 USB image needs a header stripped so it can work correctly
dd bs=512 skip=1 status=progress if=icaros_light_2-3-0_pendrive.bin of=/dev/sdxy && sync
Scalos
<pre>
-------------------------------
{ "STRING", "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K",
HALIGN LEFT | CENTER | RIGHT
VALIGN TOP | CENTER | BOTTOM
STYLE NORMAL | BOLD | ITALIC | BOLDITALIC
FONT // font specification - format: "fontname.font/size"
-------------------------------
arguments for STRING SRC
"diskstate",
"diskusage",
"diskusagefree",
"diskusageinuse",
"diskusagepercent",
"fibfilename",
"filecomment",
"filedate",
"fileprotection",
"filesize",
"filetime",
"filetypestring",
"iconname",
"linktarget",
"plugin" pluginname <optional plugin arguments>
"versionstring",
"volumecreateddate",
"volumecreatedtime",
"volumeordevicename",
-------------------------------
arguments for HIDE
"novolumenode",
"isempty" (some STRING)
-------------------------------
all internal commands:
"about",
"backdrop",
"cleanup",
"cleanupbyname",
"cleanupbydate",
"cleanupbysize",
"cleanupbytype",
"clearselection",
"clone",
"close",
"copy",
"cut",
"delete",
"emptytrashcan",
"executecommand",
"formatdisk",
"iconify",
"iconinfo",
"lastmsg",
"leaveout",
"makedir",
"open",
"parent",
"paste",
"putaway",
"quit",
"redraw",
"redrawall",
"rename",
"reset",
"selectall",
"showallfiles",
"showonlyicons",
"shutdown",
"sizetofit",
"snapshot",
"snapshotall",
"snapshotwindow",
"unsnapshot",
"update",
"updateall",
"viewbydate",
"viewbyicon",
"viewbysize",
"viewbytype",
"viewbytext",
</pre>
{{status|50%}}
{{BookCat}}
awvyxrzjb8c5ynkx7p4u51jw25fgmxv
4675861
4675858
2026-10-13T16:08:28Z
Jeff1138
301139
4675861
wikitext
text/x-wiki
{{ArosNav}}
==What is AROS==
Google translation
[http://translate.google.com/translate?hl=en&sl=auto&tl=de&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs German], [http://translate.google.com/translate?hl=en&sl=auto&tl=nl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Dutch], [http://translate.google.com/translate?hl=en&sl=auto&tl=fr&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs French], [http://translate.google.com/translate?hl=en&sl=auto&tl=it&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Italian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=da&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Danish],
[http://translate.google.com/translate?hl=en&sl=auto&tl=es&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Spanish], [http://translate.google.com/translate?hl=en&sl=auto&tl=hi&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Hindi], [http://translate.google.com/translate?hl=en&sl=auto&tl=zh-CN&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Chinese],
[http://translate.google.com/translate?hl=en&sl=auto&tl=ru&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Russian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Polish], [http://translate.google.com/translate?hl=en&sl=auto&tl=ja&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Japanese], [http://translate.google.com/translate?hl=en&sl=auto&tl=ko&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Korean],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pt&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Portuguese],
*Computer Hardware
*AROS (operating system)
*Applications and Games
*User
[http://www.osnews.com/story/15819 AROS] is one of the intermediate levels between the computer hardware and the user. It is an open-source, clean-room implementation of AmigaOS 3.x that can be run on many different computer architectures. It runs primarily on PC x86 32bit and 64bit but also on amiga motorola 68k and compatibles, some ARM like the Pi and Apple Silicon, RISC-V and some old PowerPC.
This page will cover enough to be able to write the downloaded image to your preferred media, to run a LiveUSB, LiveCD or LiveDVD on your office/home PC (Live meaning you can test without changing your existing setup) and, ultimately, to use it.
Intel / AMD PC hardware support mostly covers the years 2000 to 2024. At the moment, AROS is '''not''' recommended to be '''installed''' on a working vital data holding machine. Instead, writing to and booting from a '''USB stick''' could be a much better option.
AROS is an hobby OS and can co-exist with Windows(TM), MacOSX(TM), Android(TM) or Linux(TM) and act as an alternative.
Unfortunately, Aros has few developers so upgrades and improvements can take [https://sourceforge.net/p/aros/mailman/aros-cvs/ time to appear].
AROS core is now [http://en.wikibooks.org/wiki/Aros/Developer/IncompleteAPIs ~80%] finished and is usable, so keep in mind that the software is still considered ALPHA/BETA and in constant development. Currently AROS is fun to play with on a curiosity level, but it is also interesting to program. AROS has some multimedia features and has internet access.
Most importantly, use AROS to its maximum potential as it stands now, find ways to have fun with it and share your experiences.
Good Sites to visit
: [https://www.arosworld.org/home.php Aros World User forum]
: [https://arosnews.github.io/ AROS News]
: [https://www.facebook.com/ArosWorkshop/ Aros Workshop],
: [https://www.osnews.com/topic/amiga-aros/ OSNews]
: [https://www.reddit.com/r/aros/ Reddit]
: [https://archives.arosworld.org Aros Archives]
: [https://aminet.net/ Aminet]
: [http://www.amiga-news.de/en/ English translation of German site]
: [https://aros.sourceforge.io AROS] with [https://aros.sourceforge.io/download.html ABIv1 downloads]
: [https://github.com/aros-development-team/AROS Aros ABIv1 Codebase]
: [https://github.com/aros-development-team/AROS/issues register ABIv1 issues] and [https://sourceforge.net/p/aros/bugs/ old defunct bugs notification site]
: [https://sites.google.com/view/arosone Aros One x86, x64]
: [https://tinyarosdistro.flazio.com/ Tiny Aros x86 and x64]
: [https://arosnews.github.io/aros-portable/ AROS portable USB3 stick images of hosted Aros One x86 and x64 on debian]
: [http://vmwaros.blogspot.com Icaros Desktop x86 now on sabbatical, very old edition]
: [https://sites.google.com/site/arosaspireone AspireOS, of the netbook Aspire One, very old edition]
: [https://github.com/deadwood2 Deadwood's builds], [https://www.axrt.org/download/aros/v11/ v11 64bit PC builds], [https://axrt.org/downloads-aros Updated i386 32bit PC builds],
: [https://github.com/ezrec Ezrec x86 m68k mirror of old svn version]
: [http://arosalive.blogspot.co.uk/p/10-basic-aros-how-tos-tutorials.html Basic How To guides]
: [http://arosgamer.blogspot.co.uk/ AROS Playground], [http://thewetmachine.net/tag/aros/ Jess Wet Machine], [https://aroshacking.wordpress.com/ Jon Robertson's AROS Experiences and FPC Free Pascal], [],
:[http://www.apollo-accelerators.com/ Apollo Accelerators m68k], [http://www.amigablogs.net/ Amiga Blogs], [http://blog.a-eon.biz/blog/ Trevor Dickinson blog],
: [https://forum.amiga.org/ Amiga OS AOS 3.x forum]
: [http://eab.abime.net/ EAB Amiga]
: [http://www.amigaworld.net/ AmigaWorld]
: [http://www.ppa.pl/ Polish Amiga Like News]
: [http://www.apollo-core.com/ Apollo Forum]
: [https://amigaalive.blogspot.com/ AmigaAlive]
: [https://www.amigalove.com/software Disk Mags]
: [https://amigachristmastree.ultimateamiga.com/ Xmas Amiga Game Jam]
: [https://www.reddit.com/r/amiga/ Amiga]
== Distributions aka Distros ==
For end users there are distributions (ready made with selected apps aiming to be easy to use), mostly created and maintained by one person in their own workflow/style. They reuse the nightly boot compiles to suit their needs and possibly other end users. You are free to create your own if required.
* For native 64bit Intel/AMD: [https://sites.google.com/view/arosone Aros One x64], [https://tinyarosdistro.flazio.com/ Tiny Aros],
* For native 32bit Intel/AMD which will run on 64bit machines: [https://sites.google.com/view/arosone Aros One x86], [https://www.tinyaros.it/ Tiny Aros],
* For native 68k [https://sites.google.com/view/arosone Aros One m68k], [http://www.aros-platform.de/ AROS Vision],
'''Please, keep in mind that the distros listed above use a different ABI (abi v11) , which is NOT binary compatible with the official ABI V1.'''
* For hosted Linux usb drive image [https://arosnews.github.io/aros-portable/ x64 Debian hosted version of Aros One],
* For hosted ARM there is [https://github.com/jonx/AROS-AArch64/releases alpha for Apple Silicon] and [https://aros.sourceforge.io/nightly1.html RaspberryPi Pi3, Pi4, Pi400, Pi5, 500+ raspi-aarch64-system native 64bit]
AROS was originally developed on Linux but can run on an Intel-based Linux distro as an app. As time has gone on, it can be run as an app on many more operating systems (Windows, FreeBSD, Linux and limited on MacOS). This may sound strange: an OS running on top of another OS.
Basically, this is to take advantage of drivers (audio, internet, graphics, etc.) and compiler environments, in the existing OS, with which people may be already familiar. The term we use for what AROS does is "Hosted".
AROS Native is the term coined to describe AROS being run without any OS underneath it. It runs alone just like AmigaOS(TM) did. As this version does not benefit from "Hosted" drivers, dedicated ones have to be ported/written. Hence the smaller range of supported hardware / peripherals. We have other pages highlighting this support
AROS is open source so basically everyone can take part. The source is public on github and there are new commits most days. AROS is automatically compiled daily, result are the nightly builds hosted on Sourceforge. The nightly builds are only used for testing changes, testing software and the starting point for distribution maintainers or even your own distribution. They are very basic, miss some functionality and apps like web browsers and generic general appearance which can be changed.
* The [https://sourceforge.net/projects/aros/files/nightly2/ Nightly2], [http://aros.sourceforge.net/download.php nightly builds File Release Service] or [http://aros.sourceforge.net/downloads/ Sourceforge Project Web builds] are made automatically every night directly from the Github and in the past, SVN (Subversion) tree and contain the latest code for the AROS operating system. It should be noted that the builds have not been tested in any way and can be horribly broken but usually are not.
*ABIv1 standard for most nightly builds, it is where the most work is done by developers
*ABIv11 offspring aka fork of 64bit PC ABIv1 i.e. another PC 64bit build
*ABIv0 standard for PC 32bit intel / amd PC distributions for historic reasons
==Media==
AROS media tends to boot in this tier list of media types, first internal HDD SSD, CD DVD drive, and finally usb drive (last two can depend on bios boot order)
* USB .VHD
[https://sites.google.com/view/arosone Aros One x86 and x64], with md5 below
<pre>
0a656d53a9c902e9934000d8392e30ec *ArosOne-USB-1.3-64Bit.zip
7dd7119ab3e56d75ee852c137226b4d7 *ArosOne-USB-v1.2-x86_64-v11.zip
cf906eeaad4a83b3520b1896bdc6b0d3 *ArosOne-USB-v1.1-x86_64-v11.zip
e2eb8fe8cfd61c567b0152a61cf85251 *ArosOne-x86-v2.8-USB-IMG.zip
559909c75c2f56472c74267a7d075355 *ArosOne-x86-v2.7-USB-IMG.zip
93da5898508c1a8c05bb8991ab7bd117 *AROS One Image-USB-2.4.zip
59fcabd7090e47f12d54f7eb78cf0f45 *ArosOne-x86-v2.2-USB-Image.zip
24fb8de726ae8fc5fe5bac6d30f03dc5 ArosOne-x86-v2.0-USB-Image.zip
f3d725e990072edce633b59747911b6b ArosOne-x86-v1.8-USB-IMG.zip
e089a24ae310e92fcc407a0125602ce8 Aros-One x86-IMG-USB-v1.6.zip
</pre>
[https://tinyaros.flazio.com/ Tiny AROS]
22bc993625b7c75b17263c0cc7e7baaa *Tiny Aros_copy.vhd (March 2024)
There is usually a vhd image inside the zip that can be written to USB sticks which is so much faster than the old ISO written to physical CD DVD method. This .vhd can be written to an USB stick / ssd with these pieces of software below but it will erase the previous contents from the usb
Windows - [https://www.raspberrypi.com/software/ RPi Raspberry Imager, use custom and see all files], [https://hddguru.com/software/HDD-Raw-Copy-Tool/ HDD-Raw-Copy-Tool], [https://rufus.ie/ Rufus up to version 3.20 may work with VirtualBox HD vhd images with Win7 but not some Rufus 4.x versions], [https://etcher.balena.io/ Balena Etcher but may spy on you],
Linux - [https://www.raspberrypi.com/software/ Raspberry Imager Ubuntu], Suse Image / Multi writer, dd,
Mac -
* Virtual Machine .ISO or CDs DVDs
The native iso images are currently not compatible with Ventoy, Yumi, MultiBootUSB, Easy2Boot E2B, or similar
<pre>
617a905b1665128c5e05f94dcc48e7f1 *AROS-One-v1.3-64Bit-v11.zip
11c8a147fcad7ecf52ae3a43e1934b69 *ArosOne-DVD-v1.2-x86_64-v11.zip
f93053d3b9ccf304d7e6ac3389e1987b *ArosOne-DVD-v1.1-x86_64-v11.zip
86d808a40dc7be389a758799a9b4f595 *ArosOne-x86-v2.0-ISO-DVD.zip
f1fc8599ef6a39e5df394e0f41d55526 *AROS-One-x86-ISO-DVD-v1.6.zip
</pre>
You can use a virtual emulator like VirtualBox, VMWare to mount the iso image which can then be used to boot and/or install to USB.
No current software can write an AROS ISO to a Pendrive. The author of ‘Rufus’ (who used an Amiga 500 as a child) once tried, but when he saw the system composition, he said he was unable to do it.
The solution is to boot the ISO from a VM (WMware, VBox), then install the AROS build on the Pendrive, which will eventually become a Live Pendrive that can be booted on a PC.
The only precaution is that in some cases it is necessary to thoroughly clean the Pendrive of any partitions and remove any bootloader that is not AROS. The Pendrive must remain raw without any partitions.
You can clean the USB stick on a PC with a program that manages hard disks. You need to do a partition wipe. On some USB sticks, you can clean it with InstallAROS.
For some USB pendrives, please use a reputable partition editor to remove any and all partitions from a usb pendrive as HDToolbox cannot do this task sometimes with a wipe all option.
Previously the only installation option was CD-RW or DVD-RW, since the whole system can be burnt onto a single disk and can be reused when the next version is released. Good branded discs like Taiyo Yuden (later JVC) or Verbatim should be used to reduce frustration later. The days for this media is gone but kept here for information
Since nobody currently sells AROS on any other media, you will need access to a CD/DVD burner to create the installation disk yourself. After it is on a CD or DVD, then access and writing to USB pendrives becomes available (this should be viewed as an outdated or last resort alternative method now), as well as using good USB manufacturers like Sandisk, Kingston, etc. rather than some other no-names.
Try burning it to a CD-RW or DVD-RW using your CD/DVD burning program (most burning software have a burn iso option). The ideal writing speed is 2x or 4x, higher speeds can give errors and problems. Check the writing integrity of your CD or DVD if your software has an option to do so before going any further.
Standalone portable usb cd dvd drives do not boot physical burnt discs, please use an internal ide sata drive instead.
* SD-card
For [https://aros.sourceforge.io/nightly1.html ARM Pi Aros 64bit], copy the files onto a FAT32 formatted micro SD card.
==Booting==
The LiveUSB, and in the past LiveCD LiveDVD, is designed to trial (test drive) various operating systems without having to install them to your working system.
Since 2011, UEFI was introduced to replace the original PC BIOS which made booting media more confusing. Some changes in the UEFI/bios may be needed
*go into the bios using esc, f2 or f? and disable the Security -> Secure Boot and maybe apply option for Legacy IDE mode
*you may have to press F9, F10 or F12 or p on boot up to present a device boot options like USB or CD/DVD
*disable the Fast Boot config so it would recognize portable DVD-drive and changed the Boot-sequence
Secure boot was introduced by Microsoft and later consortium, control what operating systems work with Secure Boot via shims.
For Aros, it is best to disable and save the turn off change to Secure Boot (if you dual boot with Windows this will cause issues with further Window boots)
For the best experience, it is advised to install to another SSD than the one Windows resides on.
The grub part of the boot should be fully automatic, and you should see a multiple choice graphic card screen after 10 seconds for USB or 40 seconds CDs and DVDs.
If boot does not occur within a minute, please reboot and choose the VGA boot option as it relays a message stream so you can see where the issue lies.
After the grub graphics choice, AROS takes over the booting and any issues can arise here
If possible please use a branded usb pen drive as most of the time when we get reports of "crashes right after grub boot selection" it is mostly due to the recorded pendrive as they are made, notoriously on a will it work / will it fail nature, every time it is used.
<pre>
So one usb drive written may stop at a System halted. Reset the machine.
Or another pendrive will show give errors Smart Filesystem request - Volume 'Aros Live Drive' (DU0: usbscsi.device unit 0) There was an error while accessing this volume:
Or if a FAT32 partition present - FAT filesystem - Device USBSCSI0P1 has a read error on block xxxxxxxx -
</pre>
Sadly, no drive even branded are resistant or totally reliable, so the only solution is to try another pendrive, and possibly to repeat, until no errors.
It will give an indication on how reliable the usb drive could be.
=====Advice for various machines=====
Some of the stages involved and shown on the display in a typical AROS boot start up
<pre>
[MultiLoader]
[ELF Loader]
[Boot]
[HPET]
[Kernel:ACPI]
[Kernel:APIC-IA32]
[Kernel:SMP APIC]
[HiddStorage]
ACPI: ????
ACPI Error
[ACPI]AcpiOs????
[BattClock] Got RTC century offset 0x32 from ACPI
[PCI] Scanning bus ?
[AHCI] Sata
[Vesa] only if vesa is chosen as graphics option
[ATA] detect hd & cd drives
[ATA0?] ata-identity
[packet] fat.handler be.handler, etc.
[DOS]
[Storage:Bus]
[Storage:Controller]
[MSS] USB setup
[ehciInit] Port ? maps to controller ?
[I2C]
[ATI]
[drm] nouveau
[AROSTCP] if you have network driver prefs set up to start when booting
</pre>
; If boot fails, please give us some indication (pictures or videos) where the boot stops and the message(s) on screen.
AROS's native SATA/AHCI driver doesn't always work. If you get errors related to ahci.device, try disabling it. At your chosen boot entry in the GRUB menu, Press E, scroll down to the ahci.device entry, and add a # or ; at the start of that line or delete it with Ctrl-K. Then press Ctrl-X or F10 to boot.
If your disk isn't accessible at all with this change, you might need to change the SATA controller to IDE legacy mode in the BIOS: however, making this change will likely cause problems booting Windows on the same machine (if it's already installed). To disable ahci.device permanently, edit the text file "SYS:Arch/pc/grub/grub.cfg", and remove the ahci.device line from all boot entries you intend to use.
SATA AHCI Timeout while waiting for device to complete operations with BIOS SATA entry set to AHCI mode stops at "waiting for bootable media" screen, changing BIOS SATA setting back to IDE mode may allow it to continue booting
The ATA driver doesn't always work. If you get errors related to ata.device, try using the alternative in sys:devs/alt which is an older version. Press E when your chosen boot entry is highlighted in the GRUB menu, scroll down to the ata.device entry, and change it to read "module /Devs/Alt/ata.device". Then press Ctrl-X to boot. To make this change permanent, edit the text file "SYS:Arch/pc/grub/grub.cfg", and change the path to ata.device in all boot entries you intend to use.
Further options (removing the " ") to add to the GRUB menus to disable certain other components for debugging:
<pre>
Disable AHCI "AHCI=disable"
Disable NVME "NVME=disable"
Disable ATA: "ATA=disable"
Disable ATA: "ATA=nopci,nolegacy"
ATA safe mode: "ATA=nodma,32bit"
Disable IDE from SATA: "ATA=32bit,nosata2pata"
VIA / SIS with cdrom read io errors "ATA=nodma,nopoll"
noacpi all [PCI] devices to be invisible to AROS. disk drives work but network, sound won't
acpi=strict if there are issues with sound after boot
noioapic alternative to no acpi
Set AHCI "AHCI=force150/force300/force600"
Disable AHCI/SATA: comment out with a # ; or remove ahci.device line with Ctrl-K
Disable USB: comment out # ; or remove pciusb.device and poseidon.library lines with Ctrl-K
Disable native graphics: "nomonitors"
USB3 "USB=xhci"
</pre>
Other useful grub command line options - nomonitors, noacpi, vesahack, nopoll
Press Ctrl and X together (or F10) to exit and boot with the new options. Just experiment with different variations until successful. Those working options will need to be reused with every reboot of AROS until you can edit the grub.cfg and make it permanent i.e. install to hard disk or USB.
* If you use VESA mode, you can see the debug log if you add 'vesahack' to the command line. This will set up split-screen mode. In the upper half you'll see AROS screen, in the bottom - debug log.
* ACPI ie. PCI hardware - If you get crashes at early boot, try adding 'NOACPI' to the command line
If you're having boot issues and have a null modem cable and a spare pc, a boot log is always useful. Edit your grub line to include debug=serial but would try with an with sysdebug=all in the line later as it can cause issues booting on machines with sysdebug=all enabled (corrupts the cpu initialization).
However, if you feel you have found a genuine bug/fault in AROS that needs attention, please use the [http://sourceforge.net/tracker/?atid=439463&group_id=43586&func=browse bug submission form] to record as much information about what happened, why, and what hardware etc. you have so that people may try to assist you
For Virtual machines VMWare VirtualBox, etc., attach and press play to start the ISO image
If booting hasn't worked then it could be down to Bios/UEFI settings
=====nvme.device=====
Since 2018, nvme drives are standard on most machines
The requirement is that a PC can boot with legacy mode/BIOS at the moment - Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
This is still in testing and its' use should not be on or near precious own data
=====AHCI=====
Starting taking over since 2011 on a lot of machines
* Check that UEFI (replacement for PC BIOS) has options set to remove UEFI SecureBoot option and apply CSM
* SATA drive is set for Legacy or a mixture AHCI/IDE and not AHCI
AHCI sata can be very difficult to get working
Most Windows installs are already set to AHCI sata, changing this to a legacy IDE mode setting can help but please check if Windows will still boot. Some hardware like Lenovo laptops do not always like being set in legacy mode so only use as a last resort and aware of issues that can be caused.
Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
With a 16C/32T chip machine, disable SMT and it should boot.
=====ata.device for old BIOS's =====
Pre 2010 this was the de facto standard method of providing settings to the computer at a lower level
Some adjustments to the BIOS setup options are necessary (usually by pressing a key like DEL, F1, F2, F12 or ESC, p on the very early boot up of the computer).
*Adjust booting options like moving USB hdd, CDROM higher as it is quite often disabled or placed lower by default, i.e. USB hdd, CD/DVD are placed at the top above the hard drive. Try looking here [http://www.windowsreinstall.com/articles/bios/ Windows] or [http://www.hiren.info/pages/bios-boot-cdrom Bios] or [http://www.wikihow.com/Set-Bios-to-Boot-from-a-CD-ROM Boot] or web search "BIOS BOOT CDROM"
* At the '''SAME''' time, check if the SATA/AHCI option is set to Emulate or IDE Legacy, though this can have '''issues''' with any OS already on the hard disk. If in doubt, do nothing and seek advice.
* check that under BIOS settings you '''DO NOT''' have plug&play OS selected as Aros at this point is unable to route interrupts on its own and needs the BIOS to do that.
'''Save''' options changed at the end.
PCITool can show if the motherboard chipset is in IDE mode.
Class = 0x01 means STORAGE, Subclass = 0x01 means IDE. Also ProductID 0x3a20 resolves to non-AHCI mode in Intel ICH10 documentation.
==Installing==
We have a separate section [https://en.wikibooks.org/wiki/Aros/Platforms/x86_installing here]
We have a specific section for each CPU platform under the Specific platforms in the NavBar navigation bar on the right hand side menu
error code (-6) when using the ahci.device (has writing to disk problem but not reading) is enabled. change this line in your grub and reboot
<pre>
#module /Devs/ahci.device << disable
module /Devs/Alt/ata.device << add this line instead
</pre>
==File structure overview==
AROS' directory structure is mostly identical to AmigaOS directory structure, with some additions.
AROS: or SYS: also known as DH0: (i.e. the drive partition with AROS system) has the following simplified list of the main drawers (Amigas term for directories/folders).
{| class="wikitable"
|boot:
| grub bootloader
|----
|C:
| small apps, where AROS looks first for applications/games but will look at Tools, System afterwards
|----
|Classes:
| .class as well as datatypes
|----
|Devs:
| .device .resource and in their own drawers (folders) .audio, .hidd, network, graphics
|----
|L:
| where .handler files go
|----
|Libs:
| where .library files go
|----
|Locale:
| where help guide txt readme files go
|----
|Prefs:
| applications that adjust or setup AROS functions and capabilities
|----
|S:
| startup scripts (for the aros boot process '''not''' grub) are stored here
|----
|Storage:
| place to keep old or alternative device drivers
|----
|System:
| applications associated with AROS operating system
|----
|Tools:
| extra applications
|----
|Utilities:
| extra applications
|----
|WBStartup:
| copy applications here to autostart with needed icons, drawers, data etc
|----
|}
See [[Aros/User/DOS#Drives.2C_Files.2C_Assigns.2C_Directories|DOS manual: Drives, Files, Assigns, Directories]]
=== Filesystem ===
Whilst the kernel is the heart, the filesystem is the blood of the system they are split into two categories (only a few are supported)
<pre>
Journalling - SFS PFS3 but also NTFS ZFS XFS ext4
Non-journaling - FFS FAT32(VFAT) but also exFAT BtrFS ext2
</pre>
Filesystem options for AROS to install
* SFS default
* Professional File System PFS3 [http://eab.abime.net/showthread.php?t=52234&highlight=pfs3+free&page=13 only on motorola 68k at the moment] [https://github.com/aros-development-team/AROS/blob/e34170ea87da3b32935b60ed99d837b2b903a021/rom/filesys/pfs3/fs/mmakefile.src issues to compile]
* FFS very old now but left in for legacy usage
Other [https://archives.arosworld.org/index.php?function=browse&cat=driver/filesystem filesystems] for storage purposes
* FAT32 favorite as most OSs support
* NTFS (can lock AROS)
* exFAT
The only filesystems that really NEED defragging (i.e. disk tidy up) are from Microsoft(TM) - exFAT/VFAT/NTFS
*SFS tries to do exactly the same thing, but in certain cases it doesn't do as well as PFS. But you can defrag SFS
*PFS *minimises* the amount of fragmentation, but does not automatically defrags as it saves files to the drive
The setup of the below filesystems is usually done by the distro maintainer but if not....
<pre>
Copy L/exfat-handler L:
DOSDriver or Mountlist entry for an exFAT partition make sure that the FileSystem and Handler are set as follows:
FileSystem = exfat-handler
DosType = 0x46415458
</pre>
<pre>
Copy L/ntfs3g-handler L:
DOSDriver or Mountlist entry for an NTFS partition make sure that the FileSystem and Handler are set as follows:
FileSystem = ntfs3g-handler
DosType = 0x4e544653
Also to make a read-only mount you can set:
Control = ro
</pre>
The Smart File System (SFS) is a journaling filesystem used on Amiga computers and AmigaOS-derived operating systems. It is designed for performance, scalability and integrity, offering improvements over standard Amiga filesystems as well as some special or unique features.
SFS is written in C and was originally created and released as freeware in 1998 by John Hendrikx. After the original author left the Amiga scene in 2000, the source code to SFS was released and its development continued by Ralph Schmidt in MorphOS.
Its development has now forked; as well as the original Amiga version, there are now versions for MorphOS, AROS, AmigaOS 3, and a version for AmigaOS 4, which have different feature sets but remain compatible to each other. Versions for AROS, AmigaOS and MorphOS are based on different branches.
In addition, there is a driver for Linux to read Amiga SFS volumes, GRUB natively supports it and there are free drivers to use it from UEFI. The Linux version is [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ independent code].
SFS (Smart File System) partially defragments itself while the filesystem is in use. The defragmentation process is almost completely stateless
AROS SFS version has a 120GB partition size limit on hard disks and DVDs current 4gig size limit.
The sources for the MorphOS 64-bit version of SFS were available but no porting to AROS has happened so far due to endian issues, etc.
SFS Tools
* GUI - arSFSDoctor,
* CLI - sfscheck , [http://www.portacall.org/ sfsundelete], sfsformat, setcache hits a usability ceiling around the 10GB / 100,000 file mark,
sfscheck dh0: seek purge fraglist defragment
If there are two simultaneous file writes in progress and you reboot machine (or it locks up or crashes) you may end up with a corrupted filesystem. Although arSFSDoctor may help, you might have to copy the files to another partition, format the partition with the errors on and copy the files back.
PFS / SFS are way more advanced and much much faster than the FFS. FFS is supported for legacy reasons only.
The Professional File System (PFS) is a filesystem originally developed commercially for the Amiga and now distributed on Aminet with a 4-clause BSD license. It is a compatible successor of AmiFileSafe (AFS), with an emphasis on added reliability and speed compared to standard Amiga filesystems. It also features multi-user abilities like the older MuFS.
PFS has so many advantages including the important things, speed, the ability to recover all deleted files even simply same name by typing the command ". Deldir" convenient if done in Directory Opus, virtually deleted files are copied normally as if they had never been deleted, other convenience is to not ever invalidate the filesystem, just put it on top of the startup-sequence command "diskvalid", which automatically corrects any irregularities in the system startup; PFS also provides a device for floppy which makes them very fast and takes advantage of the full capacity of the floppy including the area dedicated to the bootloader.
The device is split into two main areas. At the beginning of the device is the metadata section, which consists of a root block, and a generic array of blocks that can be allocated to store metadata. The rest of the device is another contiguous generic array of blocks that can be allocated to store data. The metadata section usually uses a few percent of the device, depending on the size of the device.
The metadata is stored as a tree of single blocks in the metadata section. The entire directory structure is recorded in the metadata, so the data section purely contains data from files. The metadata describes the location of data in files with extents of blocks, which makes the metadata quite compact.
When a metadata update occurs, the system looks at the block containing the metadata to be changed, and copies it to a newly allocated block from the metadata section, with the change made, then it recursively changes the metadata in the block that points to that block in the same way. This way, eventually the root block needs to be changed, which causes the atomic metadata update.
The filesystem is reasonably good at keeping files unfragmented, although there is a defragmentation tool available which will work on an online filesystem ie whilst being used.
It was the first filesystem to introduce the concept of the Recycle Bin natively at filesystem-level to the Amiga, holding the last few deleted files in a hidden directory on the disk root.
PFS version 5.3 was developed in C and a small portion of assembly code by Michiel Pelt. There are endian issues to be overcome and adapting the small amount of m68k to C before use on intel based machines, etc.
Autoupdate of files in a directory is already implemented in Wanderer, but not all file systems handle dos.library/StartNotify() in its full extent. It seems to work correctly in Ram Disk (thanks to AmberRAM handler), and it also works on SFS formatted devices. Other file systems might not yet have it implemented correctly though.
The PC equivalent of the Amiga's RDB is the master boot record (MBR).
===Installing Applications===
The typical means to install applications under AROS/AmigaOS involves simply copying/extracting the archive (.zip .lha .rar .tar.gz) file containing the applications files to your own desired location i.e. drawer/folder. Once extracted, launching it by double clicking on an icon (recommended) or using the shell (alternative). Generally, this is on a separate partition from your AROS system files, however in reality it can be any location - including RAM: if you don't want it staying around too long especially when you switch off.
At some time in the future it may be desirable for AROS to have a package-manager like subsystem able to retrieve information online about packages available for AROS and whether they update anything you currently have installed, however at the moment no such ability exists.
===User Data files===
AmigaOS has no notion of a default location to store user data files, and presently neither does AROS - though it may be desirable at some time to provide a common start location.
Some people, have extra small FAT32 partition(s) using HDToolbox, and not Qparted, to store data especially if a reinstall is ever needed. And then setup the usual Sys: (DH0:) and maybe Work: (DH1:) / Live USB (DU0:) and maybe Briefcase (DU1:) partitions.
===User Environment configuration files===
AmigaOS/AROS stores persistent system configuration data in directory assigned to ENVARC:. This, by default, points to SYS:Prefs/EnvArc.
During boot a copy is made to another assign, ENV:, which is for runtime usage. Changes to the files here will not survive a reboot.
Setting the env variables is generally done by applications themselves, or when necessary by the user using the SetEnv command. SetEnv has a SAVE switch to force the persistent copy in ENVARC: to be written also for when you are sure the change should be permanent.
Under the standard installation of AmigaOS style OSs, ENVARC: is copied to ENV: upon startup, which, if you have a hard drive installation, is in RAM:, hence, ENV: ends up being RAM:Env.
ENVARC: is the Environment Archive, which is the permanent copy of ENV:, which is the Environment. It's roughly like the Registry in Windoze.
Most programs do (and all should) store their settings in ENVARC: somewhere, and load them from ENV:. The effect of this can be seen in the Preference editors. If you Save your preferences, they go in ENVARC: and ENV:. If you click Use, they only go in ENV:. If you reboot, normally, anything saved to ENV: is lost, and is replaced with a copy of what is in ENVARC:.
you can set the default public screen for any tool started from a cli with the PUBSCREEN variable. So open the pubscreen, set PUBSCREEN to the name and start newcli for example, then the new cli window (and all following windows opened from that window) will appear on that public screen.
===Drivers===
For certain hardware, e.g audio, networking and , there is no auto setup. Just like the original Amiga OS.
For audio, use AHI in the Prefs folder to set Music and at least Unit 0 with the appropriate driver and press Save. For ethernet and wifi, please use SYS:Prefs/Network
All hardware support is placed in the Devs drawer (folder/directory). The network drivers <something.device> go in the Networks sub-drawer. Audio drivers <something.audio> are put in the AHI sub-drawer. Graphics drivers <something.hidd> are put in the Drivers sub-drawer.
==Configuring==
AROS has mainly decided on a MUI-like requester&menu clone called Zune so changing the background, icons, font, menus can be done with SYS:Prefs/Zune
AROS has several desktop GUI front ends like
* DOpus5 Magellan II, Wanderer and Scalos (medium)
* AROS Workbench, Workbook (smaller)
File / Directory managers like Dopus4, MCAmiga,
App Launch Shortcuts like FKey, BoingIconBar, right mouse click on magellan, wanderer desktop, Amistart, etc.
General usability decisions - Prefs/IControl, Prefs/Locale, Prefs/Input, Prefs/Fonts,
Select an icon with left mouse button and then right click the mouse button and selecting Icon -> Information gains access to the tooltypes tab where information can be edited
CLI in icon's tooltypes means 'run it as if it was run from shell'
If, on the other hand, the WB parameter (or no parameter) is present in Tooltypes, Wanderer will execute the binary and, if provided, the options included in Tooltypes.
WBxCLI is very useful for adding options to DOS Commands.
Important: AROS has a different way of managing icons. If you have an executable file, you will never be able to add a project icon. AROS will automatically recognise that it is an executable file and will transform the icon into a tool icon.
Icons are typically now .png pictures renamed as .info e.g. so Office application name would have a Office.png renamed as Office.info or MyApp.png as MyApp.info, etc.
Leave Out menu option to leave app icon on desktop
To select multiple icons and save their positions, click on the first icon and after while you hold the Shift key down select further icons and don't release it before SnapShot is finished. You can also select a whole group of icons by pressing the LMB at the top left of the icons and while keeping the LMB down moving the power towards the bottom right. A expanding bounding box will appear and all the icons within it will be selected.
Clean Up menu option (right mouse button -> Icons) rearranges icons in a drawer or disk window into a neater condition. To use, open the window to rearrange and select Clean Up. To keep the icons in the new positions, select all the icons (shift key or mouse selection) and select 'Snapshot' and then Window and then again with All.
In DOpus5, Scalos, wanderer, most files have an icon file associated with it. To change the default tool, select Icon menu, Information, and change the default tool string. For example, you could use Multiview, Editor and so on for most text, graphics and some sound files as long as the appropriate Datatype classes are installed. For scripts, set the tool to C:IconX
We have new Icon edit tools in progress but if you need to...
C:Join Image1.png Image2.png TO MyFile.info
is enough to make a dual state icon from two png images. You can then use Wanderer's menu Icon/Information on it to edit its fields and tooltypes.
[https://archives.arosworld.org/index.php?function=browse&cat=graphics/icon AISS toolbar images] unpack unarc them into RAM: and copy Images directory to SYS:Prefs/Presets/ AISS icons are looked for in PROGDIR:, PROGDIR:Images, SYS:Prefs/Presets/Images and then in TBImages: according to Open Amiga guidelines.
there is Demos/iconscale which could be launched from S:User-Startup with two arguments, telling it the horizontal and vertical size. IE something like
Demos/iconscale 40 40
It will shrink icons... not sure if it will be very nice though. it doesn't work for the icons on the main desktop.
there is an option to scale an icon to a bounding box afair, try iconsize followed by two numbers, like:
iconsize 32 32
Is there any way in AROS to change an icon type from Project to Tool or vice versa?
Either the SIT option of [ ProcessIcon], or the TYPE option of HandleInfo (not sure if this one works at all, please test with care).
processicon sys:pathoftheicon SIT=Project
SIT Set type of ICON. Allowed types are: "Disk", "Drawer", "Tool", "Project", "Garbage", "Device", "Kick" and "AppIcon".
Btw, are your icons, the #?.info files, writable, is the W flag set ?
'''Decoration''' is Aros' way to provides a way to hide the old Workbench 3.1 style of windows and screens. In Prefs/Appearance some decorative theming elements need work
Themes - SYS:Prefs -> Appearance
The default content of Prefs/Env-Archive/SYS/themes.var should be "themes:ice" but can be changed via the Appearance prefs, please do NOT click the Use button. Its useless. As you know, it will ask for the theme volume. Just pick the theme you want, click on Save, then reboot.
* Decoration is on. Any time trying to change theme, you get: "Please insert volume Theme: in any drive"?
You could check if you find SYS:System/Themes or if it is missing. Then you could open startup-sequence which you can find in drawer "S". There should be a line:
Assign THEMES: SYS:SYSTEM/THEMES >Nil:
This does the trick.
Open a shell and run:
Assign THEMES: SYS:SYSTEM/THEMES
Than start the Theme prefs again... this should work
* The theme is the only thing that could slow the system a bit, but it's not that performance impacting on most uses, and you can switch it off completely. Remove C:Decoration from the bottom of the file sys:s/startup-sequence.
In each theme directory is
*Env-Archive -> Zune -> global.prefs
*images -> Gadgets -> 20x20 pngs for Down etc
*menu -AmigaKey - Background - Checkmark - SubMenu and config
*system - Arrowdown, Arrowleft, Arrowright, Arrowup, etc
There is an [https://archives.arosworld.org/index.php?function=browse&cat=graphics/theme ALua/Zulu script] built for faster Wanderer skin management. You can modify config files, install new (wdz format/zipped skin files) and delete skins via the Theme Manager. This has not been updated in a long time and may not work.
Certain features are added if from Tools/Commodities like Blanker screensaver, ClickToFront and DepthMenu with .info icons are selected and dragged to /WBStartup folder
Most apps can be autostarted by copying into SYS:WBStartup directory folder
e.g. WeatherBar.zip can be downloaded, unzip and the contents of the zip copied to wbstartup folder
ClicktoFront and .info to SYS:WBStartup so always be activated when turning on the computer
or add a text line to user-startup is SYS:S (scripts version of wbstartup)
e.g. standard Amiga / AROS does not allow clicking of background windows to come to the front to make it easy to get to the window you need but it has the ability if these apps are copied again to WBStartUp or are added to SYS:S/user-startup script
run QUIET sys:Tools/Commodities/ClickToFront >Nil:
run QUIET sys:Tools/Commodities/DepthMenu >Nil:
run QUIET sys:Tools/Commodities/Blanker seconds=300 >Nil:
Exchange controls Commodities and can be opened with alt, ctrl, h
*AltKeyQ uses left Alt key to add strange letters
*AutoPoint
*Blanker screensaver
*ClickToFront allows windows to be easily brought to the front
*DepthMenu adds menu to select window easily
*NoCapsKey
*Opaque
*FKey - Although there are heaps of docks, menus and other launcher programs on the Amiga like OSs, FKey has got to be one of the quickest once learnt ways to launch programs, and it comes with the OS. In SYS:Tools/Commodities, the FKey commodity (Ctrl Alt F) allows you to make actions assigned to some combinations of keys
<pre>
ALT TAB Cycle Windows
Cycle Screens
Enlarge Window
Shrink Window
Toggle Window Size
Insert Text
Run Program
Run Arexx Script
</pre>
e.g.
<pre>
LAmiga F1 = Avail Flush
LAmiga F2 = Open Prefs
LAmiga F3 = Finder
Alt Tab = Cycle Windows
LAmiga Tab or M = Cycle Screens
Alt Up arrow = Enlarge Window
Alt Down arrow = Shrink Window
Alt Home = Toggle Window Size
= Insert Text
LAmiga e = Run Program
= Run Arexx Script
</pre>
If your FKey GUI pops up when you start your Workbench up and you don't want it to, click once on the icon, go to the Icons-Information in the menu and make sure it has the tooltype set "CX_POPUP=NO".
Now let's launch it and assign the locale switching. After you double-click on FKey icon, launch the Exchange, choose the FKey from list and click the Show button. This will invoke the FKey window. You can see the ALT TAB in list assigned to window switching. Now enter the first key combination, say, ALT Z and go to the right panel. Choose Launch the program from pulldown menu and enter SYS:Prefs/Input as an argument. Append the USE switch and english preset name to the string as shown:
SYS:Prefs/Input USE SYS:Prefs/Presets/english
Click on the New Button to add the another combination. Now set the combination for your locale as shown above, replacing English name with your preset name. Click New button again and then Save Settings. Now you can use defined combinations to switch the layouts.
There is a system wide ARexx script capability (based on regina) that can manage many file manipulation task(s) but this would work only with those program that support [https://en.wikibooks.org/wiki/Aros/Developer/Docs/Rexx ARexx] like
*Desktop - DOpus5, Scalos
*Dock - FKey,
*Files - Multiview, DOpus4,
*Internet Apps - Odyssey, WookieChat,
*General Apps -
the shell can be modified with escape strings but not needed in most cases
Common Keyboard Shortcuts
<pre>
RAlt Right Alt Key
LAlt Left Alt Key
RWinKey Right Windows Key
LWinKey Left Windows Key
RAmiga Right Amiga Key (if one)
LAmiga Left Amiga Key (if one)
</pre>
;Bootup Options
:Spacebar during boot, enters the bootmenu which allows a boot without startup sequence, etc
;Left Click
:LAmiga = LWinKey = F11
;Right Click
:RAmiga = Help = F12
;Mark
:RAmiga and B
;Cut
:RAmiga and X
;Copy
:RAmiga and C
;Paste
:RAmiga and V
;Search
:RAmiga and S
;Mouse Movement
LAmiga and together with arrow keys - shift as well at the same time as well to move faster
;Mouse Selection
LAmiga and LAlt to select
;Screen Switching
LAmiga and M or N
;HELP key
Can sometimes be mapped to F11 but can be changed via FKey
ComKeyRemapper or AmigaKeyremapper could swap RAmiga to another key press
===DOpus 5 Directory Opus Magellan II===
Dopus 5.x is a whole desktop replacement on the Amiga Workbench (Desktop)
DirectoryOpus app will assign DOpus5: to it's PROGDIR: automatically but if not add the below (edit SYS:System to suit where Dopus5 was installed) to your startup-sequence
<pre>
Assign DOpus5: SYS:System/DOpus5
DOpus5:DirectoryOpus
;DOpus5:C/LoadDB
</pre>
Left mouse button clicked twice on the desktop background brings up the Device List window.
Green strip notifies SRCE (source) and if another is open it will be red for DEST (destination). clicking on the red strip changes to green
Word list of actions with a left mouse click on the DOWN Arrow and directory stuff with < button which mirrors the icons at the top of each lister
single-key hotkeys? exactly the same as in dopus4, edit your functions (button bank, toolbar, menus etc.) and under the flags gadget is a key gadget, just click in it and press the key you want to use.
As for the extra text field... try turning off Extended lister key selection in environment / miscellaneous.
Shift and click on the icon - runs the icon
DOpus5 Magellan 2 Directory folder drawer structure
<pre>
ARexx - Arexx scripts .rexx and .dopus5 to perform tasks
Buttons -
Commands -
Desktop -
Environment - two environment files bundled:
default gets loaded if you run DOpus as a normal app
workbench gets loaded if you run DOpus as a WB Replacement (with LoadDB on startup)
Filetypes -
Groups -
Icons -
Images -
Modules - compiled tasks
Settings -
Sounds -
Themes -
WBStartup - Use this if standard SYS:WBStartup gives cannot wait error messages
</pre>
Settings -> Environment -> Display -> Workbench (Use)
*Settings -> Clock (add to title bar as well as the date)
*Toolbar -> Editor (Right Win Key together with 1) for Copy, Move, Delete, etc above the Device List
*Menu -> (Right Win Key together with 2)
*Buttons -> Editor (Right Win Key together with 3)
*Settings -> Environment (Right Win key together with 4) for Backgrounds, etc
*File Types -> (Right Win key together with 5)
*User Menus -> (Right Win key together with 6)
*Hotkeys -> Setup for quick shortcut keypresses (Right Win Key together with 7)
*Scripts -> (Right Win key together with 8)
*Icon Positioning -> (Right Win key together with 9)
Each Dopus5 theme are stored in a separate directory, named appropriately, which contains further sub directories
* Font (amiga bitmap fonts)
* Screens (jpg or any picture supported by datatypes but not animations)
* Sounds (wav but not iff 8svx )
* Icons (png newicons glowicons )
* Patterns (iff jpg png )
Just use wildcards in background filenames and you get a different picture every reboot
For example, configure in Environment -> Backgrounds -> Desktop something like this:
<pre>
Work:Pictures/Backgrounds/#?
...or
Work:Pictures/back#?.iff
...etc...
</pre>
[https://aminet.net/util/dopus arcdir and themes]
If you want to change the backdrop pic after a period of time, paste below into a text file called dopusrandbg.rexx and place in DOPus5:ARexx
<pre>
/* Changes DOpus background image forever
Start with:
Run >NIL: RX dopusrandbg.rexx
*/
if ~show("L", "rexxsupport.library") then do
if ~addlib("rexxsupport.library", 0, -30,0) then exit 10
end
/* Configure these two lines for your needs: */
minutes=1
picpath="Work:Pics/#?.iff"
address DOPUS.1
do forever
call delay 3000*minutes
dopus set background '"'picpath'"' desktop center custom
dopus refresh background custom
end
</pre>
If you don't want to use/open rexxsupport.library just for DELAY() then use the DOS Wait command
<pre>
/* random diropus backdrop changer */
/* by paul trauth, 1999 */
/* to do: non-repeatable randomness? */
options results
parse arg path
address DOPUS.1
/* get current backdrop pattern so it actually changes */
dopus query background desktop custom
currentpatt=result
lastslash=lastpos('/',currentpatt)
currentpatt=substr(currentpatt,lastslash+1,(pos('"',currentpatt,2)-lastslash-1))
dir=showdir(path,'FILE','/')
num=0
do while dir~=''
where=pos('/',dir)
if where>0 then do
file=left(dir,where-1)
dir=right(dir,length(dir)-where)
end
else do
file=dir
dir=''
end
if left(file,1) ~='.' & file~=currentpatt then
do
pics.num=file
num=num+1
end
end
which=random(0,num-1,time(s))
newbg='"'||path||'/'||pics.which||'"'
dopus set background newbg desktop tile precision exact
dopus set background on
dopus refresh background
</pre>
Clock format commands available are defined by locale. They are:
<pre>
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
</pre>
like %a %d-%b-%y %H:%M or
A WB ARexx interface, you could enter a cli command as a menu item to open a WB drawer like this...
RX "address WORKBENCH;WINDOW 'device:drawer' OPEN"
Where device:drawer is replaced by the path of the drawer to open.
The ARexx script would be capable to manage such a task but this would work only with those program that support ARexx
<pre>
dopus addappicon
dopus addtrap
dopus back
dopus checkdesktop
dopus clear
dopus command
dopus desktoppopup
dopus error
dopus front
dopus getdesktop
dopus getfiletype
dopus getstring
dopus matchdesktop
dopus progress
dopus query background, font, palette, pens
dopus read
dopus refresh all, background, icons, lister
dopus remappicon
dopus remtrap
dopus request
dopus script
dopus screen
dopus send
dopus set background, font, palette, pens
dopus setappicon
dopus version
</pre>
<pre>
lister add
lister addstem
lister copy
lister clear value
lister clearcaches
lister close
lister empty
lister findcache
lister getstring
lister iconify
lister new
lister query active all, dest source
lister query abort, busy, case, dirs, display, entries, entry, files, flags, handler, header, hide
lister query label, lock, mode, namelength, numdirs, numentries, numfiles, numseldirs, numselfiles
lister query path, proc, position, seldirs, selentries, selfiles, separate, show, sort,
lister query title, toolbar, value, visible, window
lister read
lister refresh
lister reload
lister remove
lister request
lister set busy, case, dest, display, field, flags, handler, header, hide, label, lock, mode
lister set namelength, newprogress, off, path, position, progress, separate, show, sort, source
lister set title, toolbar, value, variable
lister select
lister wait
</pre>
The '''command''' allows you to call internal DOpus commands from an ARexx script
<pre>
command all
command wait copy
command read s:startup-sequence
command source 12345 makedir name noicon
</pre>
*SFTP secure encrypted comms over internet using libssh2 and zlib (different protocol to the two below) on port 22
*FTPS secured with https like security on port 21
*FTP not secure and unencrypted protocol over internet on port 21 (should not be used today on the internet but for your own server)
===Wanderer ===
Wanderer prefs in the prefs drawer - Appearance tab and Workbench icon allows backgrounds (wallpapers) icon text sizes, colors, etc but cannot use #? or *.* in the backgrounds file entry to randomly choose pictures - [https://developers.google.com/speed/webp/docs/riff_container webp riff container] issues with this format but Multiview has none.
Enable the bar, you need to edit the text file ‘statusbar.prefs’. The change is simple: just change “False” to ‘True’.
Prefs/Env-Archive/SYS/Wanderer/statusbar.prefs
===Scalos===
[https://web.archive.org/web/20180922220139/http://scalos.noname.fr/ Scalos] is not an OS replacement, it's a Workbench replacement. It replaces the desktop and graphical file management components.
Scalos is 100% Workbench replacement with most functions working like the original Workbench ones. Undo and Redo available for most window and icon operations. Fully multitasking so every window has its own task. While loading icons, any window function (e.g. Drag&Drop) is available.
24bit color support with window patterns - Unlimited and easily configurable via tooltypes. Optimised backgroundpatterns routine so patterns can be tiled, centred or even scaled to fit into the windows. Live updating window scrolling - Supports middle mouse button panning and drawer (folder) windows can be iconified on the desktop.
Icon imagetypes with all types are supported such as backfill or complement. Configurable surrounding iconborder. Icon support also visually highlights files which are soft-links in the file system. Icon dragging is more stable and far less flickery on graphics cards. Whilst dragging, icons are displayed with text and they can become transparent over anything where they can be dropped.
Single-window lasso mode, with scrolling window contents invoked by dragging mouse with configurable qualifier key. Text icon lasso selection used to ignore "Name column selects text icons" flag. Support for backfilled thumbnail icons, with selectable color and transparency. Added option to always generate square thumbnail icons with preview icons for images - Thumbnails can be permanently saved in icons.
Supports PNG icons with alpha channel and real transparency and displays OS3.5 GlowIcons and are all scalable. Iconborders with variations (normal, shadowed, outlined).
Completely configurable, filetype-specific user-definable popup menus and tooltips. Plugin system to exchange or add features and can enhance the Workbench and make it more configurable.
Filetype plugins to display filetype-specific information. - Currently, EXIF information viewer for JPEG images is included. Plugin included for 100% support of OS3.9 Workbench features. Plugin included for AREXX API compatible to OS3.9 Workbench.
Online update with updater.module
Scalos works also as a Workbench replacement. In this case the 'emulation mode' has to be set by using Scalos' own version of LoadWB and offers
* Scalos uses the Workbench Screen for its windows instead opening a new one
* AppIcon, AppMenuItem, AppWindow functions are redirected to Scalos
* all Programs placed in "WBStartup" should start
* The Screen will be reopened in case of changes in ScreenMode and Palette settings
<pre>
v1.0 (V39.201) - November 1999
v1.1 (V39.212) - December 1999
v1.2b (39.220) - June 6, 2000
v1.2d (39.222) - 2000 (latest public beta executable)
v1.3 (40.7) (beta) - August 2, 2001
v1.3 (40.22) - September 25, 2002
v1.4 (40.32) (beta) March 31, 2005
v1.6 (41.4) - March 27, 2007
v1.7 (41.5) - August 12, 2007
v1.8 (41.6) - March 12, 2009
v1.9 (41.7) (beta) - March 15, 2010
v1.9 (41.8) (RC1) - August 25, 2012 open source
v1.9.2 (41.10) Deadwoods' AROS late 2022 32bit and 64bit build unifying the code base of ` for AROS x86 ABIv0, AROS x86_64 ABIv11 and AROS m68k
</pre>
Distros may have Scalos files under SYS:System/Scalos or Extras:Scalos. Known [https://github.com/deadwood2/AROS/issues/75 bug list],
Certain files like Menu13.prefs, Palette13.prefs, Pattern.prefs and scalos.prefs need to be in SYS:Prefs/Env-Archive/Scalos they can be found in Scalos:Storage/envarc and country drawer
or run the "Scalos Menu" preferences program. Note if already setup with sub-menu entries and then re-save your menu prefs as it will now generate a new/overwrite prefs file called "Menu13.prefs" in "envarc:scalos/". The same is also required for the new Palette prefs update, click 'Save' and a "Palette13.prefs" file will be saved in to "envarc:scalos/" directory.
<pre>
ASSIGN Scalos: SYS:xxx/xxx DEFER
ASSIGN Libs: Scalos:Libs add
;ASSIGN SYS:Devs/Datatypes Scalos:Devs/Datatypes add
Assign Theme: Scalos:Themes/Default_Theme add
Assign Locale: Scalos:Locale add
Protect Scalos:Tools/browse.script s add quiet
Protect Scalos:Tools/OpenShell s add quiet
Protect Scalos:Tools/run.script s add quiet
run Scalos:Tools/LoadWB
;Scalos:Scalos
</pre>
Add the above to SYS:S/startup-sequence or SYS:S/user-startup '''before any Wanderer entries'''
In the prefs drawer (folder) is the big prefs app Scalos_Prefs which covers these user setup areas
<pre>
About Scalos
Paths - should be preset
Startup - WBStartup drawer contents should auto run on each startup
Desktop - edit titlebar, icon layout and in misc, auto leave-out (drag icon to desktop)
Icons -
Drag and Drop -
Windows -
Text Windows - in misc, drawer sorting at start of listing if needed
TrueType Fonts - use Truetype fonts rather than system ones
Miscellaneous -
Plugins - after adding oop/title_clock.plugin %ti %da does not work, maybe needs ASCII .prefs added
Modules - ??
Menu - setup for MainMenu and PopupsMenu with New Menu, RE Name, Key: shortcut, Command Properties
FileTypes - already added def_Project icons and def_Disk (hdd sdd cd dvd etc) support
PopupMenu - tweak how popups appear
Pattern - Wallpaper backgrounds with Type DE, each pattern in the list can be edited, Save as Pattern.pre
Palette - change the color of things , Save as Palette.pre
</pre>
Scalos_Prefs - Pattern - Minimum options to be changed are
*DE Desktop/Background
*SC Screen
*TW Window/TextBackground ie Text listing showing if icon type not recognised
*IW Window/Background ie Icons showing
Workflow - In "Pattern List" tab, select New - choose a picture, highlight in list, click in number box under New button and slide to another number, click on "Defaults" tab and adjust Pattern numbers slider to choose right picture for each of the above options - Click "Pattern List" tab to check eveything is OK and click Save
Pattern List tab on Patterns Page - Allows you to compile a list of pictures (one at a time rather than a whole folder e.g. with #? or *.*), assigning a number Nr to one or more of them for easy reference. Using this number you will be able to assign the pictures to specific windows on the Defaults tab Page. If multiple pictures have the same number, one of the pictures will be chosen randomly. This will allow you to have random desktop pictures, random window backdrops etc.
Defaults tab on Patterns Page - Here you can set the defaults for the background pictures for the Desktop, Screen, Window and/or Text Mode throughout Scalos.
Randomize every time [check box] - Usually Pictures with the same number will be randomly selected as soon as the configuration loads. If this option is set, the picture will be selected as soon as a window with the same number assignment is opened.
*Fit size: The picture will be resized to the dimension of the new window.You *MUST* have set GUIGfx on. asyncron layout: Pictures will be loaded and rendered while the windows opens (Like original Workbench). If this function is 'off', pictures will always be loaded before opening the windows.
*Use friendbitmap : The picture is present twice in memory for best speed. This option has no effect if V43 picture.datatype or GUIGfx are used. Always relayout: If "Fit size" is set, the picture will be scaled everytime the window's dimensions change.
*Randomize everytime: Usually Pictures with the same number will be randomly selected as soon as the If more pictures have the same number, one of them will be chosen randomly.
Patternlist New/Delete : Add a new picture. After that you should assign a number to it. The picture will be rendered as tiles. configuration loads. If this option is set, the picture
Asyncron-Task priority: You can set the CPU priority for the Task if "asyncron layout" is set.
<pre>
Desktop: Number of the Picture for the main window.
Screen: Number of the picture for the Scalos-Screen.
Window: Number of the picture for the Scalos-windows.
TextMode: Number of the picture for the Scalos-windows in Text Mode.
</pre>
Popup Menu preferences fully configurable menus (includes ToolsDaemon and ParM launch apps import), including support for context-sensitive Popup menus configs for top pull down menus for apps, etc.
Workflow - Scalos_Prefs then Menu, New Item, New Command add name at top then in Command Properties e.g. add Workbench and location e.g. DOpus:DOpus4 for apps Command for c apps or Rexx for scripts or Plugin for or AmigaDos for modules
<pre>
DESCRIPTION NAME/A This is the title that is displayed in the top line of any popup menu
INCLUDE NAME/A Name of file to be included. Path can be relative to "Scalos:FileTypes"
POPUPMENU Starts the popup menu description section for this filetype.
</pre>
The following Subcommands are allowed inside popup menus:
<pre>
SUBMENU "NAME/A"
ENDSUBMENU
MENUENTRY "NAME/A,KEY/K,DEFAULTACTION/S"
ENDMENUENTRY
INTERNALCMD "NAME/A"
WBCMD "NAME/A,STACK/K/N,WBARGS/S,PRI=PRIORITY/K/N"
AREXXCMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
CLICMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
ICONWINDOWCMD "NAME/A"
PLUGINCMD
MENUSEPARATOR
ENDPOPUPMENU
TOOLTIP
ENDTOOLTIP
</pre>
<pre>
Starts the tooltip description section for this filetype. The following Subcommands are allowed inside popup menus:
GROUP "ORIENTATION/K"
ENDGROUP
MEMBER "HIDE/K"
ENDMEMBER
HBAR
STRING "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K"
SPACE "SIZE/N/A"
DTIMAGE "FILENAME/A"
</pre>
Each theme drawer (folder) has these further folders
<pre>
About -
Desktop -
FileTrans -
FileType -
Icons -
Menu -
Modules -
PointerIcons -
Prefs -
Sound -
Window -
</pre>
*Plugins
<pre>
devicefilter.plugin
persist.plugin should a crash or reboot occur - next time Scalos started, all windows re-opened
title_clock.plugin add digital clock to title see more below
title_envvar.plugin %ev, which can be used to display the value (a string) of the variable in the titlebar
title_freepens.plugin
volumegauge.plugin
wb39.plugin
wbrexx.plugin plugin adds a Workbench 3.5+ compatible AREXX interface to Scalos internals
xtwindows.plugin left or right ALT or left or right SHIFT keys when open/close windows
filetype.plugin then run FileTypes-prefs and customize the filetypes (eg import from a DefIcons-brainfile)
menu.plugin
</pre>
*Modules - delete, empty_trashcan, execute, find, format_disk, information, iconproperties, newdrawer, reboot, rename, systeminfo, windowproperties
*Tools - scripts like LoadWB, quit.rexx, open_volume.rexx,
In Scalos_Prefs->Filetype->Recognition you can define the filetypes and on "Action" you define specific context menu for all filetypes defined in recognition (similar to magellan)
there is the same you must show all first (list is only limited) so you created a file type AAABBB, you need to have def_AAABBB icon
Associating files with "Scalos_FileTypes" is very simple, practically it is very similar to Dopus4, first you create the Def_icons to assign to the file type (will be seen automatically ), then run "Scalos_FileTypes" you add the extension, fill in the descriptor (MATCH or PATTERN etc..) and save
then you create an appropriate entry in the list and rename it, if def icon exists it is shown. Below you can define how files are identified. Use "pattern", similar to magellan to identify file by ending. Then you click on the shown icon and define in it what program is used when you double-klick on it and save it. On the tab action you can define popup menu for it.
defined all archive types from XAD in "filetypes". If you change to "action" and click on "archive" you can define the context menu that is shown if you do not define a specific context menu for a filetype
Reset to Default in Scalos_Prefs resets all settings so '''BEWARE'''
<pre>
The Scalos desktop screen titlebar may be configured using the main Scalos Preference program. This oop/time_clock plugin adds some additional placeholders:
%ti, displays the current time in the default Locale format. e.g. "10:43:37"
%da, displays the date in the default Locale format. e.g. "Saturday 14 July 2001"
Using the supplied prefs program for the plugin, or editing the ASCII file ENVARC:Scalos/title_clock.prefs you can use the following standard Amiga Locale values to change the formatting
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%C - same as "%a %b %e %T %Z %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%n - insert a linefeed
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%t - insert a tab character
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
like %d %m %y or %a %d %B %Y %p
</pre>
Shutdown -> right mouse button Scalos, About, Reboot, Shutdown
ToolTypes can be added to the Scalos.info icon like
*SCALOS_PATTERNNO=<number> : background image matching the number
*SCALOS_NOTEXT : The Icon will be drawn without Text.
*SCALOS_NODRAG : The Icon will not be draggable. Its position will be fixed.
*Module iconproperties - Added SCALOS_BROWSERMODE tooltype support
runcommand parameters... in which case:
<pre>
%p = parameters
%w = directory path
%d = device-name
%% = literal percentage token
</pre>
With the help of the wbrexx.plugin Scalos gains support for more of the compatible arexx API
If an arexx command produces an error you will find the error code placed in the WORKBENCH.LASTERROR variable.
ACTIVATEWINDOW
<pre>
/* Activate the root window */
ADDRESS workbench
ACTIVATEWINDOW root
/* Activate the "Work:" partition's window if already open*/
ACTIVATEWINDOW "Work:"
</pre>
CHANGEWINDOW
<pre>
/* Change the root window; move it to position 10,30. * and change its size to 200100 pixels */
ADDRESS workbench
CHANGEWINDOW root LEFTEDGE 10 TOPEDGE 30 WIDTH 200 HEIGHT 100
/* Change the currently active window */
CHANGEWINDOW active 20 40 200 100
</pre>
Most of Scalos' issue are due to the flexibility of its' user configuring nature but if
The sort menu plugin needs to be ported from ASM to C.
IIRC Scalos has a command line option to fully replace Workbench/Wanderer.
The Theme: assign is used by both Wanderer and Scalos but I didn't have any problems using both at the same time.
The Program will be started from the Shell.
If "WB Args" is set, with the Argument "%p" will be replaced by the path of the activated Icons. The Program will started with the specified Stack value.
IconWindow: Scalos opens the window of the specified path.
PlugIn: Starts a Scalos Menu-PlugIn.
If a Menu Item with empty name is specified, Scalos displays a separator line.
It's possible to Drag&Drop an Icon in the Configuration Window. All values will be set accordingly. Entries may be dragged across the list.
Mac-like selection : This function activates a multiselection method used on MacOS or Win95. Don't have to hold down shift to drag them. Clicking on an already activated icon will
not deselect all other icons.
MMB move: The window contents may be moved using the middle mouse button.
WindowPopup title only: PopupMenu for windows can be opened only on window's title bars.
FullBench: Screen-Titles removed and Main Window set Full Size.
Scalos Prefs. Go to Settings->Scalos->Prefs and then the Misc section. Remove the tick against Full Bench. If you've enabled it, the titlebar will disappear when you select backdrop.
Default Icons saveable : The icons which Scalos generates if "show all files" is enabled, can now be saved
using "snapshot" menu option. load DefDisk first : Try to read the icons first from the DefIcons Path before using disk info.
Hide hidden files : If this function is activated all files or directories where the "hide" flag is set will not be shown.
Many of my Icons display more than once on the screen, while on the workbench all seems ok.
The Workbench filters double displayed icons, Scalos does not. Solution: please edit the ".backdrop" file and clear double lines.
Background images not scaled. GUIGfx option not set or guigfx.library and/or render.library not installed.
If working with CD's causes crashs or Scalos doesn't work correctly.
Most Filesystems doesn't support the ExAll function correctly. Disable "Use ExAll" in Scalos prefs.
Scalos doesn't start any program in the WBStartup. WBStartup Path may be set wrongly or Scalos was not started in Emulation Mode (LoadWB etc)
Some programs will not startup with error message "has not returned, wait some more"? and "unable to open your tool"
need a def_icon with the same name predefined, then create an appropriate entry in the list and rename it, if def icon exists it is shown. Below this can define how files are identified.
* either "pattern", similar to magellan to identify file by ending
* or
Then click on the shown icon and define in it what program is used when you double-click on it and save it. On the tab action you can define popup menu for it. All in all handling is of course different to magellan but can do similar
For the RAM Icon, to obtain this you have only to copy the icon in the Icon Path as "RAM.info" or "Ram Disk.info". All functions will automatically be performed
sometimes cut into half or quarters when scrolled off screen or drawers moved - settings issue probably
Sometimes leaves initial drawer window imprint on desktop when moved - settings issue
Scalos AROS released a [https://github.com/deadwood2/contrib/tree/master/scalos new build V2022-07-21] with the following changes noted:
<pre>
Fixed:
Numerous crashes when working on 64-bit with 64-bit heap
Wrong background color of Scalos logo on Scalos splash window
Backgroung image of Scalos splash window and Scalos About window is not visible
Icon labels on desktop and in drawer windows are displayed using Topaz instead of Arial font
Font.prefs are not being loaded on 64-bit
Font.prefs are being wrongly saved on 64-bit
scalos.prefs are not being loaded on x86 and x86_64, scalos is using always default preference
scalos.prefs are being saved on x86 and x86_64 in format not compatible with m68k
NewPopupmenu.prefs is wrongly written
Plugins are not loading at Scalos startup
wbrexx.plugin is crashing at startup on 64-bit
Multiple controls missing on Scalos Prefs/Icons page
System crash when clicking on def icon image on FileTypes Prefs/Recognition page
Status bar, control bar, buttons sometimes don't have images displayed
Buttons in Scalos About window have white corners rendered where they should be transparent
Crash when leaving out an icon
Crash when adding a User-defined Button to Control bar without setting it's properties in Scalos Prefs
Crash when removing any button from Control bar in Scalos Prefs
Scalos Prefs allows editing TTEngine font properties when TTEngine is not present causing crash in Icons/Labels and Text Windows/Fonts pages
deficons.prefs are not being loaded on x86 and x86_64
Reset to default in FileType Prefs and Save does not save preferences
Won't fix:
Scrollbars visible on titles of TrueType Fonts, PopupMenu, Menu, FileTypes, Pallette and Pattern pages of Scalos Preferences
Not fixed:
Wrong rendering on DualPNG icons
Refreshing drawer windows is slow
Starting Prefs/Locale or Prefs/Input from Scalos causes other preferences to fail
Desktop wallpaper is damaged where Splay window was displayed
When started from Wanderer, after saving Scalos Prefs, reload does not re-open main Scalos window
Difference in behavior between Cleanup from popup menu and Cleanup from top menu - possibly due to missing plugin, check Cleanup association in Menu Prefs
</pre>
===DOpus 4 Directory Opus===
Copy DOpus4 app to WBStartup directory folder so it starts on boot up each time
Another method is add the below to the bottom of the user-startup script in SYS:S drawer/directory
<pre>
run DOPUS:DirectoryOpus -i >NIL
</pre>
makes DOpus starts up in Iconified state at the top of Wanderer's screen. Left click on this to highlight and right mouse click to open.
Just click on the sides of either outer edges of DOpus windows and it will display the parent device/volume list.
DOpus4 saves it features in a PROGDIR:s/DirectoryOpus.CFG file which can be edited to suit anyones' needs, '''C''' bottom right button in DOpus4 and by reading the [https://arosarchives.os4depot.net/index.php?function=browse&cat=utility/filetool Dopus4 guide Manual and Arexx calls].
*[https://www.youtube.com/watch?v=DCyXDs8baSE Pt1 Introduction]
*[https://www.youtube.com/watch?v=7fiVmopiK9I Pt2 Dopus Config]
*[]
*[]
*Button little rectangle with name inside
*Bank vertical stack of buttons
Buttons
*Workbench app {f} i.e. first use {F} for all selected items with app
*AmigaDos c type apps with arguments after
*Arexx
*Command c type apps with no arguments after
Flags (most used)
*CD Destination to extract etc
*Do all files
*Output window
*Run asynchronously
*Workbench to front
*Buffer above 100000 for 64bit
Filetypes
Defines how certain files are handled like '''default tool'''
Screen
Fonts, set each element to any font
Screenmode, Workbench Use (same screen like Windows), Workbench clone (like Linux workspaces)
System
Shell startup, set to SYS:s/shell-startup
===BoingIconBar===
User chooses the apps to add to the dock at the centre bottom of the screen but has to be done manually, please use Save afterwards
Or easier edit the text file of SYS:Prefs/Env-Archive/iconbar.prefs and save
<pre>
BOING_PREFS
;Tools
SYS:System/Shell
SYS:Tools/DOpus4/DOpus4
SYS:Utilities/Editor
SYS:System/SysMon
SYS:System/Scout
Work:Extras/Internet/OWB/OWB
Work:Extras/Graphics/Lunapaint
Work:Extras/Graphics/ZunePaint
AROS:Tools/MPlayer/MPlayer
Extras:Internet/AmiFox/AmiFox
RAM Disk:Amelinium/Amelinium
</pre>
right mouse click on bottom edge of screen where boingiconbar shows - select settings which opens BoingIconBar Preferences to add apps
If no dock showing Add, to add apps click Add Program and search for the executable
another method is to drag icons to ends of the bar and move them on the Bar using the Prefs/BoingIconBar
===AmiStart===
On 32bit PCs only - auto generates the apps menu but scans the drive each time - AmiStart can choose apps you are not interested
* how to disable annoying zune/mui 'bubbles'?
try a right-click on AmiStart and release on Global settings. Then click on the bubbles gadget. Move the Show Bubbles slider all the way to the left.
===Fonts===
Install the #?.ttf files to SYS:Fonts/TrueType. Use SYS:System/FTManager to "Install Font" each #?.ttf file which will generate associated #?.otag and #?.font in SYS:Fonts. Use SYS:Prefs/Fonts to change system fonts and SYS:Prefs/Zune to change others.
To achieve our goal we will use the Setup Locale, Input, Zune and Fonts, as well as The FTManager.
Begin
The first step you should do is to get the system to know that we speak and write in another language. What you need to do is to open the setup program and choose Locale country, and list "preferred languages" to put it first and then English. If you want the tab "Time Zone" and select city of residence to set the clock correctly. Of course we save our changes and continue opening the setup program Input. This sets the keyboard language as our beginning. When the language layout was created there was no option to switch to Aros keyboard (layout switching), so to write in the language you had to hold down Alt, something you encounter in other functions. This time working with the team of Aros to create a new keyboard layout to replace the old so we can get rid of the button Alt. For now though let only selected this layout and do not turn the switch on the keyboard.
Custom Keyboard Layout
[http://repo.or.cz/w/AROS.git/tree/HEAD:/workbench/devs/keymaps keymaps are in place but unfortunately when they are not, then indeed things become a bit 'low-level' as it involves redefining some tables with values that match your keyboards]
only need to add your compiled table as new keymap.
So taking a little peek here shows that it should be possible to compile using
gcc -opc105_tr pc_105.c -nostdlib
where the pc105_gr/pc_105.c needs to be replaced with your own adjusted keymapname/c-file
[https://en.wikiversity.org/wiki/Enabling_Greek_Characters_on_Your_Keyboard General overview of Greek letters on keyboards]
Installing fonts
*[http://aminet.net/package/util/wb/EPAGrWb System jaggy]
*Outline resizable .font .otag
In this step you need to download some fonts that can support the encoding in our system. The easiest way is to run the script "Download Fonts" you'll find in the folder OWB. This script downloads from the Internet, and unpacks some fonts for OWB web browser, which is placed under the folder Fonts:TrueType. But as these can only be used by OWB and not the system, which unfortunately does not see. To make them available to the rest of the system, open the program FTManager, you will find the folder AROS: System /. From there select the field "Codepage" option "ISO-8859-7" and list the font "Arial" and "Regular" form in which you must double-click with the mouse. In the window that appears, select the bottom right the checkbox "Anti-aliasing" button and then "Install". Immediately folder Fonts: created files "arialregular.font" and "arialregular.otag", which are necessary in order to see the system font. Do the same steps if you wish for other fonts.
Final stages
After completing the above, open the folder AROS: Prefs / and run the program settings Fonts. In the new window, select the fields "Icons" and "Screen" as the font "ArialRegular" to the size you want. In the field "System" to give "s_courier", which, however, because it is not True Type Font support Antialising, and may seem a little broken. You can also use the CourierNew, if you have installed the above procedure. After you save the changes and open the Zune program settings. In this set the "ArialRegular" font fields in tabs "Windows" and "Groups", and save the changes. Reboot the system. To make sure that the above worked properly run NoWinED, which you will find under the folder AROS: Tools /. If that everything is working correctly you will see the menu and the settings window with Greek letters. You can also write in the language using the button Alt. Second program that you can try, which is fully localized, is WookieChat, which you will find in the folder AROS: Extras / Networking. And in this place all the menu and settings window works.
===Windows===
*Intuition
The window you position and resize, you right click on that windows title bar and in the dropdown menu you snapshot from there. Right click to show menu -> Window -> Snapshot Windows or All but it will NOT work if that folder has no icon (e.g. Disk.nfo) attached to it. You need a folder icon. The window information gets saved in it.
As for maximising the window using a shortcut key - Alt and up arrow key
The AROS-Shell windows can be moved, resized by editing sys:s/startup-sequence
<pre>
; run shell
run QUIET c:newshell >NIL:
</pre>
; slimmer right aros the screen
run QUIET c:newshell con:0/150//300/ >NIL:
; top right corner scr-x scr-y win-x win-y
run QUIET c:newshell con:600/150//300/ >NIL:
*EdgeSnap
Commodity EdgeSnap allows resize and position windows on your screen by dragging them to the edges but not corners of the screen and/or other windows
EdgeSnap Prefs (once pressed Use button) lets you arrange windows but not different applications in layouts half (left or right) or full size (top) and choose to adjust the border padding
There is outline to show shape taken to aid placement and space available
*Zune - AROS version of MUI
Magic Menu type functionality is implemented in IControl preferences editor: in the frame called Menus, switch type from Pull-Down to Pop-Up and/or iControl just tick the sticky menu option.
Windows outside screens causing a problem either uncheck "Offscreen move" for windows in IControl prefs editor. Or use FKey commodity and define two key shortcuts:
* the first using the command "cycle windows" (for example ALT TAB);
* the second using the command "rescue window" (for example ALT F5).
Now you can cycle windows until the one you want to rescue, and then "rescue" it: it will move back inside your screen.
How to save the window size on wanderer (snapshot all, snapshot windows)
Same for icon position on wanderer, can't save the position. Icon position cannot be saved yet, but you should be able to save the window position and size. sys:prefs - wanderer icon has option to save window size on exit but just for dh0. To get saving working on (DH1: Extras:) partitions try deleting the dh1 disk.info file, then reboot. The system should create a new dh1 icon.
* how to set up permanently 'view all files'?
As for viewing all files, removing disk.info for that disk did the job
* how to list and kill processes (xkill would be useful) ?
sys:Extras/System/Scout can kill apps
sys:Tools/Commodities/Exchange can remove available commodities
* how to restore 'go up' button in wanderer window? (it doesn't show up anymore).
If you're using Icaros, go to the theme prefs and make sure that decoration is checked. Also, some themes do not use a parent button, so try another theme. You may have to restart Aros before the theme will change.
* Is it really safe to turn off (hardware button) computer at any time (worried about USB hard disk)
yes you can turn off the computer IF none of the drives are in progress (i.e. writing). Best to use Wanderer menu option Quit otherwise
===Say narrator===
Say "Hello World" for a simple robotic voice
SPEAK: is a write-only DOS device for text-to-speech abbreviated as tts.
To check if available, type assign into the shell and at the bottom in the Devices: section should be SPEAK
Examples of use
<pre>
Copy S:Startup-Sequence SPEAK:
Echo "Hello" >SPEAK:M/R/S150/P110
Echo "DH1 EH0 L OW1" >SPEAK:A1
</pre>
Classic options are M/F, R/N, S<rate>, P<pitch>, O0/O1, A0/A1, and D0/D1. O1 recognizes lines beginning with OPT/ as option changes. A1 treats input as narrator phonemes.
Long options select a speech engine:
Echo "Hello" >SPEAK:ENGINE=narrator/VOICE=female/STYLE=natural/LANGUAGE=en-US
Supported selectors are ENGINE=, VOICE=, STYLE=, and LANGUAGE=. Values are case-sensitive backend identifiers. ENGINE=DEFAULT selects the system default. Narrator-compatible selectors continue through the classic translator/narrator pair. Other engines use speech.device. Direct phonemes require a narrator-compatible selection.
===Printing===
This needs further [http://www.aminet.net/package/docs/help/PrinterGuide drivers written], we have postscript and write to file support only
;There are no individual drivers yet for HP's Photosmart, EPSON's EPL, CANON's, Lexmark, CUPS PPD, etc.
*Postscript
Best to set Printer Prefs in the Prefs drawer to print-to-file or parallel/USB port
Save document in postscript or convert picture/text to postscript
Print using compatible Postscript printer
*printer is simply not accepting IPP connections at the moment.
Please try the following steps:
Open the printer web interface in a browser:
http://192.168.1.x/
Look for the network or protocol settings.
Enable IPP / Internet Printing Protocol.
Make sure TCP port 631 is open/enabled.
Save the settings and reboot the printer if the web interface asks for it.
ipp://192.168.1.xx:631/ipp/print
ipp://192.168.1.xxx:631/ipp/
===Files===
====File endings and datatypes====
* Check if the file has his own .info icon file with a tool set to open it. IIRC this has higher priority over the def_XYZ.info file association.
* In ENVARC:SYS/def_Text.info or whatever def_ file needs changing, use Wanderer's menu Icon -> Information and change the def_XYZ.info there. If you're on ABIv0 and want it to be applied immediately, you might have to copy it to ENV:SYS/ (or to reboot).
* Identifying file types by file ending is only a fallback. Far better it is to search for magic words, for flac files this would be "flaC" according to this [http://flac.sourceforge.net/documentation_format_overview.html documentation].
For instance, to open PDFs with arospdf not localised in the default drawer of Icaros (Work:Extras/Applications/arospdf) but localised in a custom drawer in AROS. The default tools are defined in the icons in sys:prefs/env-archive/sys e.g. def_PDF.
File type identification is done by datatype descriptors which you can find in Devs/Datatypes. The AROS build system has a tool which creates such datatype descriptors.
'''Changing of default tools of existing icons is easy as shown above. Adding of new file types is not hard, but needs knowledge of the AROS build system.'''
The enduser way would be to download the attached file, which contained two executables:
1) createdtdesc, to make a new datatype description
2) examinedtdesc, to read/show existing datatype descriptions
use 2 to get an idea on how it things are currently done in aros by providing this executable a file from the drawer sys:devs/datatypes/ (alternatively you can find the original .dtd files here).
use 1 to make your new datatype. Use the accompanied FORMAT file (also here) to read how to make your own datatype descriptor. use 2 to get hints from other datatype descriptors.
Note:
When creating a new descriptor would advise against using the pattern property, but instead use the default pattern of #? and create a Mask that matches your filetype. This requires some research in order to discover how your filetype can be recognized properly. Of course with making something like a descriptor for an ascii textfile, you would fallback to using the pattern (e.g. #?.text as the filetype cannot be determined easily otherwise).
<pre >
# name - choose wisely and informative. also used for icon's name.
# version - choose as you like as long as it complies with version rules
# basename - the 'root' datatype class. be aware that e.g. it can influence behaviour. for example when choosing binary and using tool multiview in project icon, the file will be viewed as binary file (choosing sound would tell mulitview to view the file as a soundfile). So this can influence the underlying tool being used. Could become messy if users started to modify the tool manually.
# pattern - This is the file pattern match e.g. #?.text
# Mask - A mask to identify the file. Requires knowledge of the actual file structure. For example 'M' 'Z' for an msdos executable.
# GroupdID - not supported (AROS native) files - use syst as that would be the least intrusive in case an AROS tool/program tries to load such datatyped file.
# ID - In your case, the first four characters of the name at subchapter 1 (in lower case) (or less if name is shorter).
# flags - How the mask needs to be interpreted. In your case would be mostly DTF_BINARY in combination with (wanted or not) DTF_CASE (to tell if mask used letters are case sensitive or not)
# priority - the priority of how the type is handled so that on datatype could have precedence over another? In any case, document tells it to be mostly 0.
</pre >
Now that you know each field and what it does (more or less), you write this fields in a text file for your own invented datatype, save it and create the actual dt with the tool in 1. in the end the created dt must reside in sys:devs/datatypes/ drawer.
Then you would create a default icon in sys:prefs/Env-archive/SYS drawer. Don't forget to reboot or copy .info file to ram:env/sys in order to test. also don't forget to set which tool to start f.e. c:lx or dh4:emulators/mycoolemulator
To test, open Wanderer then show all files and doubleclick on a file of type you just created. Alternatively you could use the 'open' command from shell (with file of datatype you just created as parameter).
And as a last note. it would perhaps be welcome to have a program like xicon and/or runprglist for AROS (unfortunately both without source, but something similar could be created for AROS).
Sounds complicated ?
Perhaps... but OS like windows needs a complete registry to be able to do things like this. And yes, i am aware windows has gui tools that does it (more or less) for you (by manipulating the registry). Same could be done for AROS (without integrating a registry in AROS that is ).
Would that suffice ?
red1+2: typos, reformatting.
disclaimer: please note that using these tools can screw up your currently installed support for datatypes when used incorrectly. Do not use if you do not understand what you are doing. Use at own risk.
==Network Connection==
AROS currently only has one real choice for TCP/IP networking - AROSTCP. This is a port of the AmiTCP package from AmigaOS (TM), with a number of enhancements/fixes from AROS developers.
===Wired===
Use Network Prefs to setup
=====IPv6=====
Some support
128bit IPv6 address packet
<pre>
Local FD::/8
Global 2000::/3
64:ff9b::/96
</pre>
NAT64 translates IPv6 to IPv4
DNS64
OS routing works with
<pre>
MacOS Ventura
Windows 11 with cloud account
Ubuntu Jammy Jellyfish
Android 10 (block google dns)
</pre>
====IPv4====
The top half of the IPv4 Configuration tab on the Network Prefs deals with the network card/USB and the lower half the router part.
[[File:AROS Wanderer Network Prefs DHCP.png|thumb|DHCP Settings]]
'''Upper part of IPv4 tab'''
* Click Add on the top right of the Prefs which opens a window called '''Interface'''
* Enter Name as net0 (but can be anything as long as it is consistently used in other sections)
* check mark on Active
* select device to be used using the '''right hand-side gadget''' of the box where the device name will go
* set Unit to 0
* IP Mode is default set to '''Get address from DHCP'''
* IP Mode set to Manual if DHCP does not work automatically
From the shell CLI, ifconfig -a
Under net0: section, inet starting 192.168.x.xxx
* inet or '''Address''' of network card
* netmask convert to decimal so 0x'''ffffff7f''' becomes 255.255.255.247 which is used to adjust the above '''Address''' into
* broadcast 192.168.xxx.xxx
click OK
[[File:AROS Wanderer Network Prefs Manual.png|thumb|Manual Settings]]
'''Lower part of IPv4 tab'''
* IP Mode Get address from DHCP (default)
* or changing to Manual if automatic DHCP set up does not work
* '''Gateway''' (Router Internal LAN-IP) (Default Route) = 192.168.0.1 (D-Link Netgear), 192.168.1.1 (Linksys 3com), 192.168.2.1 (SMC Microsoft), 192.168.1.254 (Belkin), 192.168.123.254 (USRobotics) else check with your router manual
* first DNS = use 208.67.222.222 (opendns) or Gateway number above (to test web browser access to router) or 212.50.160.100 (google) i.e. or whatever your ISP needs you to set
* second DNS = use 208.67.220.220 (opendns) or Gateway number above (to test web browser access to router) or 213.249.130.100 (google) i.e. or whatever your ISP needs you to set
* At the bottom of IPv4 tab, check mark the '''Start networking during system boot''' option
* Save and reboot (sometimes Network restart fails, so reboot every time to be sure)
'''an alternative way''' to AROS ifconfig -a, other OSs have similar for the same internet connection. Another connection will have different settings.
e.g. From [http://www.ncsu.edu/resnet/windows/ipconfig/ Windows], '''ipconfig /all'''
and note down the IP, subnet mask, default gateway, and DNS servers values and put these values in "manually" into AROS Network prefs.
e.g. From Linux via dhcp router have a look at etc./dhcpc/dhcpcd-eth0.info
* for manual input look at /etc/networks (IP or Gateway) and /etc/resolv.conf (DNS)
Please note that all in one routers (wired+wireless) or separate routers may need different settings
IPv4 involves routing (192,168.x.x), firewall, NAT
===Wireless===
You may have a Wifi Prefs to use for wireless setup
[[File:MyArosWirelessSetup.png|thumb|Setting up]]
[[File:MyArosWirelessTCP.png|thumb|Shell commands to work out what is happening]]
We must first make certain you have a Atheros 5k chip inside acting as the wireless wifi option. Open PCITool in Tools directory. Down left hand side are a series of numbers 0.00.0 etc. Click on some at the bottom and hopefully one of them will say Atheros AR5??? or AR242?.
or a Realtek RTL8187B, we can check using Prefs/Trident as this one is USB based
There are many similarities with the above Wired set up so please read the above section as well
* open Network/Prefs
* In '''IPv4 Configuration''' tab - click Add - enter net0 / active tick / #?.device / Unit 0 / IP Mode = manual (important if default DHCP does not work automatically)
Make sure that any extra network names (e.g. eth1 or net1) should be deleted. If net0 already st previously, change net0 so that it shows associated with the appropriate device name like atheros5000.device or realtek8180.device. Having two entries here will cause sub-net problems.
* Go to '''Wireless''' tab and click on "Add" button.
* Insert network name (SSID your wireless network name use wirelessmanager to get it), select right "encyption" that is most likely "WPA".
* Key Type set as "Passphrase". i.e. type in your password for your router (aka access key).
* Unselect (no tick) "hidden" if it is selected, then apply. You may have to tick it if wireless does not work.
* Finally, Save and '''reboot'''.
For the best chance of success, set networking to start at boot, and then reboot with the USB adapter plugged in.
===USB Ethernet===
Open SYS:Prefs/Network and in the IPv4 Configuration tag (top table covers your usb stick)
* click Add button
* set Name as net0
* Tick Active box
* enter the usb-ethernet.device e.g. dm9601eth.device, usbpegasus.device or usbasixeth.device use SYS:c/devlist, '''Scout''' or trident prefs to get the correct spelling
* set Unit to 0 (which is usual but check the messages from the bottom of the Trident prefs whilst plugging the device in to determine the unit number otherwise)
* IP Mode is set to Get address from DHCP (make sure your router is set right for that)
'''or manual'''
* IP Address of network card, i.e. 192.168.0.xx or 192.168.1.xx (xx being greater than 1)
* Subnet netmask = 255.255.255.0
* click OK
There can be sometimes be boot failures when using USB ethernet - plug the USB device in after boot and save the network prefs to make it work again.
Lower part of IPv4 tab covers the router information
* IP Mode Get address from DHCP
'''or if manual settings'''
* Gateway (IP Address of router) = usually 192.168.0.1 or 192.168.1.1 but see router manual to make sure.
* first DNS = use 8.8.8.8, 208.67.222.222 (opendns) or 212.50.160.100
* second DNS = use 8.8.4.4, 208.67.220.220 (opendns) or 213.249.130.100
===USB Tethering via Android smartphone===
Go to AROS Network Prefs (IPv4 configuration tab) and write type in "usbrndis.device" in the "device" textfield of "Interface" sub-window, which appears when you add a new device (or modify an existing one). Select "Start Network during system boot" and saved the configuration, the Connection is immediate no reboot is needed.<br>
usbrndis.device is a resident device (virtually always there) in fact, a driver is not present in DEVS:Networks <br><br>
Plug in USB cable, go to Android settings and enable "USB Tethering" <br>
A reboot should not be necessary.
When restarting AROS, the Smartphone deactivates the connection and to access the network again have to reactivate it before starting the browser.
===Solving Issues===
[[File:MyArosTCP.png|thumb|Aros network setup diagnostics - why does it not work?]]
* In Network Preferences, have '''only one''' item in the IPv4 Configuration tab
* If using manual settings, make sure all numbers are correct, especially for IP address of the card/usb (changing the last number in chain of four)
* For any USB based networking, it is often necessary to save in Prefs/Network, reboot AROS and network support can begin
* For wired, make sure that the LAN-cable is plugged in before starting the computer
* If wireless, try getting closer to the router.
* Switch off the encryption option from your router then try wifi, if successful then your ip/dns is ok. If not then your ip/dns settings are most probably wrong or need to use one or more opendns numbers
* Replace detachable wireless antenna (best wireless option to buy if you can) with a stronger antenna ie. 5 dBi or 7 dBi
* Try with another computer/laptop/machine
Program Error C:WirelessManager
* Test with another OS
* Check that Wifi works before changeover (if possible)
* Check that socket and card are working
* Check if card is too new for laptop (date code on card MMYY blue askey date 2005-2007 etc)
Are you connecting with the Router ?
Check with protection off e.g. wps and wep to see if it makes a difference.
For USB wireless - stopping and starting may be needed...
<pre>
; $VER: AROSTCP-startnet 1.0 (01/08/06)
; AROSTCP-startnet (c) The AROS Dev Team.
;
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
; stop and restart
execute "sys:system/network/AROSTCP/s/stopnet"
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
run <NIL: >NIL: wirelessmanager realtek8180.device
</pre>
What IRQ number is assigned to the device? You can check with Tools/PCITool?
It's possible the BIOS hasn't set the right IRQ number. If you have a Linux CD/DVD handy, could you check if it boots with the options "acpi=off noapic nolapic"?
If the following does nothing, this will help us figure out why networking doesn't start automatically at boot
open a shell and run the following commands:
<pre>
echo ${AROSTCP/AutoRun}
echo ${AROSTCP/WirelessAutoRun}
echo ${AROSTCP/WirelessDevice}
</pre>
Please report the output, typically it will look like this
# True (explanation this variable is related to the "Start networking during system boot" checkbox in network prefs)
# True ()
# Devs:networks/atheros5000.device unit 0
If there's a problem with the AROSTCP package. What's the output of this?
ENV:sys/packages/AROSTCP
should return a string = Sys:System/Network/AROSTCP
By the way, a quicker way to check networking is working would be to run some shell commands such as:
<pre>
ping www.google.com
ifconfig net0
</pre>
The best way to list the available networks and diagnose / troubleshoot problems with connecting to a wireless network is to run WirelessManager manually. First uncheck the "Start networking during system boot" box in the Network prefs app, then save and reboot. Then run this in a shell:
C:wirelessmanager atheros5000.device verbose
or
C:wirelessmanager realtek8180.device verbose
and capture the output
If the above does not help, could you edit the file SYS:System/Network/AROSTCP/S/Package-Startup, and change ">NIL:" to ">T:wifi.log" on the WirelessManager line and add this as well Wait 5?
<pre>
if ${AROSTCP/WirelessAutoRun} eq "True"
Run QUIET "C:WirelessManager ${AROSTCP/WirelessDevice} >T:wifi.log"
wait 5
EndIf
</pre>
Then save, reboot and post the log file (T:wifi.log) here.
<pre>
c:wirelessmanager atheros5000.device verbose
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7)
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
Then it just sits there. Not sure what a normal dump looks like, I don't see anything that looks wrong in the configuration.
</pre>
looks like the driver isn't working with that card. Has anyone else successfully used that exact model number (AR2413)?
<pre>
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7):
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
*** [wpa_sm_init] sm->pmksa=02c66fd4 ***
Own MAC address: 00:01:36:15:ae:0c
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
Added interface atheros5000.device:0
State: DISCONNECTED -> SCANNING
Started AP scan for wildcard SSID
MLME: starting scan
MLME: scan channel 1 (2412 MHz)
sana2: sending MLME frame
Then it stops. Does this mean the router is not authorizing this NIC?
IRQ 4 (A)
</pre>
apparently locking up when the first frame is sent (a scan request).
<pre>
Devs/Networks/atheros5000.device:0
Initializing interface 'Devs/Networks/atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=12):
41 69 72 4c 69 6e 6b 35 39 33 30 30 AirLink59300
PSK (ASCII passphrase) - hexdump_ascii(len=8): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='AirLink59300'
*** [wpa_sm_init] sm->pmksa=0224e444 ***
Own MAC address: 00:1f:e1:42:e3:7a
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
[eloop_reg_timeout] Timeout is at 1317686594.160000
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
[eloop_reg_timeout] Timeout is at 1317686595.060000
[eloop_reg_timeout] Timeout is at 1317686604.060000
Added interface Devs/Networks/atheros5000.device:0
[eloop_run] Starting
State: DISCONNECTED -> SCANNING
Starting AP scan for wildcard SSID
MLME: starting scan
[eloop_reg_timeout] Timeout is at 1317686594.160001
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.233000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.373000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.513000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.553000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.693000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.013000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.073000
EAPOL: disable timer tick
EAPOL: Supplicant port status: Unauthorized
MLME: scan channel 14 (2484 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.113000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.153000
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.213000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.353000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.493000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.533000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.673000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.993000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686596.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686596.073000
MLME: scan completed
</pre>
Is your network hidden? If so, did you enable the 'Hidden' checkbox in the network prefs? What distro version are you using?
<pre>
"ENV:sys/wireless.prefs" looks like this:
network={
ssid="testadhoc"
key_mgmt=NONE
wep_key0="12345"
wep_tx_keyidx=0
}
</pre>
If your router doesn't broadcast its SSID (hidden), you need to add this option to the network block of the wpa_supplicant.conf on your aros machine and make changes after # Example blocks:
scan_ssid=1
Here's a full description of all the [http://hostap.epitest.fi/gitweb/gitweb.cgi?p=hostap.git;a=blob_plain;f=wpa_supplicant/wpa_supplicant.conf config file options].
<pre>
ap_scan=1
network={
ssid="YOURESSID"
scan_ssid=1
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP
group=CCMP
psk=YOURPASSWORD
}
</pre>
<pre>
filter_ssids=1
ap_scan=2
network={
ssid="REMOVED"
scan_ssid=1
bssid=REMOVED
priority=100
mode=0
proto=RSN
key_mgmt=WPA-PSK
auth_alg=OPEN
pairwise=CCMP
group=CCMP
psk=REMOVED
}
</pre>
Error 6: Couldn't resolve host name.
Check Scout -> Devices and look at the device that you are using, in the OCnt column it should state 2 which means AROSTCP and Wirelessmanager are both accessing this driver. If 0 or 1, then uncheck the checkbox in Network prefs for starting networking at boot, save and reboot. Then run this is the shell:
C:WirelessManager realtek8180.device unit 0
some quirks setting up the wireless network as well
1) it's far better setting up either the wired OR the wireless network adapter as net0:, or weird things happen
2) it's better using fixed IP on the local network instead of DHCP
3) network setting must be placed in network setting panel in /prefs, using the wirelessmanager helped me finding available SSIDs, but not actually connecting to them
once done, reboot.
If previous setup is proving problematic
<pre >
SYS:Prefs/Env-Archive/Wireless.prefs
SYS:Prefs/Env-Archive/Zune/OWB.config
SYS:Prefs/Env-Archive/Zune/global.config
SYS:Prefs/Env-Archive/AROSTCP/WirelessDevice
SYS:Prefs/Env-Archive/AROSTCP/db/Interfaces
</pre >
Make a copy of these files and restore in case of problems.
Please try this test to check if you can connect to your router, ie established that the WiFi layer is working
̊̊̊̊Boot with networking disabled, by make sure that "Start networking at boot" in Network Prefs is unchecked (no tick).
̊ Run this in a shell: C:WirelessManager atheros5000.device VERBOSE
̊If the output of that command is too long to summarise here, you can redirect it to a file by adding >RAM:wifi.log to the end, then attach or paste that file here.
try running "status" in the shell and check that AROSTCP is listed/running
If AROStcp is not showing, then AROSTCP is not running. attempted to start it by clicking Use or Save in network prefs, or checking the "start networking at boot" box or typing into a shell.
Execute SYS:System/Network/AROSTCP/s/startnet
(run Status again afterwards).
The "cannot resolve hostname" will appear if you are blocked on the wifi network by the router as well as aros not being able to assign correct network address.
One way of testing this might be to disable the firewall in the router. you might also check the router how it sees the attempts aros do to speak to it. The easiest way to do that would be to manually give aros an IP number in the routers accepted range. and see if it shows up at all within the router.
Tests that can be undertaken to determine correct settings and functions
pciinfo
sanautil -d broadcom4400.device status
<pre >
ping <router-address> e.g. 192.168.0.1 (aka inet) or 80.237.146.33 (www.amiganews.de)
ifconfig net0
ifconfig net0 up
extras:networking/utils/sanautil/sanautil -d atheros5000.device status
WirelessManager atheros5000.device verbose >RAM:wifi.log
;to send the log to RAM disk to be read easier or if detected,
Run WirelessManager atheros5000.device >NIL:
Run WirelessManager atheros5000.device ssid="mynet1" >NIL:
C:WirelessManager realtek8180.device unit 0
</pre >
Please look at the task list in Scout, and check if WirelessManager and AROSTCP are running. Also look at the device list in Scout to check if realtek8180.device is open.
start tools/debug/sashimi, maybe it shows some debug messages when disconnection happens.
Firstly, let's take a look at what your setup most likely looks like, assuming you use a router. See diagram below:
<pre>
Internet <---------> home router <---------> computer
-----------external IP------------------internal IP-------------
</pre>
Okay, so what am I trying to show you with that diagram. A few things. Firstly, the IP address that connects you to the Internet is not the same one that connects you to your router. What happens is that your computer doesn't have a direct connection to the Internet, instead your router connects to the Internet, and your computer connects to the router.
You can see the external and internal IP addresses in these example settings...
* Default Gateway : 76.91.64.1 (external IP for ISP/Internet host)
* IP Address : 76.91.71.184 (external IP for home router)
* IP Address : 192.168.0.1 (internal IP for home router)
* Address = 192.168.0.161 (internal IP for computer)
As you can see, there are two internal IP addresses and two external IP addresses. This is because there is a client/server relationship, effectively one address is for the service (server) and one address is for the device trying to access that service (client).
The server addresses in your case are 76.91.64.1 (your ISP's address, serving the Internet), and 192.168.0.1 (your home router's address, serving your home network). The term gateway applies here, they are your gateway to those services.
Subnet masks are used along with IP addresses to determine which IP addresses are allowed access to a network. I did learn the more in-depth rules about subnet masks once (watched a CCNA vid), but I've forgotten about it. The basic level of understanding you'll need is easy to remember though. A subnet mask value of 255 means that portion of the IP address must stay constant, whereas a subnet value of 0 means any unassigned value up to 255 is allowed in the IP address.
By far the most common subnet value is 255.255.255.0. What this means is that the first three parts of the IP address you use to connect to a service must stay the same as the server/gateway address, and only the last section can change.
So if your router's internal IP address is 192.168.0.1, and the subnet mask is 255.255.255.0, the only addresses that will be allowed to be used on that network are between 192.168.0.2 and 192.168.0.255 (I think 192.168.0.0 is reserved for other uses).
Final point to make is about DHCP (a.k.a. dynamic IP) vs static IP. A server/router using DHCP gives a device that connects to it an address within the acceptable range. It usually starts with the lowest numbered free address, so with your router it'll give the first device that connects to it 192.168.0.2, the next device 192.168.0.3, and so on. Static IP addresses are where you set the IP address you want to connect with in advance.
When using static IP addresses on a router where DHCP is active, it's good to use a high number to avoid conflicts with other devices that are connected to your network, to reduce the risk that both devices will try using the same IP. That's why your current choice of 192.168.0.161 is good, unless you have over 159 devices connected on your current network!
Okay, so what's the next step. Well, if you can use ping, I'd suggest pinging 192.168.0.1. If you get a positive response it means you're connected to your router, if you don't get a response it means the connection between your router and your computer is at fault.
Documentation on configuring the AROSTCP environment further can be found [http://en.wikibooks.org/wiki/Aros/User/Networking here]
===File Sharing===
As AROS knows only a few filesystems (FFS, OFS, SFS, PFS (amiga only), FAT12, 16, 32, Microsoft NTFS (windows), UDF (Blu-ray)).
The others in regular use like MacOSX hfs+, Linux ext2/ext3 and ext4, Haiku BeFS provide a problem in transferring files.
Linux can access SFS partitions but it needs to be compiled. The latest full source are [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ here]. It compiled fine with a 2.6.30 kernel in Puppy Linux 4.31.
An alternative, is to use a FAT32 partition to share. Setup a 4G FAT32 partition using HDToolbox for sharing, and the rest of the space as SFS for an Aros install. It works very well.
Files could be transferred via TCP internet network.
====SMB2/3====
With Windows you can share one folder or all folders of the "Public" user.
On Windows what is important is to enable sharing (Network and Sharing Center).
AROS Mountlist should look lke this
<pre>
Handler = L:smb2-handler
StackSize = 65536
Priority = 5
GlobVec = -1
ACTIVATE=1
Startup = "smb://UserAcc:password@PCShare/Sharefolder"
</pre>
which could also be
"smb://UserPC:password@192.168.x.x/Public"
or
"smb://UserPC:password@Name-PC/Public"
so
"smb://UserPC:password@192.168.1.158/Folder"
or
"smb://UserPC:password@Name-PC/Folder"
After you have configured a share generates a DOSDrivers it is named "SMB0" which includes the setting, and at each reboot it is Mounted. You can still delete the DOSDriver by hand, is located in Storage/DOSDrivers, the file "ServerAutoMounts", in ENV:AROSTCP which indicates the DOSDriver to be mounted, should also be deleted.
The per-mount files are written to ENV:SMB or SYS:Storage/DOSDrivers. There is also additional file ENV:AROSTCP/ServerAutoMounts which states what will be presented to the end user.
====Old SMBFS====
e.g. to connect to a NAS share such as \\NASBOX\Shared use -:
SMBFS WORKGROUP=<YOUR WORKGROUP NAME> VOLUME=<AROS volume name to use>: SERVICE=<UNC Path to connect to>
SMBFS WORKGROUP=MYNET VOLUME=Shared: SERVICE=//NASBOX/Shared
And you will then have an icon appear on your desktop for the volume name you have chosen.
You can put the above script into wbstartup or
give it an icon, change it to a 'project' and give it the default tool c:iconx
Open a shell and type copy sys:script.info "sys:wbstartup/YOURSCRIPTNAME.info"
This should create an icon for your script file.
Now right-click on your script and select 'information'.
Change 'tool' to 'project', put 'c:iconx' into the 'default tool' box, click save
The reason being that scripts need to be opened with 'execute SCRIPTNAME' (or 'iconx') whereas the programs started from wbstartup are opened using 'run PROGRAMNAME'. It's the same as trying to start a command-line tool from the workbench by double-clicking it.
====Setup ISO images within AROS====
Use [http://archives.aros-exec.org/index.php?function=browse&cat=driver/storage DiskImage] which supports many cd image formats ISO, CCD, MDF/MDS, CUE/BIN, NRG and UIF. To mount CD or DVD images use below....
<pre >
# Rename your iso 'Unit0' (note no extension).
# Do 'View/All files' on you Aros partition. You should now see a folder called 'Diskimages'. Copy your renamed iso to there.
(Alternatively, you could type at the shell 'assign FDSK: xxx', where xxx is the location of your iso.)
# From the shell, type 'mount CD0:' and the iso should appear on the Wanderer desktop. You can now access it like a real disk.
</pre >
assign devname: dismount
Assign DOSVOLUME: remove
[http://aminet.net/package/disk/misc/unmount-0.1 unmount] most filesystems work but SFS lacks support for ACTION_DIE packet
If you are using an IcAros install, the startup scripts are set up to wipe the Diskimages directory on boot, so its worth keeping a second copy of the iso somewhere else. Alternatively, you could set up extra mountlists for additional iso images. I've made a file called iso1 in the Aros:devs directory that contains the following text:
<pre>
/* Entry for ISO image */
ISO1:
FileSystem = cdrom.handler
Device = fdsk.device
Unit = 1
LowCyl = 0
HighCyl = 0
Surfaces = 1
BlocksPerTrack = 1
DOSType = 0x41434400
Activate = 1
#
</pre>
Then I just need an iso called 'Unit1' (corresponding to the 'Unit = 1' entry in the mountlist) in Diskimages (or wherever I assign FDSK: to) and to mount I type in at the shell:
Mount iso1: from devs:iso1
Of course, if you create mountlists for ISO2, ISO3:, etc. (with the corresponding change to the 'Unit = ' line) you can have as many isos mounted as you wish. I just call mine ISO1: etc. to distinguish them from the real CD drives
==Video Guides==
Video demonstrations and tutorials covering:
:00. '''Introduction'''
::[https://www.youtube.com/@jamesmattson6813/videos Various Aros Installs],
::[https://www.youtube.com/embed/j8EmSEby0Rg AROS repo in gource, view of AROS dev commits from 1997 to 2025], [http://www.youtube.com/watch?v=Vx_zqlBow40&feature=related Gource view of AROS 1997 up to 2009],
::[http://www.youtube.com/watch?v=s1RsvEm7UrU Why an Amiga OS in 2011],
::[https://www.youtube.com/watch?v=1W886mheV74&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Johan Grip on early days of AROS x86], [https://www.youtube.com/watch?v=mXaKDhtTTqQ&t=14s&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Michel Schulz on Aros and PiStorm],
:01. '''Installation'''
::[https://www.youtube.com/watch?v=M7YjufrJqDs Aros One install], [https://www.youtube.com/watch?v=iIMguHTdC5E Aros One USB install], [https://www.youtube.com/watch?v=ZNXauy5m5Wc Aros One install], [http://vimeo.com/11013489 Modify Grub boot],
::[http://www.youtube.com/watch?v=wyQVeyXIywc&feature=channel iMica Silent Pt3], [http://www.youtube.com/watch?v=o2AnkoflY14 Wipe whole drive and Install - warning loss of data on drive],
::[http://www.youtube.com/watch?v=OVXm6_-witQ VirtualBox install], [ VMware install],
::[http://www.youtube.com/watch?v=0k2PEmT8I14 Broadway AROS Install],
::[https://www.youtube.com/watch?v=PtDiXhjSIfs Is Aros Icaros a choice?],
::[ driver install],
::[http://www.vimeo.com/10491104 HDAudio install but needs account], [],
:02. '''Amiga Basics'''
::[http://www.youtube.com/watch?v=TY8mWxwzH5o Screens tutorial],
::[https://m.youtube.com/user/AMIGASYSTEM/videos General], [ Dos Scripts tutorial], [http://www.youtube.com/watch?v=hPT7SmVEpjc OS 1.2], [http://www.youtube.com/watch?v=n6kX3FqH8Ww&feature=related OS 1.3],
:03. '''Customisation demos'''
::[https://www.youtube.com/@AMIGASYSTEM/videos Prefs tutorial], [ Decoration tutorial], [http://www.youtube.com/watch?v=Dn5C8G3aDXU Scalos],
:04. '''Setting up''' internet access and surfing the web, FTP, IRC and Mail apps
::[ Network Prefs], [ AirCOS tutorial], [ jabberwocky tutorial],
:05. '''Native bundled Games and Applications'''
::[http://www.youtube.com/watch?v=aYlFv2B-VXc 3D Games], [http://www.youtube.com/watch?v=MXK7wwhd-R0 Latest Games], [http://www.youtube.com/watch?v=RUgiVThv23Q&feature=mfu_in_order&list=UL PrBoom GL], [http://www.youtube.com/watch?v=0s7u8TPy7V4 Assault Cubes], [http://www.youtube.com/watch?v=fih6aCXKeqs Cube 2], [http://www.youtube.com/watch?v=-X0ay0MGOms DosBox on Aros], [http://www.youtube.com/watch?v=7nKduDjf14k Oct 2010],
::[http://www.youtube.com/watch?v=FziV2z_uxnQ Apps Pt 1], [http://www.youtube.com/watch?v=xs37_nfa5CI Apps Pt 2], [http://www.youtube.com/watch?v=Bn59_VvbQR0&feature=related Apps Pt 3],
::DOpus4 [http://www.youtube.com/watch?v=aSRybWjrrME DOpus 4],
::Milkytracker [http://www.youtube.com/watch?v=VxBOEPzpdKg&feature=related Laying Down Base Tracks],
::[http://www.youtube.com/watch?v=k2uKQ0-ieOE Audio Evolution 4 in action], [http://www.youtube.com/watch?v=Zq4r9k0_jZI Quick Videos],
::[http://www.youtube.com/watch?v=gGKCFZcIc0I&feature=related ScreenRecorder], [http://www.youtube.com/watch?v=974c2e-Fqak&feature=related TV out Tests],
::[http://www.youtube.com/watch?v=fjq8ct5d5IY AmiFIG], [http://www.youtube.com/watch?v=h0rHvPhYJo4&feature=youtu.be ZuneFIG],
::[http://wiki.povray.org/content/Documentation:Tutorial_Section_1 POVray Tutorial 1],
::[http://www.youtube.com/watch?v=Jk-ZNLfJsvQ pt 1, jan. 2008], [http://www.youtube.com/watch?v=nWRy33g1R7Y pt 2, feb. 2009], [http://www.youtube.com/watch?v=r5PbhCtm4vE pt 3, feb. 2010],
::[https://www.youtube.com/watch?v=G7_FJUoQ89o Hollywood programming], [], [], [],
::[], [], [],
::[], [], [],
::[], [], [],
:06. '''Commercial software available'''
::[http://www.youtube.com/watch?v=fKXY9B4R43s AntiryadGX 3D Game Editor],
::[http://www.youtube.com/watch?v=TMS9NDzwm5U BOH indie Game],
:07. '''Running classic amiga apps and games'''
:: Amiberry [], [],
::[http://vmwaros.blogspot.com/2008/11/introducing-amibridge.html Intro Amibridge], [http://www.youtube.com/watch?v=ee2PWvCZeLo Old Amiga Apps], [http://www.youtube.com/watch?v=ee2PWvCZeLo Why Janus UAE is good],
::[https://www.youtube.com/watch?v=VhlsNSYSuDg DPaint tutorial]
::[http://vmwaros.blogspot.com/2009/11/can-icaros-play-my-amiga-games-and-why.html Play Amiga Games], [https://www.youtube.com/watch?v=XTaZCNOvCnE],
::[http://www.youtube.com/watch?v=tMehS77LXQ4 Pagestream Introduction], [http://www.youtube.com/watch?v=284-w3hTzII Pagestream Tutorial 1], [http://www.youtube.com/watch?v=mlwEGwhZzl4 Pagestream Tutorial 2],
::[http://www.youtube.com/watch?v=iIcrIjPOctc Catweasel Mk4 PCI Part 1] and [http://www.youtube.com/watch?v=BaitHeL6bEA Part 2],
:08. '''Misc and History'''
::[http://www.youtube.com/watch?v=d6mDXKU29w0 Mum uses old AmigaOS Workbench 1.1 (1986)], [http://www.youtube.com/watch?v=DaRkacQ-YMg Why an Amiga 500 (1987)], [http://www.youtube.com/watch?v=k5CYsgVCzYY an Amiga 2000 (1987)],
:09. '''Misc Shows and Events'''
::[http://www.youtube.com/watch?v=klgVSWKs4kE VCF 2010], [https://www.youtube.com/watch?v=eQ3d5qR-Hv8 24:06 Jason McMullan at amiwest 2012 about AROS], [https://www.youtube.com/watch?v=jpQO7XSfAv4 Aros SMP multi core amiwest 2013], [], [https://www.youtube.com/watch?v=gFRtAAmiFbE], [https://www.youtube.com/watch?v=DjdUEyjx8GM], [https://www.youtube.com/watch?v=ydYDqZQpim8], [], [https://www.youtube.com/@uminekoshouten/featured], [https://www.youtube.com/shorts/NfoY023w-vE],
:10.
::[https://www.youtube.com/shorts/6qJTNW4-6GY]
===History===
The project was originally started by a small group of Amiga [http://www.amigahistory.co.uk/aros.html enthusiasts] in 1995. These individuals were mainly computer-based college university students at the start, though that student trend has diminished since. An interview with Aaron Digulla [http://arosshow.blogspot.com/2006/12/interview-with-aaron-digulla-who.html here]
* 1992 Commodore folds
* 1996-1998 much of the early years was concerned with exec, dos and intuition libraries.
* Early 1999, Haage & Partner used parts of the AROS code in AmigaOS 3.9.
* March 2001, floppy disk images of AROS became available.
* Early 2002, AROS changed its name from Amiga Replacement Operating System to Amiga Research Operating System
* June 2002, AROS devs decided to use Zune (MUI 3.8 rewrite) as the GUI system.
* November 2002, Eric Schwartz drew Kitty for AROS usage.
* Early 2003, AROS.org underwent a graphics facelift.
* Late 2003, GCC C compiler arrived.
* Early 2004, Aros-Exec opened.
* Early 2005, Aros Max bootable CD arrived.
* Late 2005, SFS filesystem ported and allowed fast access to apps and network support arrived
* Early 2007, AROS.org underwent another graphics facelift.
* Mid-2007, AROS changed to AROS Research Operating System after A.Inc. sued Hyperion with a trademark violation.
* Late 2007, the hard disk installer added and VmwAROS (later called Icaros Desktop) distro launched.
* Early 2009, Our first usable web browser (OWB)
* September 2010, first wireless support appears and AspireOS started as a distro
* Early 2012, the first paper-cut bugfix and Fab's Odyssey Web Browser ported
* Early 2017, work started on utilising the addition cores on modern CPUs starting with the 64bit x86 PC version
* Mid-2017, m68k port optimized for the Vampire 2 / Apollo accelerators (68080 AMMX FPGA)
* 2018 The old AROS Exec website closed and a new one opened
* 2019 AROS One x86 32bit distribution started and now with USB install version
* Early 2021, backport of more features of 32bit PC ABIv1 into 32bit PC ABIv0 (Aros One 1.5 and above)
* 2025 year of 64bit pc builds and porting 32bit applications to 64bit ABIv11
* 2026 update of [https://www.youtube.com/watch?v=6FKTL068ULM&pp=ygUPYXJvcyBhbWlnYSAyMDI2 nvidia nouveau driver for 64bit PC]
===Bounties===
To help inspire developers with both ideas and monetary incentives, rewards are offered for the successful completion of "bounties" (requests for missing/new functionality) chosen by the community and handled by [http://power2people.org power2people] (formerly done by TeamAROS). A monthly option is [http://www.power2people.org/funds/aros/ here].
Future goals for AROS include expanding its underlying retargetability to support even more diverse architectures, provide memory protection features and user level file security, SMP and many other wonderful features missing from AmigaOS — while still providing as much source level compatibility as is possible (however it is accepted that to achieve some goals code certain things may require a little recoding).
[http://www.ohloh.net/p/aros/contributors Developers] come and go as with any open source effort and we would like to thank them for their efforts...
;1996-2000:In DigullaA (coordinator), GripJ, TempletonI (BSD), SchulzM, RittauS, voordenDagL, HolmM, JohanssonT, VanIngelgomH, SteigerwaldM, BortasP, deJongK, AlfredssonJ, InnocentiB,
;2001-2005:In [http://chodorowski.com/adam/aros.html ChodorowskiA], StegerG, BergerS, HeutlingS, AlemagnaF (gcc), VerhaegenS (rexx), KielH, MatheussenKS (CAMD), SzczygielskiP, ErikssonP, LeCorfecD (Zune), BauerS (Zune), FurlongW, GustafssonJ, AndrewsN, CafferkeyN, GierichM (jpeg), PattonJ, ParsonsM, DietrichJ, SeilerT, BischoffL, LorentzenNH, AdamO, BerglundH, SmithP, HolmenD, BlomM,
;2006-2010:In FedinP, RusslerM, SzymczykS (owb), SmiechowiczK (openGL), WeissM, NorrisR, BrunnerO, WiszkowskiT, GreppinA, [http://www.fukt.bsnet.se/~bearsoft/ Bearsoft Björn Screwelius], ErbY, CharletF, HodgesC, [http://aros-exec.org/modules/newbb/viewtopic.php?topic_id=4819&forum=18&post_id=43103#forumpost43103 HokstadV], McMullanJ (m68k), WilenT (m68k),
;2011- :In MuijzenbergPHvanden, ALB42, JonesEM, weiju, DizzyofCRN, wawa, miker,
* 1996 - The linux hosted version for i386 was the first to arrive
* 1998 - i386, The native version for i386-based PC AT computers and compatibles.
* 2004 - x86/64, The native version for 64-bit (x86_64, amd64) PC computers.
* 2008 - sam440/ppc, The native version for Sam440EP, Sam440EP Flex and Sam460ex computers.
* 2009 - efika, The native version for PowerPC Efika computers.
* 2010 - m68k, The native version for m68k Amigas or WinUAE
* 2013 - raspi/armfh, early native version for ARMv6 based Raspberry Pi computers.
* 2017 - x86/64bit smp
Debugging capture serial debug at all (especially with sysdebug=all or --sysdebug=all) to see it displayed on screen
* yes, usb -> rs232 adapters can work most of the time, some of the cheapest ones are not fully compatible with all rs232 devices to capture to another device
* you will need a null modem cable (or a null modem adapter usually female to female) in addition to the usb -> rs232 adapter (usb adapter is a normal modem ie. the pins are not crossed over)
Normal modem cable - straight connection DCE
<pre>
Pin 2 -> Pin 2 RXD
Pin 3 -> Pin 3 TXD
Pin 5 -> Pin 5 GND
</pre>
Null modem cable connections DTE
<pre>
Pin 2 -> Pin 3
Pin 3 -> Pin 2
Pin 5 -> Pin 5
</pre>
(9pole SUB-D)
<pre>
serial ser: (amiga/aros) tty2 tty1USB0 (linux) COM1 (windows) (depends on the os being used)
speed baud transfer rate 9600 38400 lower baud might be more successful
data bits 8
stop bits 1
parity none
handshaking flow control - none xon/xoff (most likely) rts/cts dsr/dtr (pins not connected so should not work)
</pre>
*You cannot use compiled aros X86-64 bit software (when ready) on aros X86 32bit. PPC compiled software on X86 and so on.
*68k is tested with the UAE emulator (WinUAE) but some tests are done on native 68000 based Amigas and others.
*PPC support is very limited to certain devices.
If you use the WBStartup, you have to delete the other icons in the folder (readme etc..) and you have to add in the Icon Tooltype the parameter DONOTWAIT
If you use user-startup instead, you need to add the attached command "after assignment to LUA"
C:WBRun DH1:Extras/Utility/WeatherBar/WeatherBar >NIL:
Change the command to match your WeatherBar path.
<pre>
PATH sys:Utilities/WeatherBar ADD
run >nil: lua:amilua weatherforecast.lua
</pre>
To enter data your Country or City, ist with city_id numbers can be found [http://bulk.openweathermap.org/sample/city.list.json.gz here] or you need to go to [https://www.bbc.com/weather BBC Weather], once you type the name of your city or town in the appropriate tab, and press enter, the 7 numbers to be added in the "WeatherBar" will appear on the Browser url address bar above
Unicode v16.0 emojis are not supported but [https://github.com/jens-maus/libcodesets codesets.library] provides
<pre>
internally supported (hardcoded) charsets/codesets are: (conversions are possible from and to each codeset):
AmigaPL – Polish (Amiga)
Amiga-1251 – Cyrillic (Amiga)
ISO-8859-1 – Western European
ISO-8859-1+Euro – West European (with EURO)
ISO-8859-2 – Central/East European
ISO-8859-3 – South European
ISO-8859-4 – North European
ISO-8859-5 – Slavic languages
ISO-8859-9 – Turkish
ISO-8859-15 – West European II
ISO-8859-16 – South-Eastern European
KOI8-R – Russian
UTF-8 – Unicode
In addition, external charset table files can be stored in LIBS:Charsets or loaded by an application from PROGDIR:Charsets. The charset files included with this distributions are:
IBM866 – Cyrillic (cp866)
ISO-8859-7 – Greek (LatinGreek)
ISO-8859-10 – Nordic (Latin 6)
windows-1250 – Central/East Europe (Windows)
windows-1251 – Cyrillic (Windows)
windows-1252 – West European (Windows)
</pre>
Icaros 2.3 USB image needs a header stripped so it can work correctly
dd bs=512 skip=1 status=progress if=icaros_light_2-3-0_pendrive.bin of=/dev/sdxy && sync
Scalos
<pre>
-------------------------------
{ "STRING", "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K",
HALIGN LEFT | CENTER | RIGHT
VALIGN TOP | CENTER | BOTTOM
STYLE NORMAL | BOLD | ITALIC | BOLDITALIC
FONT // font specification - format: "fontname.font/size"
-------------------------------
arguments for STRING SRC
"diskstate",
"diskusage",
"diskusagefree",
"diskusageinuse",
"diskusagepercent",
"fibfilename",
"filecomment",
"filedate",
"fileprotection",
"filesize",
"filetime",
"filetypestring",
"iconname",
"linktarget",
"plugin" pluginname <optional plugin arguments>
"versionstring",
"volumecreateddate",
"volumecreatedtime",
"volumeordevicename",
-------------------------------
arguments for HIDE
"novolumenode",
"isempty" (some STRING)
-------------------------------
all internal commands:
"about",
"backdrop",
"cleanup",
"cleanupbyname",
"cleanupbydate",
"cleanupbysize",
"cleanupbytype",
"clearselection",
"clone",
"close",
"copy",
"cut",
"delete",
"emptytrashcan",
"executecommand",
"formatdisk",
"iconify",
"iconinfo",
"lastmsg",
"leaveout",
"makedir",
"open",
"parent",
"paste",
"putaway",
"quit",
"redraw",
"redrawall",
"rename",
"reset",
"selectall",
"showallfiles",
"showonlyicons",
"shutdown",
"sizetofit",
"snapshot",
"snapshotall",
"snapshotwindow",
"unsnapshot",
"update",
"updateall",
"viewbydate",
"viewbyicon",
"viewbysize",
"viewbytype",
"viewbytext",
</pre>
{{status|50%}}
{{BookCat}}
ndpgakktbvm86so04be4bywelrxw7t1
4675862
4675861
2026-10-13T16:09:02Z
Jeff1138
301139
4675862
wikitext
text/x-wiki
{{ArosNav}}
==What is AROS==
Google translation
[http://translate.google.com/translate?hl=en&sl=auto&tl=de&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs German], [http://translate.google.com/translate?hl=en&sl=auto&tl=nl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Dutch], [http://translate.google.com/translate?hl=en&sl=auto&tl=fr&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs French], [http://translate.google.com/translate?hl=en&sl=auto&tl=it&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Italian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=da&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Danish],
[http://translate.google.com/translate?hl=en&sl=auto&tl=es&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Spanish], [http://translate.google.com/translate?hl=en&sl=auto&tl=hi&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Hindi], [http://translate.google.com/translate?hl=en&sl=auto&tl=zh-CN&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Chinese],
[http://translate.google.com/translate?hl=en&sl=auto&tl=ru&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Russian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Polish], [http://translate.google.com/translate?hl=en&sl=auto&tl=ja&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Japanese], [http://translate.google.com/translate?hl=en&sl=auto&tl=ko&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Korean],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pt&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Portuguese],
*Computer Hardware
*AROS (operating system)
*Applications and Games
*User
[http://www.osnews.com/story/15819 AROS] is one of the intermediate levels between the computer hardware and the user. It is an open-source, clean-room implementation of AmigaOS 3.x that can be run on many different computer architectures. It runs primarily on PC x86 32bit and 64bit but also on amiga motorola 68k and compatibles, some ARM like the Pi and Apple Silicon, RISC-V and some old PowerPC.
This page will cover enough to be able to write the downloaded image to your preferred media, to run a LiveUSB, LiveCD or LiveDVD on your office/home PC (Live meaning you can test without changing your existing setup) and, ultimately, to use it.
Intel / AMD PC hardware support mostly covers the years 2000 to 2024. At the moment, AROS is '''not''' recommended to be '''installed''' on a working vital data holding machine. Instead, writing to and booting from a '''USB stick''' could be a much better option.
AROS is an hobby OS and can co-exist with Windows(TM), MacOSX(TM), Android(TM) or Linux(TM) and act as an alternative.
Unfortunately, Aros has few developers so upgrades and improvements can take [https://sourceforge.net/p/aros/mailman/aros-cvs/ time to appear].
AROS core is now [http://en.wikibooks.org/wiki/Aros/Developer/IncompleteAPIs ~80%] finished and is usable, so keep in mind that the software is still considered ALPHA/BETA and in constant development. Currently AROS is fun to play with on a curiosity level, but it is also interesting to program. AROS has some multimedia features and has internet access.
Most importantly, use AROS to its maximum potential as it stands now, find ways to have fun with it and share your experiences.
Good Sites to visit
: [https://www.arosworld.org/home.php Aros World User forum]
: [https://arosnews.github.io/ AROS News]
: [https://www.facebook.com/ArosWorkshop/ Aros Workshop],
: [https://www.osnews.com/topic/amiga-aros/ OSNews]
: [https://www.reddit.com/r/aros/ Reddit]
: [https://archives.arosworld.org Aros Archives]
: [https://aminet.net/ Aminet]
: [http://www.amiga-news.de/en/ English translation of German site]
: [https://aros.sourceforge.io AROS] with [https://aros.sourceforge.io/download.html ABIv1 downloads]
: [https://github.com/aros-development-team/AROS Aros ABIv1 Codebase]
: [https://github.com/aros-development-team/AROS/issues register ABIv1 issues] and [https://sourceforge.net/p/aros/bugs/ old defunct bugs notification site]
: [https://sites.google.com/view/arosone Aros One x86, x64]
: [https://tinyarosdistro.flazio.com/ Tiny Aros x86 and x64]
: [https://arosnews.github.io/aros-portable/ AROS portable USB3 stick images of hosted Aros One x86 and x64 on debian]
: [http://vmwaros.blogspot.com Icaros Desktop x86 now on sabbatical, very old edition]
: [https://sites.google.com/site/arosaspireone AspireOS, of the netbook Aspire One, very old edition]
: [https://github.com/deadwood2 Deadwood's builds], [https://www.axrt.org/download/aros/v11/ v11 64bit PC builds], [https://axrt.org/downloads-aros Updated i386 32bit PC builds],
: [https://github.com/ezrec Ezrec x86 m68k mirror of old svn version]
: [http://arosalive.blogspot.co.uk/p/10-basic-aros-how-tos-tutorials.html Basic How To guides]
: [http://arosgamer.blogspot.co.uk/ AROS Playground], [http://thewetmachine.net/tag/aros/ Jess Wet Machine], [https://aroshacking.wordpress.com/ Jon Robertson's AROS Experiences and FPC Free Pascal], [],
:[http://www.apollo-accelerators.com/ Apollo Accelerators m68k], [http://www.amigablogs.net/ Amiga Blogs], [http://blog.a-eon.biz/blog/ Trevor Dickinson blog],
: [https://forum.amiga.org/ Amiga OS AOS 3.x forum]
: [http://eab.abime.net/ EAB Amiga]
: [http://www.amigaworld.net/ AmigaWorld]
: [http://www.ppa.pl/ Polish Amiga Like News]
: [http://www.apollo-core.com/ Apollo Forum]
: [https://amigaalive.blogspot.com/ AmigaAlive]
: [https://www.amigalove.com/software Disk Mags]
: [https://amigachristmastree.ultimateamiga.com/ Xmas Amiga Game Jam]
: [https://www.reddit.com/r/amiga/ Amiga]
== Distributions aka Distros ==
For end users there are distributions (ready made with selected apps aiming to be easy to use), mostly created and maintained by one person in their own workflow/style. They reuse the nightly boot compiles to suit their needs and possibly other end users. You are free to create your own if required.
* For native 64bit Intel/AMD: [https://sites.google.com/view/arosone Aros One x64], [https://tinyarosdistro.flazio.com/ Tiny Aros],
* For native 32bit Intel/AMD which will run on 64bit machines: [https://sites.google.com/view/arosone Aros One x86], [https://www.tinyaros.it/ Tiny Aros],
* For native 68k [https://sites.google.com/view/arosone Aros One m68k], [http://www.aros-platform.de/ AROS Vision],
'''Please, keep in mind that the distros listed above use a different ABI (abi v11) , which is NOT binary compatible with the official ABI V1.'''
* For hosted Linux usb drive image [https://arosnews.github.io/aros-portable/ x64 Debian hosted version of Aros One],
* For hosted ARM there is [https://github.com/jonx/AROS-AArch64/releases alpha for Apple Silicon] and [https://aros.sourceforge.io/nightly1.html RaspberryPi Pi3, Pi4, Pi400, Pi5, 500+ raspi-aarch64-system native 64bit]
AROS was originally developed on Linux but can run on an Intel-based Linux distro as an app. As time has gone on, it can be run as an app on many more operating systems (Windows, FreeBSD, Linux and limited on MacOS). This may sound strange: an OS running on top of another OS.
Basically, this is to take advantage of drivers (audio, internet, graphics, etc.) and compiler environments, in the existing OS, with which people may be already familiar. The term we use for what AROS does is "Hosted".
AROS Native is the term coined to describe AROS being run without any OS underneath it. It runs alone just like AmigaOS(TM) did. As this version does not benefit from "Hosted" drivers, dedicated ones have to be ported/written. Hence the smaller range of supported hardware / peripherals. We have other pages highlighting this support
AROS is open source so basically everyone can take part. The source is public on github and there are new commits most days. AROS is automatically compiled daily, result are the nightly builds hosted on Sourceforge. The nightly builds are only used for testing changes, testing software and the starting point for distribution maintainers or even your own distribution. They are very basic, miss some functionality and apps like web browsers and generic general appearance which can be changed.
* The [https://sourceforge.net/projects/aros/files/nightly2/ Nightly2], [http://aros.sourceforge.net/download.php nightly builds File Release Service] or [http://aros.sourceforge.net/downloads/ Sourceforge Project Web builds] are made automatically every night directly from the Github and in the past, SVN (Subversion) tree and contain the latest code for the AROS operating system. It should be noted that the builds have not been tested in any way and can be horribly broken but usually are not.
*ABIv1 standard for most nightly builds, it is where the most work is done by developers
*ABIv11 offspring aka fork of 64bit PC ABIv1 i.e. another PC 64bit build
*ABIv0 standard for PC 32bit intel / amd PC distributions for historic reasons
==Media==
AROS media tends to boot in this tier list of media types, first internal HDD SSD, CD DVD drive, and finally usb drive (last two can depend on bios boot order)
* USB .VHD
[https://sites.google.com/view/arosone Aros One x86 and x64], with md5 below
<pre>
0a656d53a9c902e9934000d8392e30ec *ArosOne-USB-1.3-64Bit.zip
7dd7119ab3e56d75ee852c137226b4d7 *ArosOne-USB-v1.2-x86_64-v11.zip
cf906eeaad4a83b3520b1896bdc6b0d3 *ArosOne-USB-v1.1-x86_64-v11.zip
e2eb8fe8cfd61c567b0152a61cf85251 *ArosOne-x86-v2.8-USB-IMG.zip
559909c75c2f56472c74267a7d075355 *ArosOne-x86-v2.7-USB-IMG.zip
93da5898508c1a8c05bb8991ab7bd117 *AROS One Image-USB-2.4.zip
59fcabd7090e47f12d54f7eb78cf0f45 *ArosOne-x86-v2.2-USB-Image.zip
24fb8de726ae8fc5fe5bac6d30f03dc5 ArosOne-x86-v2.0-USB-Image.zip
f3d725e990072edce633b59747911b6b ArosOne-x86-v1.8-USB-IMG.zip
e089a24ae310e92fcc407a0125602ce8 Aros-One x86-IMG-USB-v1.6.zip
</pre>
[https://tinyaros.flazio.com/ Tiny AROS]
22bc993625b7c75b17263c0cc7e7baaa *Tiny Aros_copy.vhd (March 2024)
There is usually a vhd image inside the zip that can be written to USB sticks which is so much faster than the old ISO written to physical CD DVD method. This .vhd can be written to an USB stick / ssd with these pieces of software below but it will erase the previous contents from the usb
Windows - [https://www.raspberrypi.com/software/ RPi Raspberry Imager, use custom and see all files], [https://hddguru.com/software/HDD-Raw-Copy-Tool/ HDD-Raw-Copy-Tool], [https://rufus.ie/ Rufus up to version 3.20 may work with VirtualBox HD vhd images with Win7 but not some Rufus 4.x versions], [https://etcher.balena.io/ Balena Etcher but may spy on you],
Linux - [https://www.raspberrypi.com/software/ Raspberry Imager Ubuntu], Suse Image / Multi writer, dd,
Mac -
* Virtual Machine .ISO or CDs DVDs
The native iso images are currently not compatible with Ventoy, Yumi, MultiBootUSB, Easy2Boot E2B, or similar
<pre>
617a905b1665128c5e05f94dcc48e7f1 *AROS-One-v1.3-64Bit-v11.zip
11c8a147fcad7ecf52ae3a43e1934b69 *ArosOne-DVD-v1.2-x86_64-v11.zip
f93053d3b9ccf304d7e6ac3389e1987b *ArosOne-DVD-v1.1-x86_64-v11.zip
86d808a40dc7be389a758799a9b4f595 *ArosOne-x86-v2.0-ISO-DVD.zip
f1fc8599ef6a39e5df394e0f41d55526 *AROS-One-x86-ISO-DVD-v1.6.zip
</pre>
You can use a virtual emulator like VirtualBox, VMWare to mount the iso image which can then be used to boot and/or install to USB.
No current software can write an AROS ISO to a Pendrive. The author of ‘Rufus’ (who used an Amiga 500 as a child) once tried, but when he saw the system composition, he said he was unable to do it.
The solution is to boot the ISO from a VM (WMware, VBox), then install the AROS build on the Pendrive, which will eventually become a Live Pendrive that can be booted on a PC.
The only precaution is that in some cases it is necessary to thoroughly clean the Pendrive of any partitions and remove any bootloader that is not AROS. The Pendrive must remain raw without any partitions.
You can clean the USB stick on a PC with a program that manages hard disks. You need to do a partition wipe. On some USB sticks, you can clean it with InstallAROS.
For some USB pendrives, please use a reputable partition editor to remove any and all partitions from a usb pendrive as HDToolbox cannot do this task sometimes with a wipe all option.
Previously the only installation option was CD-RW or DVD-RW, since the whole system can be burnt onto a single disk and can be reused when the next version is released. Good branded discs like Taiyo Yuden (later JVC) or Verbatim should be used to reduce frustration later. The days for this media is gone but kept here for information
Since nobody currently sells AROS on any other media, you will need access to a CD/DVD burner to create the installation disk yourself. After it is on a CD or DVD, then access and writing to USB pendrives becomes available (this should be viewed as an outdated or last resort alternative method now), as well as using good USB manufacturers like Sandisk, Kingston, etc. rather than some other no-names.
Try burning it to a CD-RW or DVD-RW using your CD/DVD burning program (most burning software have a burn iso option). The ideal writing speed is 2x or 4x, higher speeds can give errors and problems. Check the writing integrity of your CD or DVD if your software has an option to do so before going any further.
Standalone portable usb cd dvd drives do not boot physical burnt discs, please use an internal ide sata drive instead.
* SD-card
For [https://aros.sourceforge.io/nightly1.html ARM Pi Aros 64bit], copy the files onto a FAT32 formatted micro SD card.
==Booting==
The LiveUSB, and in the past LiveCD LiveDVD, is designed to trial (test drive) various operating systems without having to install them to your working system.
Since 2011, UEFI was introduced to replace the original PC BIOS which made booting media more confusing. Some changes in the UEFI/bios may be needed
*go into the bios using esc, f2 or f? and disable the Security -> Secure Boot and maybe apply option for Legacy IDE mode
*you may have to press F9, F10 or F12 or p on boot up to present a device boot options like USB or CD/DVD
*disable the Fast Boot config so it would recognize portable DVD-drive and changed the Boot-sequence
Secure boot was introduced by Microsoft and later consortium, control what operating systems work with Secure Boot via shims.
For Aros, it is best to disable and save the turn off change to Secure Boot (if you dual boot with Windows this will cause issues with further Window boots)
For the best experience, it is advised to install to another SSD than the one Windows resides on.
The grub part of the boot should be fully automatic, and you should see a multiple choice graphic card screen after 10 seconds for USB or 40 seconds CDs and DVDs.
If boot does not occur within a minute, please reboot and choose the VGA boot option as it relays a message stream so you can see where the issue lies.
After the grub graphics choice, AROS takes over the booting and any issues can arise here
If possible please use a branded usb pen drive as most of the time when we get reports of "crashes right after grub boot selection" it is mostly due to the recorded pendrive as they are made, notoriously on a will it work / will it fail nature, every time it is used.
<pre>
So one usb drive written may stop at a System halted. Reset the machine.
Or another pendrive will show give errors Smart Filesystem request - Volume 'Aros Live Drive' (DU0: usbscsi.device unit 0) There was an error while accessing this volume:
Or if a FAT32 partition present - FAT filesystem - Device USBSCSI0P1 has a read error on block xxxxxxxx -
</pre>
Sadly, no drive even branded are resistant or totally reliable, so the only solution is to try another pendrive, and possibly to repeat, until no errors.
It will give an indication on how reliable the usb drive could be.
=====Advice for various machines=====
Some of the stages involved and shown on the display in a typical AROS boot start up
<pre>
[MultiLoader]
[ELF Loader]
[Boot]
[HPET]
[Kernel:ACPI]
[Kernel:APIC-IA32]
[Kernel:SMP APIC]
[HiddStorage]
ACPI: ????
ACPI Error
[ACPI]AcpiOs????
[BattClock] Got RTC century offset 0x32 from ACPI
[PCI] Scanning bus ?
[AHCI] Sata
[Vesa] only if vesa is chosen as graphics option
[ATA] detect hd & cd drives
[ATA0?] ata-identity
[packet] fat.handler be.handler, etc.
[DOS]
[Storage:Bus]
[Storage:Controller]
[MSS] USB setup
[ehciInit] Port ? maps to controller ?
[I2C]
[ATI]
[drm] nouveau
[AROSTCP] if you have network driver prefs set up to start when booting
</pre>
; If boot fails, please give us some indication (pictures or videos) where the boot stops and the message(s) on screen.
AROS's native SATA/AHCI driver doesn't always work. If you get errors related to ahci.device, try disabling it. At your chosen boot entry in the GRUB menu, Press E, scroll down to the ahci.device entry, and add a # or ; at the start of that line or delete it with Ctrl-K. Then press Ctrl-X or F10 to boot.
If your disk isn't accessible at all with this change, you might need to change the SATA controller to IDE legacy mode in the BIOS: however, making this change will likely cause problems booting Windows on the same machine (if it's already installed). To disable ahci.device permanently, edit the text file "SYS:Arch/pc/grub/grub.cfg", and remove the ahci.device line from all boot entries you intend to use.
SATA AHCI Timeout while waiting for device to complete operations with BIOS SATA entry set to AHCI mode stops at "waiting for bootable media" screen, changing BIOS SATA setting back to IDE mode may allow it to continue booting
The ATA driver doesn't always work. If you get errors related to ata.device, try using the alternative in sys:devs/alt which is an older version. Press E when your chosen boot entry is highlighted in the GRUB menu, scroll down to the ata.device entry, and change it to read "module /Devs/Alt/ata.device". Then press Ctrl-X to boot. To make this change permanent, edit the text file "SYS:Arch/pc/grub/grub.cfg", and change the path to ata.device in all boot entries you intend to use.
Further options (removing the " ") to add to the GRUB menus to disable certain other components for debugging:
<pre>
Disable AHCI "AHCI=disable"
Disable NVME "NVME=disable"
Disable ATA: "ATA=disable"
Disable ATA: "ATA=nopci,nolegacy"
ATA safe mode: "ATA=nodma,32bit"
Disable IDE from SATA: "ATA=32bit,nosata2pata"
VIA / SIS with cdrom read io errors "ATA=nodma,nopoll"
noacpi all [PCI] devices to be invisible to AROS. disk drives work but network, sound won't
acpi=strict if there are issues with sound after boot
noioapic alternative to no acpi
Set AHCI "AHCI=force150/force300/force600"
Disable AHCI/SATA: comment out with a # ; or remove ahci.device line with Ctrl-K
Disable USB: comment out # ; or remove pciusb.device and poseidon.library lines with Ctrl-K
Disable native graphics: "nomonitors"
USB3 "USB=xhci"
</pre>
Other useful grub command line options - nomonitors, noacpi, vesahack, nopoll
Press Ctrl and X together (or F10) to exit and boot with the new options. Just experiment with different variations until successful. Those working options will need to be reused with every reboot of AROS until you can edit the grub.cfg and make it permanent i.e. install to hard disk or USB.
* If you use VESA mode, you can see the debug log if you add 'vesahack' to the command line. This will set up split-screen mode. In the upper half you'll see AROS screen, in the bottom - debug log.
* ACPI ie. PCI hardware - If you get crashes at early boot, try adding 'NOACPI' to the command line
If you're having boot issues and have a null modem cable and a spare pc, a boot log is always useful. Edit your grub line to include debug=serial but would try with an with sysdebug=all in the line later as it can cause issues booting on machines with sysdebug=all enabled (corrupts the cpu initialization).
However, if you feel you have found a genuine bug/fault in AROS that needs attention, please use the [http://sourceforge.net/tracker/?atid=439463&group_id=43586&func=browse bug submission form] to record as much information about what happened, why, and what hardware etc. you have so that people may try to assist you
For Virtual machines VMWare VirtualBox, etc., attach and press play to start the ISO image
If booting hasn't worked then it could be down to Bios/UEFI settings
=====nvme.device=====
Since 2018, nvme drives are standard on most machines
The requirement is that a PC can boot with legacy mode/BIOS at the moment - Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
This is still in testing and its' use should not be on or near precious own data
=====AHCI=====
Starting taking over since 2011 on a lot of machines
* Check that UEFI (replacement for PC BIOS) has options set to remove UEFI SecureBoot option and apply CSM
* SATA drive is set for Legacy or a mixture AHCI/IDE and not AHCI
AHCI sata can be very difficult to get working
Most Windows installs are already set to AHCI sata, changing this to a legacy IDE mode setting can help but please check if Windows will still boot. Some hardware like Lenovo laptops do not always like being set in legacy mode so only use as a last resort and aware of issues that can be caused.
Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
With a 16C/32T chip machine, disable SMT and it should boot.
=====ata.device for old BIOS's =====
Pre 2010 this was the de facto standard method of providing settings to the computer at a lower level
Some adjustments to the BIOS setup options are necessary (usually by pressing a key like DEL, F1, F2, F12 or ESC, p on the very early boot up of the computer).
*Adjust booting options like moving USB hdd, CDROM higher as it is quite often disabled or placed lower by default, i.e. USB hdd, CD/DVD are placed at the top above the hard drive. Try looking here [http://www.windowsreinstall.com/articles/bios/ Windows] or [http://www.hiren.info/pages/bios-boot-cdrom Bios] or [http://www.wikihow.com/Set-Bios-to-Boot-from-a-CD-ROM Boot] or web search "BIOS BOOT CDROM"
* At the '''SAME''' time, check if the SATA/AHCI option is set to Emulate or IDE Legacy, though this can have '''issues''' with any OS already on the hard disk. If in doubt, do nothing and seek advice.
* check that under BIOS settings you '''DO NOT''' have plug&play OS selected as Aros at this point is unable to route interrupts on its own and needs the BIOS to do that.
'''Save''' options changed at the end.
PCITool can show if the motherboard chipset is in IDE mode.
Class = 0x01 means STORAGE, Subclass = 0x01 means IDE. Also ProductID 0x3a20 resolves to non-AHCI mode in Intel ICH10 documentation.
==Installing==
We have a separate section [https://en.wikibooks.org/wiki/Aros/Platforms/x86_installing here]
We have a specific section for each CPU platform under the Specific platforms in the NavBar navigation bar on the right hand side menu
error code (-6) when using the ahci.device (has writing to disk problem but not reading) is enabled. change this line in your grub and reboot
<pre>
#module /Devs/ahci.device << disable
module /Devs/Alt/ata.device << add this line instead
</pre>
==File structure overview==
AROS' directory structure is mostly identical to AmigaOS directory structure, with some additions.
AROS: or SYS: also known as DH0: (i.e. the drive partition with AROS system) has the following simplified list of the main drawers (Amigas term for directories/folders).
{| class="wikitable"
|boot:
| grub bootloader
|----
|C:
| small apps, where AROS looks first for applications/games but will look at Tools, System afterwards
|----
|Classes:
| .class as well as datatypes
|----
|Devs:
| .device .resource and in their own drawers (folders) .audio, .hidd, network, graphics
|----
|L:
| where .handler files go
|----
|Libs:
| where .library files go
|----
|Locale:
| where help guide txt readme files go
|----
|Prefs:
| applications that adjust or setup AROS functions and capabilities
|----
|S:
| startup scripts (for the aros boot process '''not''' grub) are stored here
|----
|Storage:
| place to keep old or alternative device drivers
|----
|System:
| applications associated with AROS operating system
|----
|Tools:
| extra applications
|----
|Utilities:
| extra applications
|----
|WBStartup:
| copy applications here to autostart with needed icons, drawers, data etc
|----
|}
See [[Aros/User/DOS#Drives.2C_Files.2C_Assigns.2C_Directories|DOS manual: Drives, Files, Assigns, Directories]]
=== Filesystem ===
Whilst the kernel is the heart, the filesystem is the blood of the system they are split into two categories (only a few are supported)
<pre>
Journalling - SFS PFS3 but also NTFS ZFS XFS ext4
Non-journaling - FFS FAT32(VFAT) but also exFAT BtrFS ext2
</pre>
Filesystem options for AROS to install
* SFS default
* Professional File System PFS3 [http://eab.abime.net/showthread.php?t=52234&highlight=pfs3+free&page=13 only on motorola 68k at the moment] [https://github.com/aros-development-team/AROS/blob/e34170ea87da3b32935b60ed99d837b2b903a021/rom/filesys/pfs3/fs/mmakefile.src issues to compile on other platforms]
* FFS very old now but left in for legacy usage
Other [https://archives.arosworld.org/index.php?function=browse&cat=driver/filesystem filesystems] for storage purposes
* FAT32 favorite as most OSs support
* NTFS (can lock AROS)
* exFAT
The only filesystems that really NEED defragging (i.e. disk tidy up) are from Microsoft(TM) - exFAT/VFAT/NTFS
*SFS tries to do exactly the same thing, but in certain cases it doesn't do as well as PFS. But you can defrag SFS
*PFS *minimises* the amount of fragmentation, but does not automatically defrags as it saves files to the drive
The setup of the below filesystems is usually done by the distro maintainer but if not....
<pre>
Copy L/exfat-handler L:
DOSDriver or Mountlist entry for an exFAT partition make sure that the FileSystem and Handler are set as follows:
FileSystem = exfat-handler
DosType = 0x46415458
</pre>
<pre>
Copy L/ntfs3g-handler L:
DOSDriver or Mountlist entry for an NTFS partition make sure that the FileSystem and Handler are set as follows:
FileSystem = ntfs3g-handler
DosType = 0x4e544653
Also to make a read-only mount you can set:
Control = ro
</pre>
The Smart File System (SFS) is a journaling filesystem used on Amiga computers and AmigaOS-derived operating systems. It is designed for performance, scalability and integrity, offering improvements over standard Amiga filesystems as well as some special or unique features.
SFS is written in C and was originally created and released as freeware in 1998 by John Hendrikx. After the original author left the Amiga scene in 2000, the source code to SFS was released and its development continued by Ralph Schmidt in MorphOS.
Its development has now forked; as well as the original Amiga version, there are now versions for MorphOS, AROS, AmigaOS 3, and a version for AmigaOS 4, which have different feature sets but remain compatible to each other. Versions for AROS, AmigaOS and MorphOS are based on different branches.
In addition, there is a driver for Linux to read Amiga SFS volumes, GRUB natively supports it and there are free drivers to use it from UEFI. The Linux version is [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ independent code].
SFS (Smart File System) partially defragments itself while the filesystem is in use. The defragmentation process is almost completely stateless
AROS SFS version has a 120GB partition size limit on hard disks and DVDs current 4gig size limit.
The sources for the MorphOS 64-bit version of SFS were available but no porting to AROS has happened so far due to endian issues, etc.
SFS Tools
* GUI - arSFSDoctor,
* CLI - sfscheck , [http://www.portacall.org/ sfsundelete], sfsformat, setcache hits a usability ceiling around the 10GB / 100,000 file mark,
sfscheck dh0: seek purge fraglist defragment
If there are two simultaneous file writes in progress and you reboot machine (or it locks up or crashes) you may end up with a corrupted filesystem. Although arSFSDoctor may help, you might have to copy the files to another partition, format the partition with the errors on and copy the files back.
PFS / SFS are way more advanced and much much faster than the FFS. FFS is supported for legacy reasons only.
The Professional File System (PFS) is a filesystem originally developed commercially for the Amiga and now distributed on Aminet with a 4-clause BSD license. It is a compatible successor of AmiFileSafe (AFS), with an emphasis on added reliability and speed compared to standard Amiga filesystems. It also features multi-user abilities like the older MuFS.
PFS has so many advantages including the important things, speed, the ability to recover all deleted files even simply same name by typing the command ". Deldir" convenient if done in Directory Opus, virtually deleted files are copied normally as if they had never been deleted, other convenience is to not ever invalidate the filesystem, just put it on top of the startup-sequence command "diskvalid", which automatically corrects any irregularities in the system startup; PFS also provides a device for floppy which makes them very fast and takes advantage of the full capacity of the floppy including the area dedicated to the bootloader.
The device is split into two main areas. At the beginning of the device is the metadata section, which consists of a root block, and a generic array of blocks that can be allocated to store metadata. The rest of the device is another contiguous generic array of blocks that can be allocated to store data. The metadata section usually uses a few percent of the device, depending on the size of the device.
The metadata is stored as a tree of single blocks in the metadata section. The entire directory structure is recorded in the metadata, so the data section purely contains data from files. The metadata describes the location of data in files with extents of blocks, which makes the metadata quite compact.
When a metadata update occurs, the system looks at the block containing the metadata to be changed, and copies it to a newly allocated block from the metadata section, with the change made, then it recursively changes the metadata in the block that points to that block in the same way. This way, eventually the root block needs to be changed, which causes the atomic metadata update.
The filesystem is reasonably good at keeping files unfragmented, although there is a defragmentation tool available which will work on an online filesystem ie whilst being used.
It was the first filesystem to introduce the concept of the Recycle Bin natively at filesystem-level to the Amiga, holding the last few deleted files in a hidden directory on the disk root.
PFS version 5.3 was developed in C and a small portion of assembly code by Michiel Pelt. There are endian issues to be overcome and adapting the small amount of m68k to C before use on intel based machines, etc.
Autoupdate of files in a directory is already implemented in Wanderer, but not all file systems handle dos.library/StartNotify() in its full extent. It seems to work correctly in Ram Disk (thanks to AmberRAM handler), and it also works on SFS formatted devices. Other file systems might not yet have it implemented correctly though.
The PC equivalent of the Amiga's RDB is the master boot record (MBR).
===Installing Applications===
The typical means to install applications under AROS/AmigaOS involves simply copying/extracting the archive (.zip .lha .rar .tar.gz) file containing the applications files to your own desired location i.e. drawer/folder. Once extracted, launching it by double clicking on an icon (recommended) or using the shell (alternative). Generally, this is on a separate partition from your AROS system files, however in reality it can be any location - including RAM: if you don't want it staying around too long especially when you switch off.
At some time in the future it may be desirable for AROS to have a package-manager like subsystem able to retrieve information online about packages available for AROS and whether they update anything you currently have installed, however at the moment no such ability exists.
===User Data files===
AmigaOS has no notion of a default location to store user data files, and presently neither does AROS - though it may be desirable at some time to provide a common start location.
Some people, have extra small FAT32 partition(s) using HDToolbox, and not Qparted, to store data especially if a reinstall is ever needed. And then setup the usual Sys: (DH0:) and maybe Work: (DH1:) / Live USB (DU0:) and maybe Briefcase (DU1:) partitions.
===User Environment configuration files===
AmigaOS/AROS stores persistent system configuration data in directory assigned to ENVARC:. This, by default, points to SYS:Prefs/EnvArc.
During boot a copy is made to another assign, ENV:, which is for runtime usage. Changes to the files here will not survive a reboot.
Setting the env variables is generally done by applications themselves, or when necessary by the user using the SetEnv command. SetEnv has a SAVE switch to force the persistent copy in ENVARC: to be written also for when you are sure the change should be permanent.
Under the standard installation of AmigaOS style OSs, ENVARC: is copied to ENV: upon startup, which, if you have a hard drive installation, is in RAM:, hence, ENV: ends up being RAM:Env.
ENVARC: is the Environment Archive, which is the permanent copy of ENV:, which is the Environment. It's roughly like the Registry in Windoze.
Most programs do (and all should) store their settings in ENVARC: somewhere, and load them from ENV:. The effect of this can be seen in the Preference editors. If you Save your preferences, they go in ENVARC: and ENV:. If you click Use, they only go in ENV:. If you reboot, normally, anything saved to ENV: is lost, and is replaced with a copy of what is in ENVARC:.
you can set the default public screen for any tool started from a cli with the PUBSCREEN variable. So open the pubscreen, set PUBSCREEN to the name and start newcli for example, then the new cli window (and all following windows opened from that window) will appear on that public screen.
===Drivers===
For certain hardware, e.g audio, networking and , there is no auto setup. Just like the original Amiga OS.
For audio, use AHI in the Prefs folder to set Music and at least Unit 0 with the appropriate driver and press Save. For ethernet and wifi, please use SYS:Prefs/Network
All hardware support is placed in the Devs drawer (folder/directory). The network drivers <something.device> go in the Networks sub-drawer. Audio drivers <something.audio> are put in the AHI sub-drawer. Graphics drivers <something.hidd> are put in the Drivers sub-drawer.
==Configuring==
AROS has mainly decided on a MUI-like requester&menu clone called Zune so changing the background, icons, font, menus can be done with SYS:Prefs/Zune
AROS has several desktop GUI front ends like
* DOpus5 Magellan II, Wanderer and Scalos (medium)
* AROS Workbench, Workbook (smaller)
File / Directory managers like Dopus4, MCAmiga,
App Launch Shortcuts like FKey, BoingIconBar, right mouse click on magellan, wanderer desktop, Amistart, etc.
General usability decisions - Prefs/IControl, Prefs/Locale, Prefs/Input, Prefs/Fonts,
Select an icon with left mouse button and then right click the mouse button and selecting Icon -> Information gains access to the tooltypes tab where information can be edited
CLI in icon's tooltypes means 'run it as if it was run from shell'
If, on the other hand, the WB parameter (or no parameter) is present in Tooltypes, Wanderer will execute the binary and, if provided, the options included in Tooltypes.
WBxCLI is very useful for adding options to DOS Commands.
Important: AROS has a different way of managing icons. If you have an executable file, you will never be able to add a project icon. AROS will automatically recognise that it is an executable file and will transform the icon into a tool icon.
Icons are typically now .png pictures renamed as .info e.g. so Office application name would have a Office.png renamed as Office.info or MyApp.png as MyApp.info, etc.
Leave Out menu option to leave app icon on desktop
To select multiple icons and save their positions, click on the first icon and after while you hold the Shift key down select further icons and don't release it before SnapShot is finished. You can also select a whole group of icons by pressing the LMB at the top left of the icons and while keeping the LMB down moving the power towards the bottom right. A expanding bounding box will appear and all the icons within it will be selected.
Clean Up menu option (right mouse button -> Icons) rearranges icons in a drawer or disk window into a neater condition. To use, open the window to rearrange and select Clean Up. To keep the icons in the new positions, select all the icons (shift key or mouse selection) and select 'Snapshot' and then Window and then again with All.
In DOpus5, Scalos, wanderer, most files have an icon file associated with it. To change the default tool, select Icon menu, Information, and change the default tool string. For example, you could use Multiview, Editor and so on for most text, graphics and some sound files as long as the appropriate Datatype classes are installed. For scripts, set the tool to C:IconX
We have new Icon edit tools in progress but if you need to...
C:Join Image1.png Image2.png TO MyFile.info
is enough to make a dual state icon from two png images. You can then use Wanderer's menu Icon/Information on it to edit its fields and tooltypes.
[https://archives.arosworld.org/index.php?function=browse&cat=graphics/icon AISS toolbar images] unpack unarc them into RAM: and copy Images directory to SYS:Prefs/Presets/ AISS icons are looked for in PROGDIR:, PROGDIR:Images, SYS:Prefs/Presets/Images and then in TBImages: according to Open Amiga guidelines.
there is Demos/iconscale which could be launched from S:User-Startup with two arguments, telling it the horizontal and vertical size. IE something like
Demos/iconscale 40 40
It will shrink icons... not sure if it will be very nice though. it doesn't work for the icons on the main desktop.
there is an option to scale an icon to a bounding box afair, try iconsize followed by two numbers, like:
iconsize 32 32
Is there any way in AROS to change an icon type from Project to Tool or vice versa?
Either the SIT option of [ ProcessIcon], or the TYPE option of HandleInfo (not sure if this one works at all, please test with care).
processicon sys:pathoftheicon SIT=Project
SIT Set type of ICON. Allowed types are: "Disk", "Drawer", "Tool", "Project", "Garbage", "Device", "Kick" and "AppIcon".
Btw, are your icons, the #?.info files, writable, is the W flag set ?
'''Decoration''' is Aros' way to provides a way to hide the old Workbench 3.1 style of windows and screens. In Prefs/Appearance some decorative theming elements need work
Themes - SYS:Prefs -> Appearance
The default content of Prefs/Env-Archive/SYS/themes.var should be "themes:ice" but can be changed via the Appearance prefs, please do NOT click the Use button. Its useless. As you know, it will ask for the theme volume. Just pick the theme you want, click on Save, then reboot.
* Decoration is on. Any time trying to change theme, you get: "Please insert volume Theme: in any drive"?
You could check if you find SYS:System/Themes or if it is missing. Then you could open startup-sequence which you can find in drawer "S". There should be a line:
Assign THEMES: SYS:SYSTEM/THEMES >Nil:
This does the trick.
Open a shell and run:
Assign THEMES: SYS:SYSTEM/THEMES
Than start the Theme prefs again... this should work
* The theme is the only thing that could slow the system a bit, but it's not that performance impacting on most uses, and you can switch it off completely. Remove C:Decoration from the bottom of the file sys:s/startup-sequence.
In each theme directory is
*Env-Archive -> Zune -> global.prefs
*images -> Gadgets -> 20x20 pngs for Down etc
*menu -AmigaKey - Background - Checkmark - SubMenu and config
*system - Arrowdown, Arrowleft, Arrowright, Arrowup, etc
There is an [https://archives.arosworld.org/index.php?function=browse&cat=graphics/theme ALua/Zulu script] built for faster Wanderer skin management. You can modify config files, install new (wdz format/zipped skin files) and delete skins via the Theme Manager. This has not been updated in a long time and may not work.
Certain features are added if from Tools/Commodities like Blanker screensaver, ClickToFront and DepthMenu with .info icons are selected and dragged to /WBStartup folder
Most apps can be autostarted by copying into SYS:WBStartup directory folder
e.g. WeatherBar.zip can be downloaded, unzip and the contents of the zip copied to wbstartup folder
ClicktoFront and .info to SYS:WBStartup so always be activated when turning on the computer
or add a text line to user-startup is SYS:S (scripts version of wbstartup)
e.g. standard Amiga / AROS does not allow clicking of background windows to come to the front to make it easy to get to the window you need but it has the ability if these apps are copied again to WBStartUp or are added to SYS:S/user-startup script
run QUIET sys:Tools/Commodities/ClickToFront >Nil:
run QUIET sys:Tools/Commodities/DepthMenu >Nil:
run QUIET sys:Tools/Commodities/Blanker seconds=300 >Nil:
Exchange controls Commodities and can be opened with alt, ctrl, h
*AltKeyQ uses left Alt key to add strange letters
*AutoPoint
*Blanker screensaver
*ClickToFront allows windows to be easily brought to the front
*DepthMenu adds menu to select window easily
*NoCapsKey
*Opaque
*FKey - Although there are heaps of docks, menus and other launcher programs on the Amiga like OSs, FKey has got to be one of the quickest once learnt ways to launch programs, and it comes with the OS. In SYS:Tools/Commodities, the FKey commodity (Ctrl Alt F) allows you to make actions assigned to some combinations of keys
<pre>
ALT TAB Cycle Windows
Cycle Screens
Enlarge Window
Shrink Window
Toggle Window Size
Insert Text
Run Program
Run Arexx Script
</pre>
e.g.
<pre>
LAmiga F1 = Avail Flush
LAmiga F2 = Open Prefs
LAmiga F3 = Finder
Alt Tab = Cycle Windows
LAmiga Tab or M = Cycle Screens
Alt Up arrow = Enlarge Window
Alt Down arrow = Shrink Window
Alt Home = Toggle Window Size
= Insert Text
LAmiga e = Run Program
= Run Arexx Script
</pre>
If your FKey GUI pops up when you start your Workbench up and you don't want it to, click once on the icon, go to the Icons-Information in the menu and make sure it has the tooltype set "CX_POPUP=NO".
Now let's launch it and assign the locale switching. After you double-click on FKey icon, launch the Exchange, choose the FKey from list and click the Show button. This will invoke the FKey window. You can see the ALT TAB in list assigned to window switching. Now enter the first key combination, say, ALT Z and go to the right panel. Choose Launch the program from pulldown menu and enter SYS:Prefs/Input as an argument. Append the USE switch and english preset name to the string as shown:
SYS:Prefs/Input USE SYS:Prefs/Presets/english
Click on the New Button to add the another combination. Now set the combination for your locale as shown above, replacing English name with your preset name. Click New button again and then Save Settings. Now you can use defined combinations to switch the layouts.
There is a system wide ARexx script capability (based on regina) that can manage many file manipulation task(s) but this would work only with those program that support [https://en.wikibooks.org/wiki/Aros/Developer/Docs/Rexx ARexx] like
*Desktop - DOpus5, Scalos
*Dock - FKey,
*Files - Multiview, DOpus4,
*Internet Apps - Odyssey, WookieChat,
*General Apps -
the shell can be modified with escape strings but not needed in most cases
Common Keyboard Shortcuts
<pre>
RAlt Right Alt Key
LAlt Left Alt Key
RWinKey Right Windows Key
LWinKey Left Windows Key
RAmiga Right Amiga Key (if one)
LAmiga Left Amiga Key (if one)
</pre>
;Bootup Options
:Spacebar during boot, enters the bootmenu which allows a boot without startup sequence, etc
;Left Click
:LAmiga = LWinKey = F11
;Right Click
:RAmiga = Help = F12
;Mark
:RAmiga and B
;Cut
:RAmiga and X
;Copy
:RAmiga and C
;Paste
:RAmiga and V
;Search
:RAmiga and S
;Mouse Movement
LAmiga and together with arrow keys - shift as well at the same time as well to move faster
;Mouse Selection
LAmiga and LAlt to select
;Screen Switching
LAmiga and M or N
;HELP key
Can sometimes be mapped to F11 but can be changed via FKey
ComKeyRemapper or AmigaKeyremapper could swap RAmiga to another key press
===DOpus 5 Directory Opus Magellan II===
Dopus 5.x is a whole desktop replacement on the Amiga Workbench (Desktop)
DirectoryOpus app will assign DOpus5: to it's PROGDIR: automatically but if not add the below (edit SYS:System to suit where Dopus5 was installed) to your startup-sequence
<pre>
Assign DOpus5: SYS:System/DOpus5
DOpus5:DirectoryOpus
;DOpus5:C/LoadDB
</pre>
Left mouse button clicked twice on the desktop background brings up the Device List window.
Green strip notifies SRCE (source) and if another is open it will be red for DEST (destination). clicking on the red strip changes to green
Word list of actions with a left mouse click on the DOWN Arrow and directory stuff with < button which mirrors the icons at the top of each lister
single-key hotkeys? exactly the same as in dopus4, edit your functions (button bank, toolbar, menus etc.) and under the flags gadget is a key gadget, just click in it and press the key you want to use.
As for the extra text field... try turning off Extended lister key selection in environment / miscellaneous.
Shift and click on the icon - runs the icon
DOpus5 Magellan 2 Directory folder drawer structure
<pre>
ARexx - Arexx scripts .rexx and .dopus5 to perform tasks
Buttons -
Commands -
Desktop -
Environment - two environment files bundled:
default gets loaded if you run DOpus as a normal app
workbench gets loaded if you run DOpus as a WB Replacement (with LoadDB on startup)
Filetypes -
Groups -
Icons -
Images -
Modules - compiled tasks
Settings -
Sounds -
Themes -
WBStartup - Use this if standard SYS:WBStartup gives cannot wait error messages
</pre>
Settings -> Environment -> Display -> Workbench (Use)
*Settings -> Clock (add to title bar as well as the date)
*Toolbar -> Editor (Right Win Key together with 1) for Copy, Move, Delete, etc above the Device List
*Menu -> (Right Win Key together with 2)
*Buttons -> Editor (Right Win Key together with 3)
*Settings -> Environment (Right Win key together with 4) for Backgrounds, etc
*File Types -> (Right Win key together with 5)
*User Menus -> (Right Win key together with 6)
*Hotkeys -> Setup for quick shortcut keypresses (Right Win Key together with 7)
*Scripts -> (Right Win key together with 8)
*Icon Positioning -> (Right Win key together with 9)
Each Dopus5 theme are stored in a separate directory, named appropriately, which contains further sub directories
* Font (amiga bitmap fonts)
* Screens (jpg or any picture supported by datatypes but not animations)
* Sounds (wav but not iff 8svx )
* Icons (png newicons glowicons )
* Patterns (iff jpg png )
Just use wildcards in background filenames and you get a different picture every reboot
For example, configure in Environment -> Backgrounds -> Desktop something like this:
<pre>
Work:Pictures/Backgrounds/#?
...or
Work:Pictures/back#?.iff
...etc...
</pre>
[https://aminet.net/util/dopus arcdir and themes]
If you want to change the backdrop pic after a period of time, paste below into a text file called dopusrandbg.rexx and place in DOPus5:ARexx
<pre>
/* Changes DOpus background image forever
Start with:
Run >NIL: RX dopusrandbg.rexx
*/
if ~show("L", "rexxsupport.library") then do
if ~addlib("rexxsupport.library", 0, -30,0) then exit 10
end
/* Configure these two lines for your needs: */
minutes=1
picpath="Work:Pics/#?.iff"
address DOPUS.1
do forever
call delay 3000*minutes
dopus set background '"'picpath'"' desktop center custom
dopus refresh background custom
end
</pre>
If you don't want to use/open rexxsupport.library just for DELAY() then use the DOS Wait command
<pre>
/* random diropus backdrop changer */
/* by paul trauth, 1999 */
/* to do: non-repeatable randomness? */
options results
parse arg path
address DOPUS.1
/* get current backdrop pattern so it actually changes */
dopus query background desktop custom
currentpatt=result
lastslash=lastpos('/',currentpatt)
currentpatt=substr(currentpatt,lastslash+1,(pos('"',currentpatt,2)-lastslash-1))
dir=showdir(path,'FILE','/')
num=0
do while dir~=''
where=pos('/',dir)
if where>0 then do
file=left(dir,where-1)
dir=right(dir,length(dir)-where)
end
else do
file=dir
dir=''
end
if left(file,1) ~='.' & file~=currentpatt then
do
pics.num=file
num=num+1
end
end
which=random(0,num-1,time(s))
newbg='"'||path||'/'||pics.which||'"'
dopus set background newbg desktop tile precision exact
dopus set background on
dopus refresh background
</pre>
Clock format commands available are defined by locale. They are:
<pre>
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
</pre>
like %a %d-%b-%y %H:%M or
A WB ARexx interface, you could enter a cli command as a menu item to open a WB drawer like this...
RX "address WORKBENCH;WINDOW 'device:drawer' OPEN"
Where device:drawer is replaced by the path of the drawer to open.
The ARexx script would be capable to manage such a task but this would work only with those program that support ARexx
<pre>
dopus addappicon
dopus addtrap
dopus back
dopus checkdesktop
dopus clear
dopus command
dopus desktoppopup
dopus error
dopus front
dopus getdesktop
dopus getfiletype
dopus getstring
dopus matchdesktop
dopus progress
dopus query background, font, palette, pens
dopus read
dopus refresh all, background, icons, lister
dopus remappicon
dopus remtrap
dopus request
dopus script
dopus screen
dopus send
dopus set background, font, palette, pens
dopus setappicon
dopus version
</pre>
<pre>
lister add
lister addstem
lister copy
lister clear value
lister clearcaches
lister close
lister empty
lister findcache
lister getstring
lister iconify
lister new
lister query active all, dest source
lister query abort, busy, case, dirs, display, entries, entry, files, flags, handler, header, hide
lister query label, lock, mode, namelength, numdirs, numentries, numfiles, numseldirs, numselfiles
lister query path, proc, position, seldirs, selentries, selfiles, separate, show, sort,
lister query title, toolbar, value, visible, window
lister read
lister refresh
lister reload
lister remove
lister request
lister set busy, case, dest, display, field, flags, handler, header, hide, label, lock, mode
lister set namelength, newprogress, off, path, position, progress, separate, show, sort, source
lister set title, toolbar, value, variable
lister select
lister wait
</pre>
The '''command''' allows you to call internal DOpus commands from an ARexx script
<pre>
command all
command wait copy
command read s:startup-sequence
command source 12345 makedir name noicon
</pre>
*SFTP secure encrypted comms over internet using libssh2 and zlib (different protocol to the two below) on port 22
*FTPS secured with https like security on port 21
*FTP not secure and unencrypted protocol over internet on port 21 (should not be used today on the internet but for your own server)
===Wanderer ===
Wanderer prefs in the prefs drawer - Appearance tab and Workbench icon allows backgrounds (wallpapers) icon text sizes, colors, etc but cannot use #? or *.* in the backgrounds file entry to randomly choose pictures - [https://developers.google.com/speed/webp/docs/riff_container webp riff container] issues with this format but Multiview has none.
Enable the bar, you need to edit the text file ‘statusbar.prefs’. The change is simple: just change “False” to ‘True’.
Prefs/Env-Archive/SYS/Wanderer/statusbar.prefs
===Scalos===
[https://web.archive.org/web/20180922220139/http://scalos.noname.fr/ Scalos] is not an OS replacement, it's a Workbench replacement. It replaces the desktop and graphical file management components.
Scalos is 100% Workbench replacement with most functions working like the original Workbench ones. Undo and Redo available for most window and icon operations. Fully multitasking so every window has its own task. While loading icons, any window function (e.g. Drag&Drop) is available.
24bit color support with window patterns - Unlimited and easily configurable via tooltypes. Optimised backgroundpatterns routine so patterns can be tiled, centred or even scaled to fit into the windows. Live updating window scrolling - Supports middle mouse button panning and drawer (folder) windows can be iconified on the desktop.
Icon imagetypes with all types are supported such as backfill or complement. Configurable surrounding iconborder. Icon support also visually highlights files which are soft-links in the file system. Icon dragging is more stable and far less flickery on graphics cards. Whilst dragging, icons are displayed with text and they can become transparent over anything where they can be dropped.
Single-window lasso mode, with scrolling window contents invoked by dragging mouse with configurable qualifier key. Text icon lasso selection used to ignore "Name column selects text icons" flag. Support for backfilled thumbnail icons, with selectable color and transparency. Added option to always generate square thumbnail icons with preview icons for images - Thumbnails can be permanently saved in icons.
Supports PNG icons with alpha channel and real transparency and displays OS3.5 GlowIcons and are all scalable. Iconborders with variations (normal, shadowed, outlined).
Completely configurable, filetype-specific user-definable popup menus and tooltips. Plugin system to exchange or add features and can enhance the Workbench and make it more configurable.
Filetype plugins to display filetype-specific information. - Currently, EXIF information viewer for JPEG images is included. Plugin included for 100% support of OS3.9 Workbench features. Plugin included for AREXX API compatible to OS3.9 Workbench.
Online update with updater.module
Scalos works also as a Workbench replacement. In this case the 'emulation mode' has to be set by using Scalos' own version of LoadWB and offers
* Scalos uses the Workbench Screen for its windows instead opening a new one
* AppIcon, AppMenuItem, AppWindow functions are redirected to Scalos
* all Programs placed in "WBStartup" should start
* The Screen will be reopened in case of changes in ScreenMode and Palette settings
<pre>
v1.0 (V39.201) - November 1999
v1.1 (V39.212) - December 1999
v1.2b (39.220) - June 6, 2000
v1.2d (39.222) - 2000 (latest public beta executable)
v1.3 (40.7) (beta) - August 2, 2001
v1.3 (40.22) - September 25, 2002
v1.4 (40.32) (beta) March 31, 2005
v1.6 (41.4) - March 27, 2007
v1.7 (41.5) - August 12, 2007
v1.8 (41.6) - March 12, 2009
v1.9 (41.7) (beta) - March 15, 2010
v1.9 (41.8) (RC1) - August 25, 2012 open source
v1.9.2 (41.10) Deadwoods' AROS late 2022 32bit and 64bit build unifying the code base of ` for AROS x86 ABIv0, AROS x86_64 ABIv11 and AROS m68k
</pre>
Distros may have Scalos files under SYS:System/Scalos or Extras:Scalos. Known [https://github.com/deadwood2/AROS/issues/75 bug list],
Certain files like Menu13.prefs, Palette13.prefs, Pattern.prefs and scalos.prefs need to be in SYS:Prefs/Env-Archive/Scalos they can be found in Scalos:Storage/envarc and country drawer
or run the "Scalos Menu" preferences program. Note if already setup with sub-menu entries and then re-save your menu prefs as it will now generate a new/overwrite prefs file called "Menu13.prefs" in "envarc:scalos/". The same is also required for the new Palette prefs update, click 'Save' and a "Palette13.prefs" file will be saved in to "envarc:scalos/" directory.
<pre>
ASSIGN Scalos: SYS:xxx/xxx DEFER
ASSIGN Libs: Scalos:Libs add
;ASSIGN SYS:Devs/Datatypes Scalos:Devs/Datatypes add
Assign Theme: Scalos:Themes/Default_Theme add
Assign Locale: Scalos:Locale add
Protect Scalos:Tools/browse.script s add quiet
Protect Scalos:Tools/OpenShell s add quiet
Protect Scalos:Tools/run.script s add quiet
run Scalos:Tools/LoadWB
;Scalos:Scalos
</pre>
Add the above to SYS:S/startup-sequence or SYS:S/user-startup '''before any Wanderer entries'''
In the prefs drawer (folder) is the big prefs app Scalos_Prefs which covers these user setup areas
<pre>
About Scalos
Paths - should be preset
Startup - WBStartup drawer contents should auto run on each startup
Desktop - edit titlebar, icon layout and in misc, auto leave-out (drag icon to desktop)
Icons -
Drag and Drop -
Windows -
Text Windows - in misc, drawer sorting at start of listing if needed
TrueType Fonts - use Truetype fonts rather than system ones
Miscellaneous -
Plugins - after adding oop/title_clock.plugin %ti %da does not work, maybe needs ASCII .prefs added
Modules - ??
Menu - setup for MainMenu and PopupsMenu with New Menu, RE Name, Key: shortcut, Command Properties
FileTypes - already added def_Project icons and def_Disk (hdd sdd cd dvd etc) support
PopupMenu - tweak how popups appear
Pattern - Wallpaper backgrounds with Type DE, each pattern in the list can be edited, Save as Pattern.pre
Palette - change the color of things , Save as Palette.pre
</pre>
Scalos_Prefs - Pattern - Minimum options to be changed are
*DE Desktop/Background
*SC Screen
*TW Window/TextBackground ie Text listing showing if icon type not recognised
*IW Window/Background ie Icons showing
Workflow - In "Pattern List" tab, select New - choose a picture, highlight in list, click in number box under New button and slide to another number, click on "Defaults" tab and adjust Pattern numbers slider to choose right picture for each of the above options - Click "Pattern List" tab to check eveything is OK and click Save
Pattern List tab on Patterns Page - Allows you to compile a list of pictures (one at a time rather than a whole folder e.g. with #? or *.*), assigning a number Nr to one or more of them for easy reference. Using this number you will be able to assign the pictures to specific windows on the Defaults tab Page. If multiple pictures have the same number, one of the pictures will be chosen randomly. This will allow you to have random desktop pictures, random window backdrops etc.
Defaults tab on Patterns Page - Here you can set the defaults for the background pictures for the Desktop, Screen, Window and/or Text Mode throughout Scalos.
Randomize every time [check box] - Usually Pictures with the same number will be randomly selected as soon as the configuration loads. If this option is set, the picture will be selected as soon as a window with the same number assignment is opened.
*Fit size: The picture will be resized to the dimension of the new window.You *MUST* have set GUIGfx on. asyncron layout: Pictures will be loaded and rendered while the windows opens (Like original Workbench). If this function is 'off', pictures will always be loaded before opening the windows.
*Use friendbitmap : The picture is present twice in memory for best speed. This option has no effect if V43 picture.datatype or GUIGfx are used. Always relayout: If "Fit size" is set, the picture will be scaled everytime the window's dimensions change.
*Randomize everytime: Usually Pictures with the same number will be randomly selected as soon as the If more pictures have the same number, one of them will be chosen randomly.
Patternlist New/Delete : Add a new picture. After that you should assign a number to it. The picture will be rendered as tiles. configuration loads. If this option is set, the picture
Asyncron-Task priority: You can set the CPU priority for the Task if "asyncron layout" is set.
<pre>
Desktop: Number of the Picture for the main window.
Screen: Number of the picture for the Scalos-Screen.
Window: Number of the picture for the Scalos-windows.
TextMode: Number of the picture for the Scalos-windows in Text Mode.
</pre>
Popup Menu preferences fully configurable menus (includes ToolsDaemon and ParM launch apps import), including support for context-sensitive Popup menus configs for top pull down menus for apps, etc.
Workflow - Scalos_Prefs then Menu, New Item, New Command add name at top then in Command Properties e.g. add Workbench and location e.g. DOpus:DOpus4 for apps Command for c apps or Rexx for scripts or Plugin for or AmigaDos for modules
<pre>
DESCRIPTION NAME/A This is the title that is displayed in the top line of any popup menu
INCLUDE NAME/A Name of file to be included. Path can be relative to "Scalos:FileTypes"
POPUPMENU Starts the popup menu description section for this filetype.
</pre>
The following Subcommands are allowed inside popup menus:
<pre>
SUBMENU "NAME/A"
ENDSUBMENU
MENUENTRY "NAME/A,KEY/K,DEFAULTACTION/S"
ENDMENUENTRY
INTERNALCMD "NAME/A"
WBCMD "NAME/A,STACK/K/N,WBARGS/S,PRI=PRIORITY/K/N"
AREXXCMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
CLICMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
ICONWINDOWCMD "NAME/A"
PLUGINCMD
MENUSEPARATOR
ENDPOPUPMENU
TOOLTIP
ENDTOOLTIP
</pre>
<pre>
Starts the tooltip description section for this filetype. The following Subcommands are allowed inside popup menus:
GROUP "ORIENTATION/K"
ENDGROUP
MEMBER "HIDE/K"
ENDMEMBER
HBAR
STRING "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K"
SPACE "SIZE/N/A"
DTIMAGE "FILENAME/A"
</pre>
Each theme drawer (folder) has these further folders
<pre>
About -
Desktop -
FileTrans -
FileType -
Icons -
Menu -
Modules -
PointerIcons -
Prefs -
Sound -
Window -
</pre>
*Plugins
<pre>
devicefilter.plugin
persist.plugin should a crash or reboot occur - next time Scalos started, all windows re-opened
title_clock.plugin add digital clock to title see more below
title_envvar.plugin %ev, which can be used to display the value (a string) of the variable in the titlebar
title_freepens.plugin
volumegauge.plugin
wb39.plugin
wbrexx.plugin plugin adds a Workbench 3.5+ compatible AREXX interface to Scalos internals
xtwindows.plugin left or right ALT or left or right SHIFT keys when open/close windows
filetype.plugin then run FileTypes-prefs and customize the filetypes (eg import from a DefIcons-brainfile)
menu.plugin
</pre>
*Modules - delete, empty_trashcan, execute, find, format_disk, information, iconproperties, newdrawer, reboot, rename, systeminfo, windowproperties
*Tools - scripts like LoadWB, quit.rexx, open_volume.rexx,
In Scalos_Prefs->Filetype->Recognition you can define the filetypes and on "Action" you define specific context menu for all filetypes defined in recognition (similar to magellan)
there is the same you must show all first (list is only limited) so you created a file type AAABBB, you need to have def_AAABBB icon
Associating files with "Scalos_FileTypes" is very simple, practically it is very similar to Dopus4, first you create the Def_icons to assign to the file type (will be seen automatically ), then run "Scalos_FileTypes" you add the extension, fill in the descriptor (MATCH or PATTERN etc..) and save
then you create an appropriate entry in the list and rename it, if def icon exists it is shown. Below you can define how files are identified. Use "pattern", similar to magellan to identify file by ending. Then you click on the shown icon and define in it what program is used when you double-klick on it and save it. On the tab action you can define popup menu for it.
defined all archive types from XAD in "filetypes". If you change to "action" and click on "archive" you can define the context menu that is shown if you do not define a specific context menu for a filetype
Reset to Default in Scalos_Prefs resets all settings so '''BEWARE'''
<pre>
The Scalos desktop screen titlebar may be configured using the main Scalos Preference program. This oop/time_clock plugin adds some additional placeholders:
%ti, displays the current time in the default Locale format. e.g. "10:43:37"
%da, displays the date in the default Locale format. e.g. "Saturday 14 July 2001"
Using the supplied prefs program for the plugin, or editing the ASCII file ENVARC:Scalos/title_clock.prefs you can use the following standard Amiga Locale values to change the formatting
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%C - same as "%a %b %e %T %Z %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%n - insert a linefeed
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%t - insert a tab character
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
like %d %m %y or %a %d %B %Y %p
</pre>
Shutdown -> right mouse button Scalos, About, Reboot, Shutdown
ToolTypes can be added to the Scalos.info icon like
*SCALOS_PATTERNNO=<number> : background image matching the number
*SCALOS_NOTEXT : The Icon will be drawn without Text.
*SCALOS_NODRAG : The Icon will not be draggable. Its position will be fixed.
*Module iconproperties - Added SCALOS_BROWSERMODE tooltype support
runcommand parameters... in which case:
<pre>
%p = parameters
%w = directory path
%d = device-name
%% = literal percentage token
</pre>
With the help of the wbrexx.plugin Scalos gains support for more of the compatible arexx API
If an arexx command produces an error you will find the error code placed in the WORKBENCH.LASTERROR variable.
ACTIVATEWINDOW
<pre>
/* Activate the root window */
ADDRESS workbench
ACTIVATEWINDOW root
/* Activate the "Work:" partition's window if already open*/
ACTIVATEWINDOW "Work:"
</pre>
CHANGEWINDOW
<pre>
/* Change the root window; move it to position 10,30. * and change its size to 200100 pixels */
ADDRESS workbench
CHANGEWINDOW root LEFTEDGE 10 TOPEDGE 30 WIDTH 200 HEIGHT 100
/* Change the currently active window */
CHANGEWINDOW active 20 40 200 100
</pre>
Most of Scalos' issue are due to the flexibility of its' user configuring nature but if
The sort menu plugin needs to be ported from ASM to C.
IIRC Scalos has a command line option to fully replace Workbench/Wanderer.
The Theme: assign is used by both Wanderer and Scalos but I didn't have any problems using both at the same time.
The Program will be started from the Shell.
If "WB Args" is set, with the Argument "%p" will be replaced by the path of the activated Icons. The Program will started with the specified Stack value.
IconWindow: Scalos opens the window of the specified path.
PlugIn: Starts a Scalos Menu-PlugIn.
If a Menu Item with empty name is specified, Scalos displays a separator line.
It's possible to Drag&Drop an Icon in the Configuration Window. All values will be set accordingly. Entries may be dragged across the list.
Mac-like selection : This function activates a multiselection method used on MacOS or Win95. Don't have to hold down shift to drag them. Clicking on an already activated icon will
not deselect all other icons.
MMB move: The window contents may be moved using the middle mouse button.
WindowPopup title only: PopupMenu for windows can be opened only on window's title bars.
FullBench: Screen-Titles removed and Main Window set Full Size.
Scalos Prefs. Go to Settings->Scalos->Prefs and then the Misc section. Remove the tick against Full Bench. If you've enabled it, the titlebar will disappear when you select backdrop.
Default Icons saveable : The icons which Scalos generates if "show all files" is enabled, can now be saved
using "snapshot" menu option. load DefDisk first : Try to read the icons first from the DefIcons Path before using disk info.
Hide hidden files : If this function is activated all files or directories where the "hide" flag is set will not be shown.
Many of my Icons display more than once on the screen, while on the workbench all seems ok.
The Workbench filters double displayed icons, Scalos does not. Solution: please edit the ".backdrop" file and clear double lines.
Background images not scaled. GUIGfx option not set or guigfx.library and/or render.library not installed.
If working with CD's causes crashs or Scalos doesn't work correctly.
Most Filesystems doesn't support the ExAll function correctly. Disable "Use ExAll" in Scalos prefs.
Scalos doesn't start any program in the WBStartup. WBStartup Path may be set wrongly or Scalos was not started in Emulation Mode (LoadWB etc)
Some programs will not startup with error message "has not returned, wait some more"? and "unable to open your tool"
need a def_icon with the same name predefined, then create an appropriate entry in the list and rename it, if def icon exists it is shown. Below this can define how files are identified.
* either "pattern", similar to magellan to identify file by ending
* or
Then click on the shown icon and define in it what program is used when you double-click on it and save it. On the tab action you can define popup menu for it. All in all handling is of course different to magellan but can do similar
For the RAM Icon, to obtain this you have only to copy the icon in the Icon Path as "RAM.info" or "Ram Disk.info". All functions will automatically be performed
sometimes cut into half or quarters when scrolled off screen or drawers moved - settings issue probably
Sometimes leaves initial drawer window imprint on desktop when moved - settings issue
Scalos AROS released a [https://github.com/deadwood2/contrib/tree/master/scalos new build V2022-07-21] with the following changes noted:
<pre>
Fixed:
Numerous crashes when working on 64-bit with 64-bit heap
Wrong background color of Scalos logo on Scalos splash window
Backgroung image of Scalos splash window and Scalos About window is not visible
Icon labels on desktop and in drawer windows are displayed using Topaz instead of Arial font
Font.prefs are not being loaded on 64-bit
Font.prefs are being wrongly saved on 64-bit
scalos.prefs are not being loaded on x86 and x86_64, scalos is using always default preference
scalos.prefs are being saved on x86 and x86_64 in format not compatible with m68k
NewPopupmenu.prefs is wrongly written
Plugins are not loading at Scalos startup
wbrexx.plugin is crashing at startup on 64-bit
Multiple controls missing on Scalos Prefs/Icons page
System crash when clicking on def icon image on FileTypes Prefs/Recognition page
Status bar, control bar, buttons sometimes don't have images displayed
Buttons in Scalos About window have white corners rendered where they should be transparent
Crash when leaving out an icon
Crash when adding a User-defined Button to Control bar without setting it's properties in Scalos Prefs
Crash when removing any button from Control bar in Scalos Prefs
Scalos Prefs allows editing TTEngine font properties when TTEngine is not present causing crash in Icons/Labels and Text Windows/Fonts pages
deficons.prefs are not being loaded on x86 and x86_64
Reset to default in FileType Prefs and Save does not save preferences
Won't fix:
Scrollbars visible on titles of TrueType Fonts, PopupMenu, Menu, FileTypes, Pallette and Pattern pages of Scalos Preferences
Not fixed:
Wrong rendering on DualPNG icons
Refreshing drawer windows is slow
Starting Prefs/Locale or Prefs/Input from Scalos causes other preferences to fail
Desktop wallpaper is damaged where Splay window was displayed
When started from Wanderer, after saving Scalos Prefs, reload does not re-open main Scalos window
Difference in behavior between Cleanup from popup menu and Cleanup from top menu - possibly due to missing plugin, check Cleanup association in Menu Prefs
</pre>
===DOpus 4 Directory Opus===
Copy DOpus4 app to WBStartup directory folder so it starts on boot up each time
Another method is add the below to the bottom of the user-startup script in SYS:S drawer/directory
<pre>
run DOPUS:DirectoryOpus -i >NIL
</pre>
makes DOpus starts up in Iconified state at the top of Wanderer's screen. Left click on this to highlight and right mouse click to open.
Just click on the sides of either outer edges of DOpus windows and it will display the parent device/volume list.
DOpus4 saves it features in a PROGDIR:s/DirectoryOpus.CFG file which can be edited to suit anyones' needs, '''C''' bottom right button in DOpus4 and by reading the [https://arosarchives.os4depot.net/index.php?function=browse&cat=utility/filetool Dopus4 guide Manual and Arexx calls].
*[https://www.youtube.com/watch?v=DCyXDs8baSE Pt1 Introduction]
*[https://www.youtube.com/watch?v=7fiVmopiK9I Pt2 Dopus Config]
*[]
*[]
*Button little rectangle with name inside
*Bank vertical stack of buttons
Buttons
*Workbench app {f} i.e. first use {F} for all selected items with app
*AmigaDos c type apps with arguments after
*Arexx
*Command c type apps with no arguments after
Flags (most used)
*CD Destination to extract etc
*Do all files
*Output window
*Run asynchronously
*Workbench to front
*Buffer above 100000 for 64bit
Filetypes
Defines how certain files are handled like '''default tool'''
Screen
Fonts, set each element to any font
Screenmode, Workbench Use (same screen like Windows), Workbench clone (like Linux workspaces)
System
Shell startup, set to SYS:s/shell-startup
===BoingIconBar===
User chooses the apps to add to the dock at the centre bottom of the screen but has to be done manually, please use Save afterwards
Or easier edit the text file of SYS:Prefs/Env-Archive/iconbar.prefs and save
<pre>
BOING_PREFS
;Tools
SYS:System/Shell
SYS:Tools/DOpus4/DOpus4
SYS:Utilities/Editor
SYS:System/SysMon
SYS:System/Scout
Work:Extras/Internet/OWB/OWB
Work:Extras/Graphics/Lunapaint
Work:Extras/Graphics/ZunePaint
AROS:Tools/MPlayer/MPlayer
Extras:Internet/AmiFox/AmiFox
RAM Disk:Amelinium/Amelinium
</pre>
right mouse click on bottom edge of screen where boingiconbar shows - select settings which opens BoingIconBar Preferences to add apps
If no dock showing Add, to add apps click Add Program and search for the executable
another method is to drag icons to ends of the bar and move them on the Bar using the Prefs/BoingIconBar
===AmiStart===
On 32bit PCs only - auto generates the apps menu but scans the drive each time - AmiStart can choose apps you are not interested
* how to disable annoying zune/mui 'bubbles'?
try a right-click on AmiStart and release on Global settings. Then click on the bubbles gadget. Move the Show Bubbles slider all the way to the left.
===Fonts===
Install the #?.ttf files to SYS:Fonts/TrueType. Use SYS:System/FTManager to "Install Font" each #?.ttf file which will generate associated #?.otag and #?.font in SYS:Fonts. Use SYS:Prefs/Fonts to change system fonts and SYS:Prefs/Zune to change others.
To achieve our goal we will use the Setup Locale, Input, Zune and Fonts, as well as The FTManager.
Begin
The first step you should do is to get the system to know that we speak and write in another language. What you need to do is to open the setup program and choose Locale country, and list "preferred languages" to put it first and then English. If you want the tab "Time Zone" and select city of residence to set the clock correctly. Of course we save our changes and continue opening the setup program Input. This sets the keyboard language as our beginning. When the language layout was created there was no option to switch to Aros keyboard (layout switching), so to write in the language you had to hold down Alt, something you encounter in other functions. This time working with the team of Aros to create a new keyboard layout to replace the old so we can get rid of the button Alt. For now though let only selected this layout and do not turn the switch on the keyboard.
Custom Keyboard Layout
[http://repo.or.cz/w/AROS.git/tree/HEAD:/workbench/devs/keymaps keymaps are in place but unfortunately when they are not, then indeed things become a bit 'low-level' as it involves redefining some tables with values that match your keyboards]
only need to add your compiled table as new keymap.
So taking a little peek here shows that it should be possible to compile using
gcc -opc105_tr pc_105.c -nostdlib
where the pc105_gr/pc_105.c needs to be replaced with your own adjusted keymapname/c-file
[https://en.wikiversity.org/wiki/Enabling_Greek_Characters_on_Your_Keyboard General overview of Greek letters on keyboards]
Installing fonts
*[http://aminet.net/package/util/wb/EPAGrWb System jaggy]
*Outline resizable .font .otag
In this step you need to download some fonts that can support the encoding in our system. The easiest way is to run the script "Download Fonts" you'll find in the folder OWB. This script downloads from the Internet, and unpacks some fonts for OWB web browser, which is placed under the folder Fonts:TrueType. But as these can only be used by OWB and not the system, which unfortunately does not see. To make them available to the rest of the system, open the program FTManager, you will find the folder AROS: System /. From there select the field "Codepage" option "ISO-8859-7" and list the font "Arial" and "Regular" form in which you must double-click with the mouse. In the window that appears, select the bottom right the checkbox "Anti-aliasing" button and then "Install". Immediately folder Fonts: created files "arialregular.font" and "arialregular.otag", which are necessary in order to see the system font. Do the same steps if you wish for other fonts.
Final stages
After completing the above, open the folder AROS: Prefs / and run the program settings Fonts. In the new window, select the fields "Icons" and "Screen" as the font "ArialRegular" to the size you want. In the field "System" to give "s_courier", which, however, because it is not True Type Font support Antialising, and may seem a little broken. You can also use the CourierNew, if you have installed the above procedure. After you save the changes and open the Zune program settings. In this set the "ArialRegular" font fields in tabs "Windows" and "Groups", and save the changes. Reboot the system. To make sure that the above worked properly run NoWinED, which you will find under the folder AROS: Tools /. If that everything is working correctly you will see the menu and the settings window with Greek letters. You can also write in the language using the button Alt. Second program that you can try, which is fully localized, is WookieChat, which you will find in the folder AROS: Extras / Networking. And in this place all the menu and settings window works.
===Windows===
*Intuition
The window you position and resize, you right click on that windows title bar and in the dropdown menu you snapshot from there. Right click to show menu -> Window -> Snapshot Windows or All but it will NOT work if that folder has no icon (e.g. Disk.nfo) attached to it. You need a folder icon. The window information gets saved in it.
As for maximising the window using a shortcut key - Alt and up arrow key
The AROS-Shell windows can be moved, resized by editing sys:s/startup-sequence
<pre>
; run shell
run QUIET c:newshell >NIL:
</pre>
; slimmer right aros the screen
run QUIET c:newshell con:0/150//300/ >NIL:
; top right corner scr-x scr-y win-x win-y
run QUIET c:newshell con:600/150//300/ >NIL:
*EdgeSnap
Commodity EdgeSnap allows resize and position windows on your screen by dragging them to the edges but not corners of the screen and/or other windows
EdgeSnap Prefs (once pressed Use button) lets you arrange windows but not different applications in layouts half (left or right) or full size (top) and choose to adjust the border padding
There is outline to show shape taken to aid placement and space available
*Zune - AROS version of MUI
Magic Menu type functionality is implemented in IControl preferences editor: in the frame called Menus, switch type from Pull-Down to Pop-Up and/or iControl just tick the sticky menu option.
Windows outside screens causing a problem either uncheck "Offscreen move" for windows in IControl prefs editor. Or use FKey commodity and define two key shortcuts:
* the first using the command "cycle windows" (for example ALT TAB);
* the second using the command "rescue window" (for example ALT F5).
Now you can cycle windows until the one you want to rescue, and then "rescue" it: it will move back inside your screen.
How to save the window size on wanderer (snapshot all, snapshot windows)
Same for icon position on wanderer, can't save the position. Icon position cannot be saved yet, but you should be able to save the window position and size. sys:prefs - wanderer icon has option to save window size on exit but just for dh0. To get saving working on (DH1: Extras:) partitions try deleting the dh1 disk.info file, then reboot. The system should create a new dh1 icon.
* how to set up permanently 'view all files'?
As for viewing all files, removing disk.info for that disk did the job
* how to list and kill processes (xkill would be useful) ?
sys:Extras/System/Scout can kill apps
sys:Tools/Commodities/Exchange can remove available commodities
* how to restore 'go up' button in wanderer window? (it doesn't show up anymore).
If you're using Icaros, go to the theme prefs and make sure that decoration is checked. Also, some themes do not use a parent button, so try another theme. You may have to restart Aros before the theme will change.
* Is it really safe to turn off (hardware button) computer at any time (worried about USB hard disk)
yes you can turn off the computer IF none of the drives are in progress (i.e. writing). Best to use Wanderer menu option Quit otherwise
===Say narrator===
Say "Hello World" for a simple robotic voice
SPEAK: is a write-only DOS device for text-to-speech abbreviated as tts.
To check if available, type assign into the shell and at the bottom in the Devices: section should be SPEAK
Examples of use
<pre>
Copy S:Startup-Sequence SPEAK:
Echo "Hello" >SPEAK:M/R/S150/P110
Echo "DH1 EH0 L OW1" >SPEAK:A1
</pre>
Classic options are M/F, R/N, S<rate>, P<pitch>, O0/O1, A0/A1, and D0/D1. O1 recognizes lines beginning with OPT/ as option changes. A1 treats input as narrator phonemes.
Long options select a speech engine:
Echo "Hello" >SPEAK:ENGINE=narrator/VOICE=female/STYLE=natural/LANGUAGE=en-US
Supported selectors are ENGINE=, VOICE=, STYLE=, and LANGUAGE=. Values are case-sensitive backend identifiers. ENGINE=DEFAULT selects the system default. Narrator-compatible selectors continue through the classic translator/narrator pair. Other engines use speech.device. Direct phonemes require a narrator-compatible selection.
===Printing===
This needs further [http://www.aminet.net/package/docs/help/PrinterGuide drivers written], we have postscript and write to file support only
;There are no individual drivers yet for HP's Photosmart, EPSON's EPL, CANON's, Lexmark, CUPS PPD, etc.
*Postscript
Best to set Printer Prefs in the Prefs drawer to print-to-file or parallel/USB port
Save document in postscript or convert picture/text to postscript
Print using compatible Postscript printer
*printer is simply not accepting IPP connections at the moment.
Please try the following steps:
Open the printer web interface in a browser:
http://192.168.1.x/
Look for the network or protocol settings.
Enable IPP / Internet Printing Protocol.
Make sure TCP port 631 is open/enabled.
Save the settings and reboot the printer if the web interface asks for it.
ipp://192.168.1.xx:631/ipp/print
ipp://192.168.1.xxx:631/ipp/
===Files===
====File endings and datatypes====
* Check if the file has his own .info icon file with a tool set to open it. IIRC this has higher priority over the def_XYZ.info file association.
* In ENVARC:SYS/def_Text.info or whatever def_ file needs changing, use Wanderer's menu Icon -> Information and change the def_XYZ.info there. If you're on ABIv0 and want it to be applied immediately, you might have to copy it to ENV:SYS/ (or to reboot).
* Identifying file types by file ending is only a fallback. Far better it is to search for magic words, for flac files this would be "flaC" according to this [http://flac.sourceforge.net/documentation_format_overview.html documentation].
For instance, to open PDFs with arospdf not localised in the default drawer of Icaros (Work:Extras/Applications/arospdf) but localised in a custom drawer in AROS. The default tools are defined in the icons in sys:prefs/env-archive/sys e.g. def_PDF.
File type identification is done by datatype descriptors which you can find in Devs/Datatypes. The AROS build system has a tool which creates such datatype descriptors.
'''Changing of default tools of existing icons is easy as shown above. Adding of new file types is not hard, but needs knowledge of the AROS build system.'''
The enduser way would be to download the attached file, which contained two executables:
1) createdtdesc, to make a new datatype description
2) examinedtdesc, to read/show existing datatype descriptions
use 2 to get an idea on how it things are currently done in aros by providing this executable a file from the drawer sys:devs/datatypes/ (alternatively you can find the original .dtd files here).
use 1 to make your new datatype. Use the accompanied FORMAT file (also here) to read how to make your own datatype descriptor. use 2 to get hints from other datatype descriptors.
Note:
When creating a new descriptor would advise against using the pattern property, but instead use the default pattern of #? and create a Mask that matches your filetype. This requires some research in order to discover how your filetype can be recognized properly. Of course with making something like a descriptor for an ascii textfile, you would fallback to using the pattern (e.g. #?.text as the filetype cannot be determined easily otherwise).
<pre >
# name - choose wisely and informative. also used for icon's name.
# version - choose as you like as long as it complies with version rules
# basename - the 'root' datatype class. be aware that e.g. it can influence behaviour. for example when choosing binary and using tool multiview in project icon, the file will be viewed as binary file (choosing sound would tell mulitview to view the file as a soundfile). So this can influence the underlying tool being used. Could become messy if users started to modify the tool manually.
# pattern - This is the file pattern match e.g. #?.text
# Mask - A mask to identify the file. Requires knowledge of the actual file structure. For example 'M' 'Z' for an msdos executable.
# GroupdID - not supported (AROS native) files - use syst as that would be the least intrusive in case an AROS tool/program tries to load such datatyped file.
# ID - In your case, the first four characters of the name at subchapter 1 (in lower case) (or less if name is shorter).
# flags - How the mask needs to be interpreted. In your case would be mostly DTF_BINARY in combination with (wanted or not) DTF_CASE (to tell if mask used letters are case sensitive or not)
# priority - the priority of how the type is handled so that on datatype could have precedence over another? In any case, document tells it to be mostly 0.
</pre >
Now that you know each field and what it does (more or less), you write this fields in a text file for your own invented datatype, save it and create the actual dt with the tool in 1. in the end the created dt must reside in sys:devs/datatypes/ drawer.
Then you would create a default icon in sys:prefs/Env-archive/SYS drawer. Don't forget to reboot or copy .info file to ram:env/sys in order to test. also don't forget to set which tool to start f.e. c:lx or dh4:emulators/mycoolemulator
To test, open Wanderer then show all files and doubleclick on a file of type you just created. Alternatively you could use the 'open' command from shell (with file of datatype you just created as parameter).
And as a last note. it would perhaps be welcome to have a program like xicon and/or runprglist for AROS (unfortunately both without source, but something similar could be created for AROS).
Sounds complicated ?
Perhaps... but OS like windows needs a complete registry to be able to do things like this. And yes, i am aware windows has gui tools that does it (more or less) for you (by manipulating the registry). Same could be done for AROS (without integrating a registry in AROS that is ).
Would that suffice ?
red1+2: typos, reformatting.
disclaimer: please note that using these tools can screw up your currently installed support for datatypes when used incorrectly. Do not use if you do not understand what you are doing. Use at own risk.
==Network Connection==
AROS currently only has one real choice for TCP/IP networking - AROSTCP. This is a port of the AmiTCP package from AmigaOS (TM), with a number of enhancements/fixes from AROS developers.
===Wired===
Use Network Prefs to setup
=====IPv6=====
Some support
128bit IPv6 address packet
<pre>
Local FD::/8
Global 2000::/3
64:ff9b::/96
</pre>
NAT64 translates IPv6 to IPv4
DNS64
OS routing works with
<pre>
MacOS Ventura
Windows 11 with cloud account
Ubuntu Jammy Jellyfish
Android 10 (block google dns)
</pre>
====IPv4====
The top half of the IPv4 Configuration tab on the Network Prefs deals with the network card/USB and the lower half the router part.
[[File:AROS Wanderer Network Prefs DHCP.png|thumb|DHCP Settings]]
'''Upper part of IPv4 tab'''
* Click Add on the top right of the Prefs which opens a window called '''Interface'''
* Enter Name as net0 (but can be anything as long as it is consistently used in other sections)
* check mark on Active
* select device to be used using the '''right hand-side gadget''' of the box where the device name will go
* set Unit to 0
* IP Mode is default set to '''Get address from DHCP'''
* IP Mode set to Manual if DHCP does not work automatically
From the shell CLI, ifconfig -a
Under net0: section, inet starting 192.168.x.xxx
* inet or '''Address''' of network card
* netmask convert to decimal so 0x'''ffffff7f''' becomes 255.255.255.247 which is used to adjust the above '''Address''' into
* broadcast 192.168.xxx.xxx
click OK
[[File:AROS Wanderer Network Prefs Manual.png|thumb|Manual Settings]]
'''Lower part of IPv4 tab'''
* IP Mode Get address from DHCP (default)
* or changing to Manual if automatic DHCP set up does not work
* '''Gateway''' (Router Internal LAN-IP) (Default Route) = 192.168.0.1 (D-Link Netgear), 192.168.1.1 (Linksys 3com), 192.168.2.1 (SMC Microsoft), 192.168.1.254 (Belkin), 192.168.123.254 (USRobotics) else check with your router manual
* first DNS = use 208.67.222.222 (opendns) or Gateway number above (to test web browser access to router) or 212.50.160.100 (google) i.e. or whatever your ISP needs you to set
* second DNS = use 208.67.220.220 (opendns) or Gateway number above (to test web browser access to router) or 213.249.130.100 (google) i.e. or whatever your ISP needs you to set
* At the bottom of IPv4 tab, check mark the '''Start networking during system boot''' option
* Save and reboot (sometimes Network restart fails, so reboot every time to be sure)
'''an alternative way''' to AROS ifconfig -a, other OSs have similar for the same internet connection. Another connection will have different settings.
e.g. From [http://www.ncsu.edu/resnet/windows/ipconfig/ Windows], '''ipconfig /all'''
and note down the IP, subnet mask, default gateway, and DNS servers values and put these values in "manually" into AROS Network prefs.
e.g. From Linux via dhcp router have a look at etc./dhcpc/dhcpcd-eth0.info
* for manual input look at /etc/networks (IP or Gateway) and /etc/resolv.conf (DNS)
Please note that all in one routers (wired+wireless) or separate routers may need different settings
IPv4 involves routing (192,168.x.x), firewall, NAT
===Wireless===
You may have a Wifi Prefs to use for wireless setup
[[File:MyArosWirelessSetup.png|thumb|Setting up]]
[[File:MyArosWirelessTCP.png|thumb|Shell commands to work out what is happening]]
We must first make certain you have a Atheros 5k chip inside acting as the wireless wifi option. Open PCITool in Tools directory. Down left hand side are a series of numbers 0.00.0 etc. Click on some at the bottom and hopefully one of them will say Atheros AR5??? or AR242?.
or a Realtek RTL8187B, we can check using Prefs/Trident as this one is USB based
There are many similarities with the above Wired set up so please read the above section as well
* open Network/Prefs
* In '''IPv4 Configuration''' tab - click Add - enter net0 / active tick / #?.device / Unit 0 / IP Mode = manual (important if default DHCP does not work automatically)
Make sure that any extra network names (e.g. eth1 or net1) should be deleted. If net0 already st previously, change net0 so that it shows associated with the appropriate device name like atheros5000.device or realtek8180.device. Having two entries here will cause sub-net problems.
* Go to '''Wireless''' tab and click on "Add" button.
* Insert network name (SSID your wireless network name use wirelessmanager to get it), select right "encyption" that is most likely "WPA".
* Key Type set as "Passphrase". i.e. type in your password for your router (aka access key).
* Unselect (no tick) "hidden" if it is selected, then apply. You may have to tick it if wireless does not work.
* Finally, Save and '''reboot'''.
For the best chance of success, set networking to start at boot, and then reboot with the USB adapter plugged in.
===USB Ethernet===
Open SYS:Prefs/Network and in the IPv4 Configuration tag (top table covers your usb stick)
* click Add button
* set Name as net0
* Tick Active box
* enter the usb-ethernet.device e.g. dm9601eth.device, usbpegasus.device or usbasixeth.device use SYS:c/devlist, '''Scout''' or trident prefs to get the correct spelling
* set Unit to 0 (which is usual but check the messages from the bottom of the Trident prefs whilst plugging the device in to determine the unit number otherwise)
* IP Mode is set to Get address from DHCP (make sure your router is set right for that)
'''or manual'''
* IP Address of network card, i.e. 192.168.0.xx or 192.168.1.xx (xx being greater than 1)
* Subnet netmask = 255.255.255.0
* click OK
There can be sometimes be boot failures when using USB ethernet - plug the USB device in after boot and save the network prefs to make it work again.
Lower part of IPv4 tab covers the router information
* IP Mode Get address from DHCP
'''or if manual settings'''
* Gateway (IP Address of router) = usually 192.168.0.1 or 192.168.1.1 but see router manual to make sure.
* first DNS = use 8.8.8.8, 208.67.222.222 (opendns) or 212.50.160.100
* second DNS = use 8.8.4.4, 208.67.220.220 (opendns) or 213.249.130.100
===USB Tethering via Android smartphone===
Go to AROS Network Prefs (IPv4 configuration tab) and write type in "usbrndis.device" in the "device" textfield of "Interface" sub-window, which appears when you add a new device (or modify an existing one). Select "Start Network during system boot" and saved the configuration, the Connection is immediate no reboot is needed.<br>
usbrndis.device is a resident device (virtually always there) in fact, a driver is not present in DEVS:Networks <br><br>
Plug in USB cable, go to Android settings and enable "USB Tethering" <br>
A reboot should not be necessary.
When restarting AROS, the Smartphone deactivates the connection and to access the network again have to reactivate it before starting the browser.
===Solving Issues===
[[File:MyArosTCP.png|thumb|Aros network setup diagnostics - why does it not work?]]
* In Network Preferences, have '''only one''' item in the IPv4 Configuration tab
* If using manual settings, make sure all numbers are correct, especially for IP address of the card/usb (changing the last number in chain of four)
* For any USB based networking, it is often necessary to save in Prefs/Network, reboot AROS and network support can begin
* For wired, make sure that the LAN-cable is plugged in before starting the computer
* If wireless, try getting closer to the router.
* Switch off the encryption option from your router then try wifi, if successful then your ip/dns is ok. If not then your ip/dns settings are most probably wrong or need to use one or more opendns numbers
* Replace detachable wireless antenna (best wireless option to buy if you can) with a stronger antenna ie. 5 dBi or 7 dBi
* Try with another computer/laptop/machine
Program Error C:WirelessManager
* Test with another OS
* Check that Wifi works before changeover (if possible)
* Check that socket and card are working
* Check if card is too new for laptop (date code on card MMYY blue askey date 2005-2007 etc)
Are you connecting with the Router ?
Check with protection off e.g. wps and wep to see if it makes a difference.
For USB wireless - stopping and starting may be needed...
<pre>
; $VER: AROSTCP-startnet 1.0 (01/08/06)
; AROSTCP-startnet (c) The AROS Dev Team.
;
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
; stop and restart
execute "sys:system/network/AROSTCP/s/stopnet"
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
run <NIL: >NIL: wirelessmanager realtek8180.device
</pre>
What IRQ number is assigned to the device? You can check with Tools/PCITool?
It's possible the BIOS hasn't set the right IRQ number. If you have a Linux CD/DVD handy, could you check if it boots with the options "acpi=off noapic nolapic"?
If the following does nothing, this will help us figure out why networking doesn't start automatically at boot
open a shell and run the following commands:
<pre>
echo ${AROSTCP/AutoRun}
echo ${AROSTCP/WirelessAutoRun}
echo ${AROSTCP/WirelessDevice}
</pre>
Please report the output, typically it will look like this
# True (explanation this variable is related to the "Start networking during system boot" checkbox in network prefs)
# True ()
# Devs:networks/atheros5000.device unit 0
If there's a problem with the AROSTCP package. What's the output of this?
ENV:sys/packages/AROSTCP
should return a string = Sys:System/Network/AROSTCP
By the way, a quicker way to check networking is working would be to run some shell commands such as:
<pre>
ping www.google.com
ifconfig net0
</pre>
The best way to list the available networks and diagnose / troubleshoot problems with connecting to a wireless network is to run WirelessManager manually. First uncheck the "Start networking during system boot" box in the Network prefs app, then save and reboot. Then run this in a shell:
C:wirelessmanager atheros5000.device verbose
or
C:wirelessmanager realtek8180.device verbose
and capture the output
If the above does not help, could you edit the file SYS:System/Network/AROSTCP/S/Package-Startup, and change ">NIL:" to ">T:wifi.log" on the WirelessManager line and add this as well Wait 5?
<pre>
if ${AROSTCP/WirelessAutoRun} eq "True"
Run QUIET "C:WirelessManager ${AROSTCP/WirelessDevice} >T:wifi.log"
wait 5
EndIf
</pre>
Then save, reboot and post the log file (T:wifi.log) here.
<pre>
c:wirelessmanager atheros5000.device verbose
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7)
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
Then it just sits there. Not sure what a normal dump looks like, I don't see anything that looks wrong in the configuration.
</pre>
looks like the driver isn't working with that card. Has anyone else successfully used that exact model number (AR2413)?
<pre>
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7):
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
*** [wpa_sm_init] sm->pmksa=02c66fd4 ***
Own MAC address: 00:01:36:15:ae:0c
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
Added interface atheros5000.device:0
State: DISCONNECTED -> SCANNING
Started AP scan for wildcard SSID
MLME: starting scan
MLME: scan channel 1 (2412 MHz)
sana2: sending MLME frame
Then it stops. Does this mean the router is not authorizing this NIC?
IRQ 4 (A)
</pre>
apparently locking up when the first frame is sent (a scan request).
<pre>
Devs/Networks/atheros5000.device:0
Initializing interface 'Devs/Networks/atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=12):
41 69 72 4c 69 6e 6b 35 39 33 30 30 AirLink59300
PSK (ASCII passphrase) - hexdump_ascii(len=8): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='AirLink59300'
*** [wpa_sm_init] sm->pmksa=0224e444 ***
Own MAC address: 00:1f:e1:42:e3:7a
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
[eloop_reg_timeout] Timeout is at 1317686594.160000
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
[eloop_reg_timeout] Timeout is at 1317686595.060000
[eloop_reg_timeout] Timeout is at 1317686604.060000
Added interface Devs/Networks/atheros5000.device:0
[eloop_run] Starting
State: DISCONNECTED -> SCANNING
Starting AP scan for wildcard SSID
MLME: starting scan
[eloop_reg_timeout] Timeout is at 1317686594.160001
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.233000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.373000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.513000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.553000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.693000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.013000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.073000
EAPOL: disable timer tick
EAPOL: Supplicant port status: Unauthorized
MLME: scan channel 14 (2484 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.113000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.153000
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.213000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.353000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.493000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.533000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.673000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.993000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686596.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686596.073000
MLME: scan completed
</pre>
Is your network hidden? If so, did you enable the 'Hidden' checkbox in the network prefs? What distro version are you using?
<pre>
"ENV:sys/wireless.prefs" looks like this:
network={
ssid="testadhoc"
key_mgmt=NONE
wep_key0="12345"
wep_tx_keyidx=0
}
</pre>
If your router doesn't broadcast its SSID (hidden), you need to add this option to the network block of the wpa_supplicant.conf on your aros machine and make changes after # Example blocks:
scan_ssid=1
Here's a full description of all the [http://hostap.epitest.fi/gitweb/gitweb.cgi?p=hostap.git;a=blob_plain;f=wpa_supplicant/wpa_supplicant.conf config file options].
<pre>
ap_scan=1
network={
ssid="YOURESSID"
scan_ssid=1
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP
group=CCMP
psk=YOURPASSWORD
}
</pre>
<pre>
filter_ssids=1
ap_scan=2
network={
ssid="REMOVED"
scan_ssid=1
bssid=REMOVED
priority=100
mode=0
proto=RSN
key_mgmt=WPA-PSK
auth_alg=OPEN
pairwise=CCMP
group=CCMP
psk=REMOVED
}
</pre>
Error 6: Couldn't resolve host name.
Check Scout -> Devices and look at the device that you are using, in the OCnt column it should state 2 which means AROSTCP and Wirelessmanager are both accessing this driver. If 0 or 1, then uncheck the checkbox in Network prefs for starting networking at boot, save and reboot. Then run this is the shell:
C:WirelessManager realtek8180.device unit 0
some quirks setting up the wireless network as well
1) it's far better setting up either the wired OR the wireless network adapter as net0:, or weird things happen
2) it's better using fixed IP on the local network instead of DHCP
3) network setting must be placed in network setting panel in /prefs, using the wirelessmanager helped me finding available SSIDs, but not actually connecting to them
once done, reboot.
If previous setup is proving problematic
<pre >
SYS:Prefs/Env-Archive/Wireless.prefs
SYS:Prefs/Env-Archive/Zune/OWB.config
SYS:Prefs/Env-Archive/Zune/global.config
SYS:Prefs/Env-Archive/AROSTCP/WirelessDevice
SYS:Prefs/Env-Archive/AROSTCP/db/Interfaces
</pre >
Make a copy of these files and restore in case of problems.
Please try this test to check if you can connect to your router, ie established that the WiFi layer is working
̊̊̊̊Boot with networking disabled, by make sure that "Start networking at boot" in Network Prefs is unchecked (no tick).
̊ Run this in a shell: C:WirelessManager atheros5000.device VERBOSE
̊If the output of that command is too long to summarise here, you can redirect it to a file by adding >RAM:wifi.log to the end, then attach or paste that file here.
try running "status" in the shell and check that AROSTCP is listed/running
If AROStcp is not showing, then AROSTCP is not running. attempted to start it by clicking Use or Save in network prefs, or checking the "start networking at boot" box or typing into a shell.
Execute SYS:System/Network/AROSTCP/s/startnet
(run Status again afterwards).
The "cannot resolve hostname" will appear if you are blocked on the wifi network by the router as well as aros not being able to assign correct network address.
One way of testing this might be to disable the firewall in the router. you might also check the router how it sees the attempts aros do to speak to it. The easiest way to do that would be to manually give aros an IP number in the routers accepted range. and see if it shows up at all within the router.
Tests that can be undertaken to determine correct settings and functions
pciinfo
sanautil -d broadcom4400.device status
<pre >
ping <router-address> e.g. 192.168.0.1 (aka inet) or 80.237.146.33 (www.amiganews.de)
ifconfig net0
ifconfig net0 up
extras:networking/utils/sanautil/sanautil -d atheros5000.device status
WirelessManager atheros5000.device verbose >RAM:wifi.log
;to send the log to RAM disk to be read easier or if detected,
Run WirelessManager atheros5000.device >NIL:
Run WirelessManager atheros5000.device ssid="mynet1" >NIL:
C:WirelessManager realtek8180.device unit 0
</pre >
Please look at the task list in Scout, and check if WirelessManager and AROSTCP are running. Also look at the device list in Scout to check if realtek8180.device is open.
start tools/debug/sashimi, maybe it shows some debug messages when disconnection happens.
Firstly, let's take a look at what your setup most likely looks like, assuming you use a router. See diagram below:
<pre>
Internet <---------> home router <---------> computer
-----------external IP------------------internal IP-------------
</pre>
Okay, so what am I trying to show you with that diagram. A few things. Firstly, the IP address that connects you to the Internet is not the same one that connects you to your router. What happens is that your computer doesn't have a direct connection to the Internet, instead your router connects to the Internet, and your computer connects to the router.
You can see the external and internal IP addresses in these example settings...
* Default Gateway : 76.91.64.1 (external IP for ISP/Internet host)
* IP Address : 76.91.71.184 (external IP for home router)
* IP Address : 192.168.0.1 (internal IP for home router)
* Address = 192.168.0.161 (internal IP for computer)
As you can see, there are two internal IP addresses and two external IP addresses. This is because there is a client/server relationship, effectively one address is for the service (server) and one address is for the device trying to access that service (client).
The server addresses in your case are 76.91.64.1 (your ISP's address, serving the Internet), and 192.168.0.1 (your home router's address, serving your home network). The term gateway applies here, they are your gateway to those services.
Subnet masks are used along with IP addresses to determine which IP addresses are allowed access to a network. I did learn the more in-depth rules about subnet masks once (watched a CCNA vid), but I've forgotten about it. The basic level of understanding you'll need is easy to remember though. A subnet mask value of 255 means that portion of the IP address must stay constant, whereas a subnet value of 0 means any unassigned value up to 255 is allowed in the IP address.
By far the most common subnet value is 255.255.255.0. What this means is that the first three parts of the IP address you use to connect to a service must stay the same as the server/gateway address, and only the last section can change.
So if your router's internal IP address is 192.168.0.1, and the subnet mask is 255.255.255.0, the only addresses that will be allowed to be used on that network are between 192.168.0.2 and 192.168.0.255 (I think 192.168.0.0 is reserved for other uses).
Final point to make is about DHCP (a.k.a. dynamic IP) vs static IP. A server/router using DHCP gives a device that connects to it an address within the acceptable range. It usually starts with the lowest numbered free address, so with your router it'll give the first device that connects to it 192.168.0.2, the next device 192.168.0.3, and so on. Static IP addresses are where you set the IP address you want to connect with in advance.
When using static IP addresses on a router where DHCP is active, it's good to use a high number to avoid conflicts with other devices that are connected to your network, to reduce the risk that both devices will try using the same IP. That's why your current choice of 192.168.0.161 is good, unless you have over 159 devices connected on your current network!
Okay, so what's the next step. Well, if you can use ping, I'd suggest pinging 192.168.0.1. If you get a positive response it means you're connected to your router, if you don't get a response it means the connection between your router and your computer is at fault.
Documentation on configuring the AROSTCP environment further can be found [http://en.wikibooks.org/wiki/Aros/User/Networking here]
===File Sharing===
As AROS knows only a few filesystems (FFS, OFS, SFS, PFS (amiga only), FAT12, 16, 32, Microsoft NTFS (windows), UDF (Blu-ray)).
The others in regular use like MacOSX hfs+, Linux ext2/ext3 and ext4, Haiku BeFS provide a problem in transferring files.
Linux can access SFS partitions but it needs to be compiled. The latest full source are [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ here]. It compiled fine with a 2.6.30 kernel in Puppy Linux 4.31.
An alternative, is to use a FAT32 partition to share. Setup a 4G FAT32 partition using HDToolbox for sharing, and the rest of the space as SFS for an Aros install. It works very well.
Files could be transferred via TCP internet network.
====SMB2/3====
With Windows you can share one folder or all folders of the "Public" user.
On Windows what is important is to enable sharing (Network and Sharing Center).
AROS Mountlist should look lke this
<pre>
Handler = L:smb2-handler
StackSize = 65536
Priority = 5
GlobVec = -1
ACTIVATE=1
Startup = "smb://UserAcc:password@PCShare/Sharefolder"
</pre>
which could also be
"smb://UserPC:password@192.168.x.x/Public"
or
"smb://UserPC:password@Name-PC/Public"
so
"smb://UserPC:password@192.168.1.158/Folder"
or
"smb://UserPC:password@Name-PC/Folder"
After you have configured a share generates a DOSDrivers it is named "SMB0" which includes the setting, and at each reboot it is Mounted. You can still delete the DOSDriver by hand, is located in Storage/DOSDrivers, the file "ServerAutoMounts", in ENV:AROSTCP which indicates the DOSDriver to be mounted, should also be deleted.
The per-mount files are written to ENV:SMB or SYS:Storage/DOSDrivers. There is also additional file ENV:AROSTCP/ServerAutoMounts which states what will be presented to the end user.
====Old SMBFS====
e.g. to connect to a NAS share such as \\NASBOX\Shared use -:
SMBFS WORKGROUP=<YOUR WORKGROUP NAME> VOLUME=<AROS volume name to use>: SERVICE=<UNC Path to connect to>
SMBFS WORKGROUP=MYNET VOLUME=Shared: SERVICE=//NASBOX/Shared
And you will then have an icon appear on your desktop for the volume name you have chosen.
You can put the above script into wbstartup or
give it an icon, change it to a 'project' and give it the default tool c:iconx
Open a shell and type copy sys:script.info "sys:wbstartup/YOURSCRIPTNAME.info"
This should create an icon for your script file.
Now right-click on your script and select 'information'.
Change 'tool' to 'project', put 'c:iconx' into the 'default tool' box, click save
The reason being that scripts need to be opened with 'execute SCRIPTNAME' (or 'iconx') whereas the programs started from wbstartup are opened using 'run PROGRAMNAME'. It's the same as trying to start a command-line tool from the workbench by double-clicking it.
====Setup ISO images within AROS====
Use [http://archives.aros-exec.org/index.php?function=browse&cat=driver/storage DiskImage] which supports many cd image formats ISO, CCD, MDF/MDS, CUE/BIN, NRG and UIF. To mount CD or DVD images use below....
<pre >
# Rename your iso 'Unit0' (note no extension).
# Do 'View/All files' on you Aros partition. You should now see a folder called 'Diskimages'. Copy your renamed iso to there.
(Alternatively, you could type at the shell 'assign FDSK: xxx', where xxx is the location of your iso.)
# From the shell, type 'mount CD0:' and the iso should appear on the Wanderer desktop. You can now access it like a real disk.
</pre >
assign devname: dismount
Assign DOSVOLUME: remove
[http://aminet.net/package/disk/misc/unmount-0.1 unmount] most filesystems work but SFS lacks support for ACTION_DIE packet
If you are using an IcAros install, the startup scripts are set up to wipe the Diskimages directory on boot, so its worth keeping a second copy of the iso somewhere else. Alternatively, you could set up extra mountlists for additional iso images. I've made a file called iso1 in the Aros:devs directory that contains the following text:
<pre>
/* Entry for ISO image */
ISO1:
FileSystem = cdrom.handler
Device = fdsk.device
Unit = 1
LowCyl = 0
HighCyl = 0
Surfaces = 1
BlocksPerTrack = 1
DOSType = 0x41434400
Activate = 1
#
</pre>
Then I just need an iso called 'Unit1' (corresponding to the 'Unit = 1' entry in the mountlist) in Diskimages (or wherever I assign FDSK: to) and to mount I type in at the shell:
Mount iso1: from devs:iso1
Of course, if you create mountlists for ISO2, ISO3:, etc. (with the corresponding change to the 'Unit = ' line) you can have as many isos mounted as you wish. I just call mine ISO1: etc. to distinguish them from the real CD drives
==Video Guides==
Video demonstrations and tutorials covering:
:00. '''Introduction'''
::[https://www.youtube.com/@jamesmattson6813/videos Various Aros Installs],
::[https://www.youtube.com/embed/j8EmSEby0Rg AROS repo in gource, view of AROS dev commits from 1997 to 2025], [http://www.youtube.com/watch?v=Vx_zqlBow40&feature=related Gource view of AROS 1997 up to 2009],
::[http://www.youtube.com/watch?v=s1RsvEm7UrU Why an Amiga OS in 2011],
::[https://www.youtube.com/watch?v=1W886mheV74&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Johan Grip on early days of AROS x86], [https://www.youtube.com/watch?v=mXaKDhtTTqQ&t=14s&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Michel Schulz on Aros and PiStorm],
:01. '''Installation'''
::[https://www.youtube.com/watch?v=M7YjufrJqDs Aros One install], [https://www.youtube.com/watch?v=iIMguHTdC5E Aros One USB install], [https://www.youtube.com/watch?v=ZNXauy5m5Wc Aros One install], [http://vimeo.com/11013489 Modify Grub boot],
::[http://www.youtube.com/watch?v=wyQVeyXIywc&feature=channel iMica Silent Pt3], [http://www.youtube.com/watch?v=o2AnkoflY14 Wipe whole drive and Install - warning loss of data on drive],
::[http://www.youtube.com/watch?v=OVXm6_-witQ VirtualBox install], [ VMware install],
::[http://www.youtube.com/watch?v=0k2PEmT8I14 Broadway AROS Install],
::[https://www.youtube.com/watch?v=PtDiXhjSIfs Is Aros Icaros a choice?],
::[ driver install],
::[http://www.vimeo.com/10491104 HDAudio install but needs account], [],
:02. '''Amiga Basics'''
::[http://www.youtube.com/watch?v=TY8mWxwzH5o Screens tutorial],
::[https://m.youtube.com/user/AMIGASYSTEM/videos General], [ Dos Scripts tutorial], [http://www.youtube.com/watch?v=hPT7SmVEpjc OS 1.2], [http://www.youtube.com/watch?v=n6kX3FqH8Ww&feature=related OS 1.3],
:03. '''Customisation demos'''
::[https://www.youtube.com/@AMIGASYSTEM/videos Prefs tutorial], [ Decoration tutorial], [http://www.youtube.com/watch?v=Dn5C8G3aDXU Scalos],
:04. '''Setting up''' internet access and surfing the web, FTP, IRC and Mail apps
::[ Network Prefs], [ AirCOS tutorial], [ jabberwocky tutorial],
:05. '''Native bundled Games and Applications'''
::[http://www.youtube.com/watch?v=aYlFv2B-VXc 3D Games], [http://www.youtube.com/watch?v=MXK7wwhd-R0 Latest Games], [http://www.youtube.com/watch?v=RUgiVThv23Q&feature=mfu_in_order&list=UL PrBoom GL], [http://www.youtube.com/watch?v=0s7u8TPy7V4 Assault Cubes], [http://www.youtube.com/watch?v=fih6aCXKeqs Cube 2], [http://www.youtube.com/watch?v=-X0ay0MGOms DosBox on Aros], [http://www.youtube.com/watch?v=7nKduDjf14k Oct 2010],
::[http://www.youtube.com/watch?v=FziV2z_uxnQ Apps Pt 1], [http://www.youtube.com/watch?v=xs37_nfa5CI Apps Pt 2], [http://www.youtube.com/watch?v=Bn59_VvbQR0&feature=related Apps Pt 3],
::DOpus4 [http://www.youtube.com/watch?v=aSRybWjrrME DOpus 4],
::Milkytracker [http://www.youtube.com/watch?v=VxBOEPzpdKg&feature=related Laying Down Base Tracks],
::[http://www.youtube.com/watch?v=k2uKQ0-ieOE Audio Evolution 4 in action], [http://www.youtube.com/watch?v=Zq4r9k0_jZI Quick Videos],
::[http://www.youtube.com/watch?v=gGKCFZcIc0I&feature=related ScreenRecorder], [http://www.youtube.com/watch?v=974c2e-Fqak&feature=related TV out Tests],
::[http://www.youtube.com/watch?v=fjq8ct5d5IY AmiFIG], [http://www.youtube.com/watch?v=h0rHvPhYJo4&feature=youtu.be ZuneFIG],
::[http://wiki.povray.org/content/Documentation:Tutorial_Section_1 POVray Tutorial 1],
::[http://www.youtube.com/watch?v=Jk-ZNLfJsvQ pt 1, jan. 2008], [http://www.youtube.com/watch?v=nWRy33g1R7Y pt 2, feb. 2009], [http://www.youtube.com/watch?v=r5PbhCtm4vE pt 3, feb. 2010],
::[https://www.youtube.com/watch?v=G7_FJUoQ89o Hollywood programming], [], [], [],
::[], [], [],
::[], [], [],
::[], [], [],
:06. '''Commercial software available'''
::[http://www.youtube.com/watch?v=fKXY9B4R43s AntiryadGX 3D Game Editor],
::[http://www.youtube.com/watch?v=TMS9NDzwm5U BOH indie Game],
:07. '''Running classic amiga apps and games'''
:: Amiberry [], [],
::[http://vmwaros.blogspot.com/2008/11/introducing-amibridge.html Intro Amibridge], [http://www.youtube.com/watch?v=ee2PWvCZeLo Old Amiga Apps], [http://www.youtube.com/watch?v=ee2PWvCZeLo Why Janus UAE is good],
::[https://www.youtube.com/watch?v=VhlsNSYSuDg DPaint tutorial]
::[http://vmwaros.blogspot.com/2009/11/can-icaros-play-my-amiga-games-and-why.html Play Amiga Games], [https://www.youtube.com/watch?v=XTaZCNOvCnE],
::[http://www.youtube.com/watch?v=tMehS77LXQ4 Pagestream Introduction], [http://www.youtube.com/watch?v=284-w3hTzII Pagestream Tutorial 1], [http://www.youtube.com/watch?v=mlwEGwhZzl4 Pagestream Tutorial 2],
::[http://www.youtube.com/watch?v=iIcrIjPOctc Catweasel Mk4 PCI Part 1] and [http://www.youtube.com/watch?v=BaitHeL6bEA Part 2],
:08. '''Misc and History'''
::[http://www.youtube.com/watch?v=d6mDXKU29w0 Mum uses old AmigaOS Workbench 1.1 (1986)], [http://www.youtube.com/watch?v=DaRkacQ-YMg Why an Amiga 500 (1987)], [http://www.youtube.com/watch?v=k5CYsgVCzYY an Amiga 2000 (1987)],
:09. '''Misc Shows and Events'''
::[http://www.youtube.com/watch?v=klgVSWKs4kE VCF 2010], [https://www.youtube.com/watch?v=eQ3d5qR-Hv8 24:06 Jason McMullan at amiwest 2012 about AROS], [https://www.youtube.com/watch?v=jpQO7XSfAv4 Aros SMP multi core amiwest 2013], [], [https://www.youtube.com/watch?v=gFRtAAmiFbE], [https://www.youtube.com/watch?v=DjdUEyjx8GM], [https://www.youtube.com/watch?v=ydYDqZQpim8], [], [https://www.youtube.com/@uminekoshouten/featured], [https://www.youtube.com/shorts/NfoY023w-vE],
:10.
::[https://www.youtube.com/shorts/6qJTNW4-6GY]
===History===
The project was originally started by a small group of Amiga [http://www.amigahistory.co.uk/aros.html enthusiasts] in 1995. These individuals were mainly computer-based college university students at the start, though that student trend has diminished since. An interview with Aaron Digulla [http://arosshow.blogspot.com/2006/12/interview-with-aaron-digulla-who.html here]
* 1992 Commodore folds
* 1996-1998 much of the early years was concerned with exec, dos and intuition libraries.
* Early 1999, Haage & Partner used parts of the AROS code in AmigaOS 3.9.
* March 2001, floppy disk images of AROS became available.
* Early 2002, AROS changed its name from Amiga Replacement Operating System to Amiga Research Operating System
* June 2002, AROS devs decided to use Zune (MUI 3.8 rewrite) as the GUI system.
* November 2002, Eric Schwartz drew Kitty for AROS usage.
* Early 2003, AROS.org underwent a graphics facelift.
* Late 2003, GCC C compiler arrived.
* Early 2004, Aros-Exec opened.
* Early 2005, Aros Max bootable CD arrived.
* Late 2005, SFS filesystem ported and allowed fast access to apps and network support arrived
* Early 2007, AROS.org underwent another graphics facelift.
* Mid-2007, AROS changed to AROS Research Operating System after A.Inc. sued Hyperion with a trademark violation.
* Late 2007, the hard disk installer added and VmwAROS (later called Icaros Desktop) distro launched.
* Early 2009, Our first usable web browser (OWB)
* September 2010, first wireless support appears and AspireOS started as a distro
* Early 2012, the first paper-cut bugfix and Fab's Odyssey Web Browser ported
* Early 2017, work started on utilising the addition cores on modern CPUs starting with the 64bit x86 PC version
* Mid-2017, m68k port optimized for the Vampire 2 / Apollo accelerators (68080 AMMX FPGA)
* 2018 The old AROS Exec website closed and a new one opened
* 2019 AROS One x86 32bit distribution started and now with USB install version
* Early 2021, backport of more features of 32bit PC ABIv1 into 32bit PC ABIv0 (Aros One 1.5 and above)
* 2025 year of 64bit pc builds and porting 32bit applications to 64bit ABIv11
* 2026 update of [https://www.youtube.com/watch?v=6FKTL068ULM&pp=ygUPYXJvcyBhbWlnYSAyMDI2 nvidia nouveau driver for 64bit PC]
===Bounties===
To help inspire developers with both ideas and monetary incentives, rewards are offered for the successful completion of "bounties" (requests for missing/new functionality) chosen by the community and handled by [http://power2people.org power2people] (formerly done by TeamAROS). A monthly option is [http://www.power2people.org/funds/aros/ here].
Future goals for AROS include expanding its underlying retargetability to support even more diverse architectures, provide memory protection features and user level file security, SMP and many other wonderful features missing from AmigaOS — while still providing as much source level compatibility as is possible (however it is accepted that to achieve some goals code certain things may require a little recoding).
[http://www.ohloh.net/p/aros/contributors Developers] come and go as with any open source effort and we would like to thank them for their efforts...
;1996-2000:In DigullaA (coordinator), GripJ, TempletonI (BSD), SchulzM, RittauS, voordenDagL, HolmM, JohanssonT, VanIngelgomH, SteigerwaldM, BortasP, deJongK, AlfredssonJ, InnocentiB,
;2001-2005:In [http://chodorowski.com/adam/aros.html ChodorowskiA], StegerG, BergerS, HeutlingS, AlemagnaF (gcc), VerhaegenS (rexx), KielH, MatheussenKS (CAMD), SzczygielskiP, ErikssonP, LeCorfecD (Zune), BauerS (Zune), FurlongW, GustafssonJ, AndrewsN, CafferkeyN, GierichM (jpeg), PattonJ, ParsonsM, DietrichJ, SeilerT, BischoffL, LorentzenNH, AdamO, BerglundH, SmithP, HolmenD, BlomM,
;2006-2010:In FedinP, RusslerM, SzymczykS (owb), SmiechowiczK (openGL), WeissM, NorrisR, BrunnerO, WiszkowskiT, GreppinA, [http://www.fukt.bsnet.se/~bearsoft/ Bearsoft Björn Screwelius], ErbY, CharletF, HodgesC, [http://aros-exec.org/modules/newbb/viewtopic.php?topic_id=4819&forum=18&post_id=43103#forumpost43103 HokstadV], McMullanJ (m68k), WilenT (m68k),
;2011- :In MuijzenbergPHvanden, ALB42, JonesEM, weiju, DizzyofCRN, wawa, miker,
* 1996 - The linux hosted version for i386 was the first to arrive
* 1998 - i386, The native version for i386-based PC AT computers and compatibles.
* 2004 - x86/64, The native version for 64-bit (x86_64, amd64) PC computers.
* 2008 - sam440/ppc, The native version for Sam440EP, Sam440EP Flex and Sam460ex computers.
* 2009 - efika, The native version for PowerPC Efika computers.
* 2010 - m68k, The native version for m68k Amigas or WinUAE
* 2013 - raspi/armfh, early native version for ARMv6 based Raspberry Pi computers.
* 2017 - x86/64bit smp
Debugging capture serial debug at all (especially with sysdebug=all or --sysdebug=all) to see it displayed on screen
* yes, usb -> rs232 adapters can work most of the time, some of the cheapest ones are not fully compatible with all rs232 devices to capture to another device
* you will need a null modem cable (or a null modem adapter usually female to female) in addition to the usb -> rs232 adapter (usb adapter is a normal modem ie. the pins are not crossed over)
Normal modem cable - straight connection DCE
<pre>
Pin 2 -> Pin 2 RXD
Pin 3 -> Pin 3 TXD
Pin 5 -> Pin 5 GND
</pre>
Null modem cable connections DTE
<pre>
Pin 2 -> Pin 3
Pin 3 -> Pin 2
Pin 5 -> Pin 5
</pre>
(9pole SUB-D)
<pre>
serial ser: (amiga/aros) tty2 tty1USB0 (linux) COM1 (windows) (depends on the os being used)
speed baud transfer rate 9600 38400 lower baud might be more successful
data bits 8
stop bits 1
parity none
handshaking flow control - none xon/xoff (most likely) rts/cts dsr/dtr (pins not connected so should not work)
</pre>
*You cannot use compiled aros X86-64 bit software (when ready) on aros X86 32bit. PPC compiled software on X86 and so on.
*68k is tested with the UAE emulator (WinUAE) but some tests are done on native 68000 based Amigas and others.
*PPC support is very limited to certain devices.
If you use the WBStartup, you have to delete the other icons in the folder (readme etc..) and you have to add in the Icon Tooltype the parameter DONOTWAIT
If you use user-startup instead, you need to add the attached command "after assignment to LUA"
C:WBRun DH1:Extras/Utility/WeatherBar/WeatherBar >NIL:
Change the command to match your WeatherBar path.
<pre>
PATH sys:Utilities/WeatherBar ADD
run >nil: lua:amilua weatherforecast.lua
</pre>
To enter data your Country or City, ist with city_id numbers can be found [http://bulk.openweathermap.org/sample/city.list.json.gz here] or you need to go to [https://www.bbc.com/weather BBC Weather], once you type the name of your city or town in the appropriate tab, and press enter, the 7 numbers to be added in the "WeatherBar" will appear on the Browser url address bar above
Unicode v16.0 emojis are not supported but [https://github.com/jens-maus/libcodesets codesets.library] provides
<pre>
internally supported (hardcoded) charsets/codesets are: (conversions are possible from and to each codeset):
AmigaPL – Polish (Amiga)
Amiga-1251 – Cyrillic (Amiga)
ISO-8859-1 – Western European
ISO-8859-1+Euro – West European (with EURO)
ISO-8859-2 – Central/East European
ISO-8859-3 – South European
ISO-8859-4 – North European
ISO-8859-5 – Slavic languages
ISO-8859-9 – Turkish
ISO-8859-15 – West European II
ISO-8859-16 – South-Eastern European
KOI8-R – Russian
UTF-8 – Unicode
In addition, external charset table files can be stored in LIBS:Charsets or loaded by an application from PROGDIR:Charsets. The charset files included with this distributions are:
IBM866 – Cyrillic (cp866)
ISO-8859-7 – Greek (LatinGreek)
ISO-8859-10 – Nordic (Latin 6)
windows-1250 – Central/East Europe (Windows)
windows-1251 – Cyrillic (Windows)
windows-1252 – West European (Windows)
</pre>
Icaros 2.3 USB image needs a header stripped so it can work correctly
dd bs=512 skip=1 status=progress if=icaros_light_2-3-0_pendrive.bin of=/dev/sdxy && sync
Scalos
<pre>
-------------------------------
{ "STRING", "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K",
HALIGN LEFT | CENTER | RIGHT
VALIGN TOP | CENTER | BOTTOM
STYLE NORMAL | BOLD | ITALIC | BOLDITALIC
FONT // font specification - format: "fontname.font/size"
-------------------------------
arguments for STRING SRC
"diskstate",
"diskusage",
"diskusagefree",
"diskusageinuse",
"diskusagepercent",
"fibfilename",
"filecomment",
"filedate",
"fileprotection",
"filesize",
"filetime",
"filetypestring",
"iconname",
"linktarget",
"plugin" pluginname <optional plugin arguments>
"versionstring",
"volumecreateddate",
"volumecreatedtime",
"volumeordevicename",
-------------------------------
arguments for HIDE
"novolumenode",
"isempty" (some STRING)
-------------------------------
all internal commands:
"about",
"backdrop",
"cleanup",
"cleanupbyname",
"cleanupbydate",
"cleanupbysize",
"cleanupbytype",
"clearselection",
"clone",
"close",
"copy",
"cut",
"delete",
"emptytrashcan",
"executecommand",
"formatdisk",
"iconify",
"iconinfo",
"lastmsg",
"leaveout",
"makedir",
"open",
"parent",
"paste",
"putaway",
"quit",
"redraw",
"redrawall",
"rename",
"reset",
"selectall",
"showallfiles",
"showonlyicons",
"shutdown",
"sizetofit",
"snapshot",
"snapshotall",
"snapshotwindow",
"unsnapshot",
"update",
"updateall",
"viewbydate",
"viewbyicon",
"viewbysize",
"viewbytype",
"viewbytext",
</pre>
{{status|50%}}
{{BookCat}}
2qhvwi394zsnre4l60enmgfwbivbhdg
4675864
4675862
2026-10-13T16:11:56Z
Jeff1138
301139
4675864
wikitext
text/x-wiki
{{ArosNav}}
==What is AROS==
Google translation
[http://translate.google.com/translate?hl=en&sl=auto&tl=de&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs German], [http://translate.google.com/translate?hl=en&sl=auto&tl=nl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Dutch], [http://translate.google.com/translate?hl=en&sl=auto&tl=fr&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs French], [http://translate.google.com/translate?hl=en&sl=auto&tl=it&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Italian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=da&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Danish],
[http://translate.google.com/translate?hl=en&sl=auto&tl=es&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Spanish], [http://translate.google.com/translate?hl=en&sl=auto&tl=hi&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Hindi], [http://translate.google.com/translate?hl=en&sl=auto&tl=zh-CN&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Chinese],
[http://translate.google.com/translate?hl=en&sl=auto&tl=ru&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Russian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Polish], [http://translate.google.com/translate?hl=en&sl=auto&tl=ja&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Japanese], [http://translate.google.com/translate?hl=en&sl=auto&tl=ko&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Korean],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pt&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Portuguese],
*Computer Hardware
*AROS (operating system)
*Applications and Games
*User
[http://www.osnews.com/story/15819 AROS] is one of the intermediate levels between the computer hardware and the user. It is an open-source, clean-room implementation of AmigaOS 3.x that can be run on many different computer architectures. It runs primarily on PC x86 32bit and 64bit but also on amiga motorola 68k and compatibles, some ARM like the Pi and Apple Silicon, RISC-V and some old PowerPC.
This page will cover enough to be able to write the downloaded image to your preferred media, to run a LiveUSB, LiveCD or LiveDVD on your office/home PC (Live meaning you can test without changing your existing setup) and, ultimately, to use it.
Intel / AMD PC hardware support mostly covers the years 2000 to 2024. At the moment, AROS is '''not''' recommended to be '''installed''' on a working vital data holding machine. Instead, writing to and booting from a '''USB stick''' could be a much better option.
AROS is an hobby OS and can co-exist with Windows(TM), MacOSX(TM), Android(TM) or Linux(TM) and act as an alternative.
Unfortunately, Aros has few developers so upgrades and improvements can take [https://sourceforge.net/p/aros/mailman/aros-cvs/ time to appear].
AROS core is now [http://en.wikibooks.org/wiki/Aros/Developer/IncompleteAPIs ~80%] finished and is usable, so keep in mind that the software is still considered ALPHA/BETA and in constant development. Currently AROS is fun to play with on a curiosity level, but it is also interesting to program. AROS has some multimedia features and has internet access.
Most importantly, use AROS to its maximum potential as it stands now, find ways to have fun with it and share your experiences.
Good Sites to visit
: [https://www.arosworld.org/home.php Aros World User forum]
: [https://arosnews.github.io/ AROS News]
: [https://www.facebook.com/ArosWorkshop/ Aros Workshop],
: [https://www.osnews.com/topic/amiga-aros/ OSNews]
: [https://www.reddit.com/r/aros/ Reddit]
: [https://archives.arosworld.org Aros Archives]
: [https://aminet.net/ Aminet]
: [http://www.amiga-news.de/en/ English translation of German site]
: [https://aros.sourceforge.io AROS] with [https://aros.sourceforge.io/download.html ABIv1 downloads]
: [https://github.com/aros-development-team/AROS Aros ABIv1 Codebase]
: [https://github.com/aros-development-team/AROS/issues register ABIv1 issues] and [https://sourceforge.net/p/aros/bugs/ old defunct bugs notification site]
: [https://sites.google.com/view/arosone Aros One x86, x64]
: [https://tinyarosdistro.flazio.com/ Tiny Aros x86 and x64]
: [https://arosnews.github.io/aros-portable/ AROS portable USB3 stick images of hosted Aros One x86 and x64 on debian]
: [http://vmwaros.blogspot.com Icaros Desktop x86 now on sabbatical, very old edition]
: [https://sites.google.com/site/arosaspireone AspireOS, of the netbook Aspire One, very old edition]
: [https://github.com/deadwood2 Deadwood's builds], [https://www.axrt.org/download/aros/v11/ v11 64bit PC builds], [https://axrt.org/downloads-aros Updated i386 32bit PC builds],
: [https://github.com/ezrec Ezrec x86 m68k mirror of old svn version]
: [http://arosalive.blogspot.co.uk/p/10-basic-aros-how-tos-tutorials.html Basic How To guides]
: [http://arosgamer.blogspot.co.uk/ AROS Playground], [http://thewetmachine.net/tag/aros/ Jess Wet Machine], [https://aroshacking.wordpress.com/ Jon Robertson's AROS Experiences and FPC Free Pascal], [],
:[http://www.apollo-accelerators.com/ Apollo Accelerators m68k], [http://www.amigablogs.net/ Amiga Blogs], [http://blog.a-eon.biz/blog/ Trevor Dickinson blog],
: [https://forum.amiga.org/ Amiga OS AOS 3.x forum]
: [http://eab.abime.net/ EAB Amiga]
: [http://www.amigaworld.net/ AmigaWorld]
: [http://www.ppa.pl/ Polish Amiga Like News]
: [http://www.apollo-core.com/ Apollo Forum]
: [https://amigaalive.blogspot.com/ AmigaAlive]
: [https://www.amigalove.com/software Disk Mags]
: [https://amigachristmastree.ultimateamiga.com/ Xmas Amiga Game Jam]
: [https://www.reddit.com/r/amiga/ Amiga]
== Distributions aka Distros ==
For end users there are distributions (ready made with selected apps aiming to be easy to use), mostly created and maintained by one person in their own workflow/style. They reuse the nightly boot compiles to suit their needs and possibly other end users. You are free to create your own if required.
* For native 64bit Intel/AMD: [https://sites.google.com/view/arosone Aros One x64], [https://tinyarosdistro.flazio.com/ Tiny Aros],
* For native 32bit Intel/AMD which will run on 64bit machines: [https://sites.google.com/view/arosone Aros One x86], [https://www.tinyaros.it/ Tiny Aros],
* For native 68k [https://sites.google.com/view/arosone Aros One m68k], [http://www.aros-platform.de/ AROS Vision],
'''Please, keep in mind that the distros listed above use a different ABI (abi v11) , which is NOT binary compatible with the official ABI V1.'''
* For hosted Linux usb drive image [https://arosnews.github.io/aros-portable/ x64 Debian hosted version of Aros One],
* For hosted ARM there is [https://github.com/jonx/AROS-AArch64/releases alpha for Apple Silicon] and [https://aros.sourceforge.io/nightly1.html RaspberryPi Pi3, Pi4, Pi400, Pi5, 500+ raspi-aarch64-system native 64bit]
AROS was originally developed on Linux but can run on an Intel-based Linux distro as an app. As time has gone on, it can be run as an app on many more operating systems (Windows, FreeBSD, Linux and limited on MacOS). This may sound strange: an OS running on top of another OS.
Basically, this is to take advantage of drivers (audio, internet, graphics, etc.) and compiler environments, in the existing OS, with which people may be already familiar. The term we use for what AROS does is "Hosted".
AROS Native is the term coined to describe AROS being run without any OS underneath it. It runs alone just like AmigaOS(TM) did. As this version does not benefit from "Hosted" drivers, dedicated ones have to be ported/written. Hence the smaller range of supported hardware / peripherals. We have other pages highlighting this support
AROS is open source so basically everyone can take part. The source is public on github and there are new commits most days. AROS is automatically compiled daily, result are the nightly builds hosted on Sourceforge. The nightly builds are only used for testing changes, testing software and the starting point for distribution maintainers or even your own distribution. They are very basic, miss some functionality and apps like web browsers and generic general appearance which can be changed.
* The [https://sourceforge.net/projects/aros/files/nightly2/ Nightly2], [http://aros.sourceforge.net/download.php nightly builds File Release Service] or [http://aros.sourceforge.net/downloads/ Sourceforge Project Web builds] are made automatically every night directly from the Github and in the past, SVN (Subversion) tree and contain the latest code for the AROS operating system. It should be noted that the builds have not been tested in any way and can be horribly broken but usually are not.
*ABIv1 standard for most nightly builds, it is where the most work is done by developers
*ABIv11 offspring aka fork of 64bit PC ABIv1 i.e. another PC 64bit build
*ABIv0 standard for PC 32bit intel / amd PC distributions for historic reasons
==Media==
AROS media tends to boot in this tier list of media types, first internal HDD SSD, CD DVD drive, and finally usb drive (last two can depend on bios boot order)
* USB .VHD
[https://sites.google.com/view/arosone Aros One x86 and x64], with md5 below
<pre>
0a656d53a9c902e9934000d8392e30ec *ArosOne-USB-1.3-64Bit.zip
7dd7119ab3e56d75ee852c137226b4d7 *ArosOne-USB-v1.2-x86_64-v11.zip
cf906eeaad4a83b3520b1896bdc6b0d3 *ArosOne-USB-v1.1-x86_64-v11.zip
e2eb8fe8cfd61c567b0152a61cf85251 *ArosOne-x86-v2.8-USB-IMG.zip
559909c75c2f56472c74267a7d075355 *ArosOne-x86-v2.7-USB-IMG.zip
93da5898508c1a8c05bb8991ab7bd117 *AROS One Image-USB-2.4.zip
59fcabd7090e47f12d54f7eb78cf0f45 *ArosOne-x86-v2.2-USB-Image.zip
24fb8de726ae8fc5fe5bac6d30f03dc5 ArosOne-x86-v2.0-USB-Image.zip
f3d725e990072edce633b59747911b6b ArosOne-x86-v1.8-USB-IMG.zip
e089a24ae310e92fcc407a0125602ce8 Aros-One x86-IMG-USB-v1.6.zip
</pre>
[https://tinyaros.flazio.com/ Tiny AROS]
22bc993625b7c75b17263c0cc7e7baaa *Tiny Aros_copy.vhd (March 2024)
There is usually a vhd image inside the zip that can be written to USB sticks which is so much faster than the old ISO written to physical CD DVD method. This .vhd can be written to an USB stick / ssd with these pieces of software below but it will erase the previous contents from the usb
Windows - [https://www.raspberrypi.com/software/ RPi Raspberry Imager, use custom and see all files], [https://hddguru.com/software/HDD-Raw-Copy-Tool/ HDD-Raw-Copy-Tool], [https://rufus.ie/ Rufus up to version 3.20 may work with VirtualBox HD vhd images with Win7 but not some Rufus 4.x versions], [https://etcher.balena.io/ Balena Etcher but may spy on you],
Linux - [https://www.raspberrypi.com/software/ Raspberry Imager Ubuntu], Suse Image / Multi writer, dd,
Mac -
* Virtual Machine .ISO or CDs DVDs
The native iso images are currently not compatible with Ventoy, Yumi, MultiBootUSB, Easy2Boot E2B, or similar
<pre>
617a905b1665128c5e05f94dcc48e7f1 *AROS-One-v1.3-64Bit-v11.zip
11c8a147fcad7ecf52ae3a43e1934b69 *ArosOne-DVD-v1.2-x86_64-v11.zip
f93053d3b9ccf304d7e6ac3389e1987b *ArosOne-DVD-v1.1-x86_64-v11.zip
86d808a40dc7be389a758799a9b4f595 *ArosOne-x86-v2.0-ISO-DVD.zip
f1fc8599ef6a39e5df394e0f41d55526 *AROS-One-x86-ISO-DVD-v1.6.zip
</pre>
You can use a virtual emulator like VirtualBox, VMWare to mount the iso image which can then be used to boot and/or install to USB.
No current software can write an AROS ISO to a Pendrive. The author of ‘Rufus’ (who used an Amiga 500 as a child) once tried, but when he saw the system composition, he said he was unable to do it.
The solution is to boot the ISO from a VM (WMware, VBox), then install the AROS build on the Pendrive, which will eventually become a Live Pendrive that can be booted on a PC.
The only precaution is that in some cases it is necessary to thoroughly clean the Pendrive of any partitions and remove any bootloader that is not AROS. The Pendrive must remain raw without any partitions.
You can clean the USB stick on a PC with a program that manages hard disks. You need to do a partition wipe. On some USB sticks, you can clean it with InstallAROS.
For some USB pendrives, please use a reputable partition editor to remove any and all partitions from a usb pendrive as HDToolbox cannot do this task sometimes with a wipe all option.
Previously the only installation option was CD-RW or DVD-RW, since the whole system can be burnt onto a single disk and can be reused when the next version is released. Good branded discs like Taiyo Yuden (later JVC) or Verbatim should be used to reduce frustration later. The days for this media is gone but kept here for information
Since nobody currently sells AROS on any other media, you will need access to a CD/DVD burner to create the installation disk yourself. After it is on a CD or DVD, then access and writing to USB pendrives becomes available (this should be viewed as an outdated or last resort alternative method now), as well as using good USB manufacturers like Sandisk, Kingston, etc. rather than some other no-names.
Try burning it to a CD-RW or DVD-RW using your CD/DVD burning program (most burning software have a burn iso option). The ideal writing speed is 2x or 4x, higher speeds can give errors and problems. Check the writing integrity of your CD or DVD if your software has an option to do so before going any further.
Standalone portable usb cd dvd drives do not boot physical burnt discs, please use an internal ide sata drive instead.
* SD-card
For [https://aros.sourceforge.io/nightly1.html ARM Pi Aros 64bit], copy the files onto a FAT32 formatted micro SD card.
==Booting==
The LiveUSB, and in the past LiveCD LiveDVD, is designed to trial (test drive) various operating systems without having to install them to your working system.
Since 2011, UEFI was introduced to replace the original PC BIOS which made booting media more confusing. Some changes in the UEFI/bios may be needed
*go into the bios using esc, f2 or f? and disable the Security -> Secure Boot and maybe apply option for Legacy IDE mode
*you may have to press F9, F10 or F12 or p on boot up to present a device boot options like USB or CD/DVD
*disable the Fast Boot config so it would recognize portable DVD-drive and changed the Boot-sequence
Secure boot was introduced by Microsoft and later consortium, control what operating systems work with Secure Boot via shims.
For Aros, it is best to disable and save the turn off change to Secure Boot (if you dual boot with Windows this will cause issues with further Window boots)
For the best experience, it is advised to install to another SSD than the one Windows resides on.
The grub part of the boot should be fully automatic, and you should see a multiple choice graphic card screen after 10 seconds for USB or 40 seconds CDs and DVDs.
If boot does not occur within a minute, please reboot and choose the VGA boot option as it relays a message stream so you can see where the issue lies.
After the grub graphics choice, AROS takes over the booting and any issues can arise here
If possible please use a branded usb pen drive as most of the time when we get reports of "crashes right after grub boot selection" it is mostly due to the recorded pendrive as they are made, notoriously on a will it work / will it fail nature, every time it is used.
<pre>
So one usb drive written may stop at a System halted. Reset the machine.
Or another pendrive will show give errors Smart Filesystem request - Volume 'Aros Live Drive' (DU0: usbscsi.device unit 0) There was an error while accessing this volume:
Or if a FAT32 partition present - FAT filesystem - Device USBSCSI0P1 has a read error on block xxxxxxxx -
</pre>
Sadly, no drive even branded are resistant or totally reliable, so the only solution is to try another pendrive, and possibly to repeat, until no errors.
It will give an indication on how reliable the usb drive could be.
=====Advice for various machines=====
Some of the stages involved and shown on the display in a typical AROS boot start up
<pre>
[MultiLoader]
[ELF Loader]
[Boot]
[HPET]
[Kernel:ACPI]
[Kernel:APIC-IA32]
[Kernel:SMP APIC]
[HiddStorage]
ACPI: ????
ACPI Error
[ACPI]AcpiOs????
[BattClock] Got RTC century offset 0x32 from ACPI
[PCI] Scanning bus ?
[AHCI] Sata
[Vesa] only if vesa is chosen as graphics option
[ATA] detect hd & cd drives
[ATA0?] ata-identity
[packet] fat.handler be.handler, etc.
[DOS]
[Storage:Bus]
[Storage:Controller]
[MSS] USB setup
[ehciInit] Port ? maps to controller ?
[I2C]
[ATI]
[drm] nouveau
[AROSTCP] if you have network driver prefs set up to start when booting
</pre>
; If boot fails, please give us some indication (pictures or videos) where the boot stops and the message(s) on screen.
AROS's native SATA/AHCI driver doesn't always work. If you get errors related to ahci.device, try disabling it. At your chosen boot entry in the GRUB menu, Press E, scroll down to the ahci.device entry, and add a # or ; at the start of that line or delete it with Ctrl-K. Then press Ctrl-X or F10 to boot.
If your disk isn't accessible at all with this change, you might need to change the SATA controller to IDE legacy mode in the BIOS: however, making this change will likely cause problems booting Windows on the same machine (if it's already installed). To disable ahci.device permanently, edit the text file "SYS:Arch/pc/grub/grub.cfg", and remove the ahci.device line from all boot entries you intend to use.
SATA AHCI Timeout while waiting for device to complete operations with BIOS SATA entry set to AHCI mode stops at "waiting for bootable media" screen, changing BIOS SATA setting back to IDE mode may allow it to continue booting
The ATA driver doesn't always work. If you get errors related to ata.device, try using the alternative in sys:devs/alt which is an older version. Press E when your chosen boot entry is highlighted in the GRUB menu, scroll down to the ata.device entry, and change it to read "module /Devs/Alt/ata.device". Then press Ctrl-X to boot. To make this change permanent, edit the text file "SYS:Arch/pc/grub/grub.cfg", and change the path to ata.device in all boot entries you intend to use.
Further options (removing the " ") to add to the GRUB menus to disable certain other components for debugging:
<pre>
Disable AHCI "AHCI=disable"
Disable NVME "NVME=disable"
Disable ATA: "ATA=disable"
Disable ATA: "ATA=nopci,nolegacy"
ATA safe mode: "ATA=nodma,32bit"
Disable IDE from SATA: "ATA=32bit,nosata2pata"
VIA / SIS with cdrom read io errors "ATA=nodma,nopoll"
noacpi all [PCI] devices to be invisible to AROS. disk drives work but network, sound won't
acpi=strict if there are issues with sound after boot
noioapic alternative to no acpi
Set AHCI "AHCI=force150/force300/force600"
Disable AHCI/SATA: comment out with a # ; or remove ahci.device line with Ctrl-K
Disable USB: comment out # ; or remove pciusb.device and poseidon.library lines with Ctrl-K
Disable native graphics: "nomonitors"
USB3 "USB=xhci"
</pre>
Other useful grub command line options - nomonitors, noacpi, vesahack, nopoll
Press Ctrl and X together (or F10) to exit and boot with the new options. Just experiment with different variations until successful. Those working options will need to be reused with every reboot of AROS until you can edit the grub.cfg and make it permanent i.e. install to hard disk or USB.
* If you use VESA mode, you can see the debug log if you add 'vesahack' to the command line. This will set up split-screen mode. In the upper half you'll see AROS screen, in the bottom - debug log.
* ACPI ie. PCI hardware - If you get crashes at early boot, try adding 'NOACPI' to the command line
If you're having boot issues and have a null modem cable and a spare pc, a boot log is always useful. Edit your grub line to include debug=serial but would try with an with sysdebug=all in the line later as it can cause issues booting on machines with sysdebug=all enabled (corrupts the cpu initialization).
However, if you feel you have found a genuine bug/fault in AROS that needs attention, please use the [http://sourceforge.net/tracker/?atid=439463&group_id=43586&func=browse bug submission form] to record as much information about what happened, why, and what hardware etc. you have so that people may try to assist you
For Virtual machines VMWare VirtualBox, etc., attach and press play to start the ISO image
If booting hasn't worked then it could be down to Bios/UEFI settings
=====nvme.device=====
Since 2018, nvme drives are standard on most machines
The requirement is that a PC can boot with legacy mode/BIOS at the moment - Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
This is still in testing and its' use should not be on or near precious own data
=====AHCI=====
Starting taking over since 2011 on a lot of machines
* Check that UEFI (replacement for PC BIOS) has options set to remove UEFI SecureBoot option and apply CSM
* SATA drive is set for Legacy or a mixture AHCI/IDE and not AHCI
AHCI sata can be very difficult to get working
Most Windows installs are already set to AHCI sata, changing this to a legacy IDE mode setting can help but please check if Windows will still boot. Some hardware like Lenovo laptops do not always like being set in legacy mode so only use as a last resort and aware of issues that can be caused.
Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
With a 16C/32T chip machine, disable SMT and it should boot.
=====ata.device for old BIOS's =====
Pre 2010 this was the de facto standard method of providing settings to the computer at a lower level
Some adjustments to the BIOS setup options are necessary (usually by pressing a key like DEL, F1, F2, F12 or ESC, p on the very early boot up of the computer).
*Adjust booting options like moving USB hdd, CDROM higher as it is quite often disabled or placed lower by default, i.e. USB hdd, CD/DVD are placed at the top above the hard drive. Try looking here [http://www.windowsreinstall.com/articles/bios/ Windows] or [http://www.hiren.info/pages/bios-boot-cdrom Bios] or [http://www.wikihow.com/Set-Bios-to-Boot-from-a-CD-ROM Boot] or web search "BIOS BOOT CDROM"
* At the '''SAME''' time, check if the SATA/AHCI option is set to Emulate or IDE Legacy, though this can have '''issues''' with any OS already on the hard disk. If in doubt, do nothing and seek advice.
* check that under BIOS settings you '''DO NOT''' have plug&play OS selected as Aros at this point is unable to route interrupts on its own and needs the BIOS to do that.
'''Save''' options changed at the end.
PCITool can show if the motherboard chipset is in IDE mode.
Class = 0x01 means STORAGE, Subclass = 0x01 means IDE. Also ProductID 0x3a20 resolves to non-AHCI mode in Intel ICH10 documentation.
==Installing==
We have a separate section [https://en.wikibooks.org/wiki/Aros/Platforms/x86_installing here]
We have a specific section for each CPU platform under the Specific platforms in the NavBar navigation bar on the right hand side menu
error code (-6) when using the ahci.device (has writing to disk problem but not reading) is enabled. change this line in your grub and reboot
<pre>
#module /Devs/ahci.device << disable
module /Devs/Alt/ata.device << add this line instead
</pre>
==File structure overview==
AROS' directory structure is mostly identical to AmigaOS directory structure, with some additions.
AROS: or SYS: also known as DH0: (i.e. the drive partition with AROS system) has the following simplified list of the main drawers (Amigas term for directories/folders).
{| class="wikitable"
|boot:
| grub bootloader
|----
|C:
| small apps, where AROS looks first for applications/games but will look at Tools, System afterwards
|----
|Classes:
| .class as well as datatypes
|----
|Devs:
| .device .resource and in their own drawers (folders) .audio, .hidd, network, graphics
|----
|L:
| where .handler files go
|----
|Libs:
| where .library files go
|----
|Locale:
| where help guide txt readme files go
|----
|Prefs:
| applications that adjust or setup AROS functions and capabilities
|----
|S:
| startup scripts (for the aros boot process '''not''' grub) are stored here
|----
|Storage:
| place to keep old or alternative device drivers
|----
|System:
| applications associated with AROS operating system
|----
|Tools:
| extra applications
|----
|Utilities:
| extra applications
|----
|WBStartup:
| copy applications here to autostart with needed icons, drawers, data etc
|----
|}
See [[Aros/User/DOS#Drives.2C_Files.2C_Assigns.2C_Directories|DOS manual: Drives, Files, Assigns, Directories]]
=== Filesystem ===
Whilst the kernel is the heart, the filesystem is the blood of the system they are split into two categories (only a few are supported)
<pre>
Journalling - SFS PFS3 but also NTFS ZFS XFS ext4
Non-journaling - FFS FAT32(VFAT) but also exFAT BtrFS ext2
</pre>
Filesystem options for AROS to install
* SFS default
* Professional File System PFS3 [http://eab.abime.net/showthread.php?t=52234&highlight=pfs3+free&page=13 only on motorola 68k at the moment] [https://github.com/aros-development-team/AROS/blob/e34170ea87da3b32935b60ed99d837b2b903a021/rom/filesys/pfs3/fs/mmakefile.src issues to compile on other platforms]
* FFS very old now but left in for legacy usage
Other [https://archives.arosworld.org/index.php?function=browse&cat=driver/filesystem filesystems] for storage purposes
* FAT32 favorite as most OSs support
* NTFS (can lock AROS)
* exFAT there is a [ standalone version] as well as the fuse based one
The only filesystems that really NEED defragging (i.e. disk tidy up) are from Microsoft(TM) - exFAT/VFAT/NTFS
*SFS tries to do exactly the same thing, but in certain cases it doesn't do as well as PFS. But you can defrag SFS
*PFS *minimises* the amount of fragmentation, but does not automatically defrags as it saves files to the drive
The setup of the below filesystems is usually done by the distro maintainer but if not....
<pre>
Copy L/exfat-handler L:
DOSDriver or Mountlist entry for an exFAT partition make sure that the FileSystem and Handler are set as follows:
FileSystem = exfat-handler
DosType = 0x46415458
</pre>
<pre>
Copy L/ntfs3g-handler L:
DOSDriver or Mountlist entry for an NTFS partition make sure that the FileSystem and Handler are set as follows:
FileSystem = ntfs3g-handler
DosType = 0x4e544653
Also to make a read-only mount you can set:
Control = ro
</pre>
The Smart File System (SFS) is a journaling filesystem used on Amiga computers and AmigaOS-derived operating systems. It is designed for performance, scalability and integrity, offering improvements over standard Amiga filesystems as well as some special or unique features.
SFS is written in C and was originally created and released as freeware in 1998 by John Hendrikx. After the original author left the Amiga scene in 2000, the source code to SFS was released and its development continued by Ralph Schmidt in MorphOS.
Its development has now forked; as well as the original Amiga version, there are now versions for MorphOS, AROS, AmigaOS 3, and a version for AmigaOS 4, which have different feature sets but remain compatible to each other. Versions for AROS, AmigaOS and MorphOS are based on different branches.
In addition, there is a driver for Linux to read Amiga SFS volumes, GRUB natively supports it and there are free drivers to use it from UEFI. The Linux version is [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ independent code].
SFS (Smart File System) partially defragments itself while the filesystem is in use. The defragmentation process is almost completely stateless
AROS SFS version has a 120GB partition size limit on hard disks and DVDs current 4gig size limit.
The sources for the MorphOS 64-bit version of SFS were available but no porting to AROS has happened so far due to endian issues, etc.
SFS Tools
* GUI - arSFSDoctor,
* CLI - sfscheck , [http://www.portacall.org/ sfsundelete], sfsformat, setcache hits a usability ceiling around the 10GB / 100,000 file mark,
sfscheck dh0: seek purge fraglist defragment
If there are two simultaneous file writes in progress and you reboot machine (or it locks up or crashes) you may end up with a corrupted filesystem. Although arSFSDoctor may help, you might have to copy the files to another partition, format the partition with the errors on and copy the files back.
PFS / SFS are way more advanced and much much faster than the FFS. FFS is supported for legacy reasons only.
The Professional File System (PFS) is a filesystem originally developed commercially for the Amiga and now distributed on Aminet with a 4-clause BSD license. It is a compatible successor of AmiFileSafe (AFS), with an emphasis on added reliability and speed compared to standard Amiga filesystems. It also features multi-user abilities like the older MuFS.
PFS has so many advantages including the important things, speed, the ability to recover all deleted files even simply same name by typing the command ". Deldir" convenient if done in Directory Opus, virtually deleted files are copied normally as if they had never been deleted, other convenience is to not ever invalidate the filesystem, just put it on top of the startup-sequence command "diskvalid", which automatically corrects any irregularities in the system startup; PFS also provides a device for floppy which makes them very fast and takes advantage of the full capacity of the floppy including the area dedicated to the bootloader.
The device is split into two main areas. At the beginning of the device is the metadata section, which consists of a root block, and a generic array of blocks that can be allocated to store metadata. The rest of the device is another contiguous generic array of blocks that can be allocated to store data. The metadata section usually uses a few percent of the device, depending on the size of the device.
The metadata is stored as a tree of single blocks in the metadata section. The entire directory structure is recorded in the metadata, so the data section purely contains data from files. The metadata describes the location of data in files with extents of blocks, which makes the metadata quite compact.
When a metadata update occurs, the system looks at the block containing the metadata to be changed, and copies it to a newly allocated block from the metadata section, with the change made, then it recursively changes the metadata in the block that points to that block in the same way. This way, eventually the root block needs to be changed, which causes the atomic metadata update.
The filesystem is reasonably good at keeping files unfragmented, although there is a defragmentation tool available which will work on an online filesystem ie whilst being used.
It was the first filesystem to introduce the concept of the Recycle Bin natively at filesystem-level to the Amiga, holding the last few deleted files in a hidden directory on the disk root.
PFS version 5.3 was developed in C and a small portion of assembly code by Michiel Pelt. There are endian issues to be overcome and adapting the small amount of m68k to C before use on intel based machines, etc.
Autoupdate of files in a directory is already implemented in Wanderer, but not all file systems handle dos.library/StartNotify() in its full extent. It seems to work correctly in Ram Disk (thanks to AmberRAM handler), and it also works on SFS formatted devices. Other file systems might not yet have it implemented correctly though.
The PC equivalent of the Amiga's RDB is the master boot record (MBR).
===Installing Applications===
The typical means to install applications under AROS/AmigaOS involves simply copying/extracting the archive (.zip .lha .rar .tar.gz) file containing the applications files to your own desired location i.e. drawer/folder. Once extracted, launching it by double clicking on an icon (recommended) or using the shell (alternative). Generally, this is on a separate partition from your AROS system files, however in reality it can be any location - including RAM: if you don't want it staying around too long especially when you switch off.
At some time in the future it may be desirable for AROS to have a package-manager like subsystem able to retrieve information online about packages available for AROS and whether they update anything you currently have installed, however at the moment no such ability exists.
===User Data files===
AmigaOS has no notion of a default location to store user data files, and presently neither does AROS - though it may be desirable at some time to provide a common start location.
Some people, have extra small FAT32 partition(s) using HDToolbox, and not Qparted, to store data especially if a reinstall is ever needed. And then setup the usual Sys: (DH0:) and maybe Work: (DH1:) / Live USB (DU0:) and maybe Briefcase (DU1:) partitions.
===User Environment configuration files===
AmigaOS/AROS stores persistent system configuration data in directory assigned to ENVARC:. This, by default, points to SYS:Prefs/EnvArc.
During boot a copy is made to another assign, ENV:, which is for runtime usage. Changes to the files here will not survive a reboot.
Setting the env variables is generally done by applications themselves, or when necessary by the user using the SetEnv command. SetEnv has a SAVE switch to force the persistent copy in ENVARC: to be written also for when you are sure the change should be permanent.
Under the standard installation of AmigaOS style OSs, ENVARC: is copied to ENV: upon startup, which, if you have a hard drive installation, is in RAM:, hence, ENV: ends up being RAM:Env.
ENVARC: is the Environment Archive, which is the permanent copy of ENV:, which is the Environment. It's roughly like the Registry in Windoze.
Most programs do (and all should) store their settings in ENVARC: somewhere, and load them from ENV:. The effect of this can be seen in the Preference editors. If you Save your preferences, they go in ENVARC: and ENV:. If you click Use, they only go in ENV:. If you reboot, normally, anything saved to ENV: is lost, and is replaced with a copy of what is in ENVARC:.
you can set the default public screen for any tool started from a cli with the PUBSCREEN variable. So open the pubscreen, set PUBSCREEN to the name and start newcli for example, then the new cli window (and all following windows opened from that window) will appear on that public screen.
===Drivers===
For certain hardware, e.g audio, networking and , there is no auto setup. Just like the original Amiga OS.
For audio, use AHI in the Prefs folder to set Music and at least Unit 0 with the appropriate driver and press Save. For ethernet and wifi, please use SYS:Prefs/Network
All hardware support is placed in the Devs drawer (folder/directory). The network drivers <something.device> go in the Networks sub-drawer. Audio drivers <something.audio> are put in the AHI sub-drawer. Graphics drivers <something.hidd> are put in the Drivers sub-drawer.
==Configuring==
AROS has mainly decided on a MUI-like requester&menu clone called Zune so changing the background, icons, font, menus can be done with SYS:Prefs/Zune
AROS has several desktop GUI front ends like
* DOpus5 Magellan II, Wanderer and Scalos (medium)
* AROS Workbench, Workbook (smaller)
File / Directory managers like Dopus4, MCAmiga,
App Launch Shortcuts like FKey, BoingIconBar, right mouse click on magellan, wanderer desktop, Amistart, etc.
General usability decisions - Prefs/IControl, Prefs/Locale, Prefs/Input, Prefs/Fonts,
Select an icon with left mouse button and then right click the mouse button and selecting Icon -> Information gains access to the tooltypes tab where information can be edited
CLI in icon's tooltypes means 'run it as if it was run from shell'
If, on the other hand, the WB parameter (or no parameter) is present in Tooltypes, Wanderer will execute the binary and, if provided, the options included in Tooltypes.
WBxCLI is very useful for adding options to DOS Commands.
Important: AROS has a different way of managing icons. If you have an executable file, you will never be able to add a project icon. AROS will automatically recognise that it is an executable file and will transform the icon into a tool icon.
Icons are typically now .png pictures renamed as .info e.g. so Office application name would have a Office.png renamed as Office.info or MyApp.png as MyApp.info, etc.
Leave Out menu option to leave app icon on desktop
To select multiple icons and save their positions, click on the first icon and after while you hold the Shift key down select further icons and don't release it before SnapShot is finished. You can also select a whole group of icons by pressing the LMB at the top left of the icons and while keeping the LMB down moving the power towards the bottom right. A expanding bounding box will appear and all the icons within it will be selected.
Clean Up menu option (right mouse button -> Icons) rearranges icons in a drawer or disk window into a neater condition. To use, open the window to rearrange and select Clean Up. To keep the icons in the new positions, select all the icons (shift key or mouse selection) and select 'Snapshot' and then Window and then again with All.
In DOpus5, Scalos, wanderer, most files have an icon file associated with it. To change the default tool, select Icon menu, Information, and change the default tool string. For example, you could use Multiview, Editor and so on for most text, graphics and some sound files as long as the appropriate Datatype classes are installed. For scripts, set the tool to C:IconX
We have new Icon edit tools in progress but if you need to...
C:Join Image1.png Image2.png TO MyFile.info
is enough to make a dual state icon from two png images. You can then use Wanderer's menu Icon/Information on it to edit its fields and tooltypes.
[https://archives.arosworld.org/index.php?function=browse&cat=graphics/icon AISS toolbar images] unpack unarc them into RAM: and copy Images directory to SYS:Prefs/Presets/ AISS icons are looked for in PROGDIR:, PROGDIR:Images, SYS:Prefs/Presets/Images and then in TBImages: according to Open Amiga guidelines.
there is Demos/iconscale which could be launched from S:User-Startup with two arguments, telling it the horizontal and vertical size. IE something like
Demos/iconscale 40 40
It will shrink icons... not sure if it will be very nice though. it doesn't work for the icons on the main desktop.
there is an option to scale an icon to a bounding box afair, try iconsize followed by two numbers, like:
iconsize 32 32
Is there any way in AROS to change an icon type from Project to Tool or vice versa?
Either the SIT option of [ ProcessIcon], or the TYPE option of HandleInfo (not sure if this one works at all, please test with care).
processicon sys:pathoftheicon SIT=Project
SIT Set type of ICON. Allowed types are: "Disk", "Drawer", "Tool", "Project", "Garbage", "Device", "Kick" and "AppIcon".
Btw, are your icons, the #?.info files, writable, is the W flag set ?
'''Decoration''' is Aros' way to provides a way to hide the old Workbench 3.1 style of windows and screens. In Prefs/Appearance some decorative theming elements need work
Themes - SYS:Prefs -> Appearance
The default content of Prefs/Env-Archive/SYS/themes.var should be "themes:ice" but can be changed via the Appearance prefs, please do NOT click the Use button. Its useless. As you know, it will ask for the theme volume. Just pick the theme you want, click on Save, then reboot.
* Decoration is on. Any time trying to change theme, you get: "Please insert volume Theme: in any drive"?
You could check if you find SYS:System/Themes or if it is missing. Then you could open startup-sequence which you can find in drawer "S". There should be a line:
Assign THEMES: SYS:SYSTEM/THEMES >Nil:
This does the trick.
Open a shell and run:
Assign THEMES: SYS:SYSTEM/THEMES
Than start the Theme prefs again... this should work
* The theme is the only thing that could slow the system a bit, but it's not that performance impacting on most uses, and you can switch it off completely. Remove C:Decoration from the bottom of the file sys:s/startup-sequence.
In each theme directory is
*Env-Archive -> Zune -> global.prefs
*images -> Gadgets -> 20x20 pngs for Down etc
*menu -AmigaKey - Background - Checkmark - SubMenu and config
*system - Arrowdown, Arrowleft, Arrowright, Arrowup, etc
There is an [https://archives.arosworld.org/index.php?function=browse&cat=graphics/theme ALua/Zulu script] built for faster Wanderer skin management. You can modify config files, install new (wdz format/zipped skin files) and delete skins via the Theme Manager. This has not been updated in a long time and may not work.
Certain features are added if from Tools/Commodities like Blanker screensaver, ClickToFront and DepthMenu with .info icons are selected and dragged to /WBStartup folder
Most apps can be autostarted by copying into SYS:WBStartup directory folder
e.g. WeatherBar.zip can be downloaded, unzip and the contents of the zip copied to wbstartup folder
ClicktoFront and .info to SYS:WBStartup so always be activated when turning on the computer
or add a text line to user-startup is SYS:S (scripts version of wbstartup)
e.g. standard Amiga / AROS does not allow clicking of background windows to come to the front to make it easy to get to the window you need but it has the ability if these apps are copied again to WBStartUp or are added to SYS:S/user-startup script
run QUIET sys:Tools/Commodities/ClickToFront >Nil:
run QUIET sys:Tools/Commodities/DepthMenu >Nil:
run QUIET sys:Tools/Commodities/Blanker seconds=300 >Nil:
Exchange controls Commodities and can be opened with alt, ctrl, h
*AltKeyQ uses left Alt key to add strange letters
*AutoPoint
*Blanker screensaver
*ClickToFront allows windows to be easily brought to the front
*DepthMenu adds menu to select window easily
*NoCapsKey
*Opaque
*FKey - Although there are heaps of docks, menus and other launcher programs on the Amiga like OSs, FKey has got to be one of the quickest once learnt ways to launch programs, and it comes with the OS. In SYS:Tools/Commodities, the FKey commodity (Ctrl Alt F) allows you to make actions assigned to some combinations of keys
<pre>
ALT TAB Cycle Windows
Cycle Screens
Enlarge Window
Shrink Window
Toggle Window Size
Insert Text
Run Program
Run Arexx Script
</pre>
e.g.
<pre>
LAmiga F1 = Avail Flush
LAmiga F2 = Open Prefs
LAmiga F3 = Finder
Alt Tab = Cycle Windows
LAmiga Tab or M = Cycle Screens
Alt Up arrow = Enlarge Window
Alt Down arrow = Shrink Window
Alt Home = Toggle Window Size
= Insert Text
LAmiga e = Run Program
= Run Arexx Script
</pre>
If your FKey GUI pops up when you start your Workbench up and you don't want it to, click once on the icon, go to the Icons-Information in the menu and make sure it has the tooltype set "CX_POPUP=NO".
Now let's launch it and assign the locale switching. After you double-click on FKey icon, launch the Exchange, choose the FKey from list and click the Show button. This will invoke the FKey window. You can see the ALT TAB in list assigned to window switching. Now enter the first key combination, say, ALT Z and go to the right panel. Choose Launch the program from pulldown menu and enter SYS:Prefs/Input as an argument. Append the USE switch and english preset name to the string as shown:
SYS:Prefs/Input USE SYS:Prefs/Presets/english
Click on the New Button to add the another combination. Now set the combination for your locale as shown above, replacing English name with your preset name. Click New button again and then Save Settings. Now you can use defined combinations to switch the layouts.
There is a system wide ARexx script capability (based on regina) that can manage many file manipulation task(s) but this would work only with those program that support [https://en.wikibooks.org/wiki/Aros/Developer/Docs/Rexx ARexx] like
*Desktop - DOpus5, Scalos
*Dock - FKey,
*Files - Multiview, DOpus4,
*Internet Apps - Odyssey, WookieChat,
*General Apps -
the shell can be modified with escape strings but not needed in most cases
Common Keyboard Shortcuts
<pre>
RAlt Right Alt Key
LAlt Left Alt Key
RWinKey Right Windows Key
LWinKey Left Windows Key
RAmiga Right Amiga Key (if one)
LAmiga Left Amiga Key (if one)
</pre>
;Bootup Options
:Spacebar during boot, enters the bootmenu which allows a boot without startup sequence, etc
;Left Click
:LAmiga = LWinKey = F11
;Right Click
:RAmiga = Help = F12
;Mark
:RAmiga and B
;Cut
:RAmiga and X
;Copy
:RAmiga and C
;Paste
:RAmiga and V
;Search
:RAmiga and S
;Mouse Movement
LAmiga and together with arrow keys - shift as well at the same time as well to move faster
;Mouse Selection
LAmiga and LAlt to select
;Screen Switching
LAmiga and M or N
;HELP key
Can sometimes be mapped to F11 but can be changed via FKey
ComKeyRemapper or AmigaKeyremapper could swap RAmiga to another key press
===DOpus 5 Directory Opus Magellan II===
Dopus 5.x is a whole desktop replacement on the Amiga Workbench (Desktop)
DirectoryOpus app will assign DOpus5: to it's PROGDIR: automatically but if not add the below (edit SYS:System to suit where Dopus5 was installed) to your startup-sequence
<pre>
Assign DOpus5: SYS:System/DOpus5
DOpus5:DirectoryOpus
;DOpus5:C/LoadDB
</pre>
Left mouse button clicked twice on the desktop background brings up the Device List window.
Green strip notifies SRCE (source) and if another is open it will be red for DEST (destination). clicking on the red strip changes to green
Word list of actions with a left mouse click on the DOWN Arrow and directory stuff with < button which mirrors the icons at the top of each lister
single-key hotkeys? exactly the same as in dopus4, edit your functions (button bank, toolbar, menus etc.) and under the flags gadget is a key gadget, just click in it and press the key you want to use.
As for the extra text field... try turning off Extended lister key selection in environment / miscellaneous.
Shift and click on the icon - runs the icon
DOpus5 Magellan 2 Directory folder drawer structure
<pre>
ARexx - Arexx scripts .rexx and .dopus5 to perform tasks
Buttons -
Commands -
Desktop -
Environment - two environment files bundled:
default gets loaded if you run DOpus as a normal app
workbench gets loaded if you run DOpus as a WB Replacement (with LoadDB on startup)
Filetypes -
Groups -
Icons -
Images -
Modules - compiled tasks
Settings -
Sounds -
Themes -
WBStartup - Use this if standard SYS:WBStartup gives cannot wait error messages
</pre>
Settings -> Environment -> Display -> Workbench (Use)
*Settings -> Clock (add to title bar as well as the date)
*Toolbar -> Editor (Right Win Key together with 1) for Copy, Move, Delete, etc above the Device List
*Menu -> (Right Win Key together with 2)
*Buttons -> Editor (Right Win Key together with 3)
*Settings -> Environment (Right Win key together with 4) for Backgrounds, etc
*File Types -> (Right Win key together with 5)
*User Menus -> (Right Win key together with 6)
*Hotkeys -> Setup for quick shortcut keypresses (Right Win Key together with 7)
*Scripts -> (Right Win key together with 8)
*Icon Positioning -> (Right Win key together with 9)
Each Dopus5 theme are stored in a separate directory, named appropriately, which contains further sub directories
* Font (amiga bitmap fonts)
* Screens (jpg or any picture supported by datatypes but not animations)
* Sounds (wav but not iff 8svx )
* Icons (png newicons glowicons )
* Patterns (iff jpg png )
Just use wildcards in background filenames and you get a different picture every reboot
For example, configure in Environment -> Backgrounds -> Desktop something like this:
<pre>
Work:Pictures/Backgrounds/#?
...or
Work:Pictures/back#?.iff
...etc...
</pre>
[https://aminet.net/util/dopus arcdir and themes]
If you want to change the backdrop pic after a period of time, paste below into a text file called dopusrandbg.rexx and place in DOPus5:ARexx
<pre>
/* Changes DOpus background image forever
Start with:
Run >NIL: RX dopusrandbg.rexx
*/
if ~show("L", "rexxsupport.library") then do
if ~addlib("rexxsupport.library", 0, -30,0) then exit 10
end
/* Configure these two lines for your needs: */
minutes=1
picpath="Work:Pics/#?.iff"
address DOPUS.1
do forever
call delay 3000*minutes
dopus set background '"'picpath'"' desktop center custom
dopus refresh background custom
end
</pre>
If you don't want to use/open rexxsupport.library just for DELAY() then use the DOS Wait command
<pre>
/* random diropus backdrop changer */
/* by paul trauth, 1999 */
/* to do: non-repeatable randomness? */
options results
parse arg path
address DOPUS.1
/* get current backdrop pattern so it actually changes */
dopus query background desktop custom
currentpatt=result
lastslash=lastpos('/',currentpatt)
currentpatt=substr(currentpatt,lastslash+1,(pos('"',currentpatt,2)-lastslash-1))
dir=showdir(path,'FILE','/')
num=0
do while dir~=''
where=pos('/',dir)
if where>0 then do
file=left(dir,where-1)
dir=right(dir,length(dir)-where)
end
else do
file=dir
dir=''
end
if left(file,1) ~='.' & file~=currentpatt then
do
pics.num=file
num=num+1
end
end
which=random(0,num-1,time(s))
newbg='"'||path||'/'||pics.which||'"'
dopus set background newbg desktop tile precision exact
dopus set background on
dopus refresh background
</pre>
Clock format commands available are defined by locale. They are:
<pre>
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
</pre>
like %a %d-%b-%y %H:%M or
A WB ARexx interface, you could enter a cli command as a menu item to open a WB drawer like this...
RX "address WORKBENCH;WINDOW 'device:drawer' OPEN"
Where device:drawer is replaced by the path of the drawer to open.
The ARexx script would be capable to manage such a task but this would work only with those program that support ARexx
<pre>
dopus addappicon
dopus addtrap
dopus back
dopus checkdesktop
dopus clear
dopus command
dopus desktoppopup
dopus error
dopus front
dopus getdesktop
dopus getfiletype
dopus getstring
dopus matchdesktop
dopus progress
dopus query background, font, palette, pens
dopus read
dopus refresh all, background, icons, lister
dopus remappicon
dopus remtrap
dopus request
dopus script
dopus screen
dopus send
dopus set background, font, palette, pens
dopus setappicon
dopus version
</pre>
<pre>
lister add
lister addstem
lister copy
lister clear value
lister clearcaches
lister close
lister empty
lister findcache
lister getstring
lister iconify
lister new
lister query active all, dest source
lister query abort, busy, case, dirs, display, entries, entry, files, flags, handler, header, hide
lister query label, lock, mode, namelength, numdirs, numentries, numfiles, numseldirs, numselfiles
lister query path, proc, position, seldirs, selentries, selfiles, separate, show, sort,
lister query title, toolbar, value, visible, window
lister read
lister refresh
lister reload
lister remove
lister request
lister set busy, case, dest, display, field, flags, handler, header, hide, label, lock, mode
lister set namelength, newprogress, off, path, position, progress, separate, show, sort, source
lister set title, toolbar, value, variable
lister select
lister wait
</pre>
The '''command''' allows you to call internal DOpus commands from an ARexx script
<pre>
command all
command wait copy
command read s:startup-sequence
command source 12345 makedir name noicon
</pre>
*SFTP secure encrypted comms over internet using libssh2 and zlib (different protocol to the two below) on port 22
*FTPS secured with https like security on port 21
*FTP not secure and unencrypted protocol over internet on port 21 (should not be used today on the internet but for your own server)
===Wanderer ===
Wanderer prefs in the prefs drawer - Appearance tab and Workbench icon allows backgrounds (wallpapers) icon text sizes, colors, etc but cannot use #? or *.* in the backgrounds file entry to randomly choose pictures - [https://developers.google.com/speed/webp/docs/riff_container webp riff container] issues with this format but Multiview has none.
Enable the bar, you need to edit the text file ‘statusbar.prefs’. The change is simple: just change “False” to ‘True’.
Prefs/Env-Archive/SYS/Wanderer/statusbar.prefs
===Scalos===
[https://web.archive.org/web/20180922220139/http://scalos.noname.fr/ Scalos] is not an OS replacement, it's a Workbench replacement. It replaces the desktop and graphical file management components.
Scalos is 100% Workbench replacement with most functions working like the original Workbench ones. Undo and Redo available for most window and icon operations. Fully multitasking so every window has its own task. While loading icons, any window function (e.g. Drag&Drop) is available.
24bit color support with window patterns - Unlimited and easily configurable via tooltypes. Optimised backgroundpatterns routine so patterns can be tiled, centred or even scaled to fit into the windows. Live updating window scrolling - Supports middle mouse button panning and drawer (folder) windows can be iconified on the desktop.
Icon imagetypes with all types are supported such as backfill or complement. Configurable surrounding iconborder. Icon support also visually highlights files which are soft-links in the file system. Icon dragging is more stable and far less flickery on graphics cards. Whilst dragging, icons are displayed with text and they can become transparent over anything where they can be dropped.
Single-window lasso mode, with scrolling window contents invoked by dragging mouse with configurable qualifier key. Text icon lasso selection used to ignore "Name column selects text icons" flag. Support for backfilled thumbnail icons, with selectable color and transparency. Added option to always generate square thumbnail icons with preview icons for images - Thumbnails can be permanently saved in icons.
Supports PNG icons with alpha channel and real transparency and displays OS3.5 GlowIcons and are all scalable. Iconborders with variations (normal, shadowed, outlined).
Completely configurable, filetype-specific user-definable popup menus and tooltips. Plugin system to exchange or add features and can enhance the Workbench and make it more configurable.
Filetype plugins to display filetype-specific information. - Currently, EXIF information viewer for JPEG images is included. Plugin included for 100% support of OS3.9 Workbench features. Plugin included for AREXX API compatible to OS3.9 Workbench.
Online update with updater.module
Scalos works also as a Workbench replacement. In this case the 'emulation mode' has to be set by using Scalos' own version of LoadWB and offers
* Scalos uses the Workbench Screen for its windows instead opening a new one
* AppIcon, AppMenuItem, AppWindow functions are redirected to Scalos
* all Programs placed in "WBStartup" should start
* The Screen will be reopened in case of changes in ScreenMode and Palette settings
<pre>
v1.0 (V39.201) - November 1999
v1.1 (V39.212) - December 1999
v1.2b (39.220) - June 6, 2000
v1.2d (39.222) - 2000 (latest public beta executable)
v1.3 (40.7) (beta) - August 2, 2001
v1.3 (40.22) - September 25, 2002
v1.4 (40.32) (beta) March 31, 2005
v1.6 (41.4) - March 27, 2007
v1.7 (41.5) - August 12, 2007
v1.8 (41.6) - March 12, 2009
v1.9 (41.7) (beta) - March 15, 2010
v1.9 (41.8) (RC1) - August 25, 2012 open source
v1.9.2 (41.10) Deadwoods' AROS late 2022 32bit and 64bit build unifying the code base of ` for AROS x86 ABIv0, AROS x86_64 ABIv11 and AROS m68k
</pre>
Distros may have Scalos files under SYS:System/Scalos or Extras:Scalos. Known [https://github.com/deadwood2/AROS/issues/75 bug list],
Certain files like Menu13.prefs, Palette13.prefs, Pattern.prefs and scalos.prefs need to be in SYS:Prefs/Env-Archive/Scalos they can be found in Scalos:Storage/envarc and country drawer
or run the "Scalos Menu" preferences program. Note if already setup with sub-menu entries and then re-save your menu prefs as it will now generate a new/overwrite prefs file called "Menu13.prefs" in "envarc:scalos/". The same is also required for the new Palette prefs update, click 'Save' and a "Palette13.prefs" file will be saved in to "envarc:scalos/" directory.
<pre>
ASSIGN Scalos: SYS:xxx/xxx DEFER
ASSIGN Libs: Scalos:Libs add
;ASSIGN SYS:Devs/Datatypes Scalos:Devs/Datatypes add
Assign Theme: Scalos:Themes/Default_Theme add
Assign Locale: Scalos:Locale add
Protect Scalos:Tools/browse.script s add quiet
Protect Scalos:Tools/OpenShell s add quiet
Protect Scalos:Tools/run.script s add quiet
run Scalos:Tools/LoadWB
;Scalos:Scalos
</pre>
Add the above to SYS:S/startup-sequence or SYS:S/user-startup '''before any Wanderer entries'''
In the prefs drawer (folder) is the big prefs app Scalos_Prefs which covers these user setup areas
<pre>
About Scalos
Paths - should be preset
Startup - WBStartup drawer contents should auto run on each startup
Desktop - edit titlebar, icon layout and in misc, auto leave-out (drag icon to desktop)
Icons -
Drag and Drop -
Windows -
Text Windows - in misc, drawer sorting at start of listing if needed
TrueType Fonts - use Truetype fonts rather than system ones
Miscellaneous -
Plugins - after adding oop/title_clock.plugin %ti %da does not work, maybe needs ASCII .prefs added
Modules - ??
Menu - setup for MainMenu and PopupsMenu with New Menu, RE Name, Key: shortcut, Command Properties
FileTypes - already added def_Project icons and def_Disk (hdd sdd cd dvd etc) support
PopupMenu - tweak how popups appear
Pattern - Wallpaper backgrounds with Type DE, each pattern in the list can be edited, Save as Pattern.pre
Palette - change the color of things , Save as Palette.pre
</pre>
Scalos_Prefs - Pattern - Minimum options to be changed are
*DE Desktop/Background
*SC Screen
*TW Window/TextBackground ie Text listing showing if icon type not recognised
*IW Window/Background ie Icons showing
Workflow - In "Pattern List" tab, select New - choose a picture, highlight in list, click in number box under New button and slide to another number, click on "Defaults" tab and adjust Pattern numbers slider to choose right picture for each of the above options - Click "Pattern List" tab to check eveything is OK and click Save
Pattern List tab on Patterns Page - Allows you to compile a list of pictures (one at a time rather than a whole folder e.g. with #? or *.*), assigning a number Nr to one or more of them for easy reference. Using this number you will be able to assign the pictures to specific windows on the Defaults tab Page. If multiple pictures have the same number, one of the pictures will be chosen randomly. This will allow you to have random desktop pictures, random window backdrops etc.
Defaults tab on Patterns Page - Here you can set the defaults for the background pictures for the Desktop, Screen, Window and/or Text Mode throughout Scalos.
Randomize every time [check box] - Usually Pictures with the same number will be randomly selected as soon as the configuration loads. If this option is set, the picture will be selected as soon as a window with the same number assignment is opened.
*Fit size: The picture will be resized to the dimension of the new window.You *MUST* have set GUIGfx on. asyncron layout: Pictures will be loaded and rendered while the windows opens (Like original Workbench). If this function is 'off', pictures will always be loaded before opening the windows.
*Use friendbitmap : The picture is present twice in memory for best speed. This option has no effect if V43 picture.datatype or GUIGfx are used. Always relayout: If "Fit size" is set, the picture will be scaled everytime the window's dimensions change.
*Randomize everytime: Usually Pictures with the same number will be randomly selected as soon as the If more pictures have the same number, one of them will be chosen randomly.
Patternlist New/Delete : Add a new picture. After that you should assign a number to it. The picture will be rendered as tiles. configuration loads. If this option is set, the picture
Asyncron-Task priority: You can set the CPU priority for the Task if "asyncron layout" is set.
<pre>
Desktop: Number of the Picture for the main window.
Screen: Number of the picture for the Scalos-Screen.
Window: Number of the picture for the Scalos-windows.
TextMode: Number of the picture for the Scalos-windows in Text Mode.
</pre>
Popup Menu preferences fully configurable menus (includes ToolsDaemon and ParM launch apps import), including support for context-sensitive Popup menus configs for top pull down menus for apps, etc.
Workflow - Scalos_Prefs then Menu, New Item, New Command add name at top then in Command Properties e.g. add Workbench and location e.g. DOpus:DOpus4 for apps Command for c apps or Rexx for scripts or Plugin for or AmigaDos for modules
<pre>
DESCRIPTION NAME/A This is the title that is displayed in the top line of any popup menu
INCLUDE NAME/A Name of file to be included. Path can be relative to "Scalos:FileTypes"
POPUPMENU Starts the popup menu description section for this filetype.
</pre>
The following Subcommands are allowed inside popup menus:
<pre>
SUBMENU "NAME/A"
ENDSUBMENU
MENUENTRY "NAME/A,KEY/K,DEFAULTACTION/S"
ENDMENUENTRY
INTERNALCMD "NAME/A"
WBCMD "NAME/A,STACK/K/N,WBARGS/S,PRI=PRIORITY/K/N"
AREXXCMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
CLICMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
ICONWINDOWCMD "NAME/A"
PLUGINCMD
MENUSEPARATOR
ENDPOPUPMENU
TOOLTIP
ENDTOOLTIP
</pre>
<pre>
Starts the tooltip description section for this filetype. The following Subcommands are allowed inside popup menus:
GROUP "ORIENTATION/K"
ENDGROUP
MEMBER "HIDE/K"
ENDMEMBER
HBAR
STRING "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K"
SPACE "SIZE/N/A"
DTIMAGE "FILENAME/A"
</pre>
Each theme drawer (folder) has these further folders
<pre>
About -
Desktop -
FileTrans -
FileType -
Icons -
Menu -
Modules -
PointerIcons -
Prefs -
Sound -
Window -
</pre>
*Plugins
<pre>
devicefilter.plugin
persist.plugin should a crash or reboot occur - next time Scalos started, all windows re-opened
title_clock.plugin add digital clock to title see more below
title_envvar.plugin %ev, which can be used to display the value (a string) of the variable in the titlebar
title_freepens.plugin
volumegauge.plugin
wb39.plugin
wbrexx.plugin plugin adds a Workbench 3.5+ compatible AREXX interface to Scalos internals
xtwindows.plugin left or right ALT or left or right SHIFT keys when open/close windows
filetype.plugin then run FileTypes-prefs and customize the filetypes (eg import from a DefIcons-brainfile)
menu.plugin
</pre>
*Modules - delete, empty_trashcan, execute, find, format_disk, information, iconproperties, newdrawer, reboot, rename, systeminfo, windowproperties
*Tools - scripts like LoadWB, quit.rexx, open_volume.rexx,
In Scalos_Prefs->Filetype->Recognition you can define the filetypes and on "Action" you define specific context menu for all filetypes defined in recognition (similar to magellan)
there is the same you must show all first (list is only limited) so you created a file type AAABBB, you need to have def_AAABBB icon
Associating files with "Scalos_FileTypes" is very simple, practically it is very similar to Dopus4, first you create the Def_icons to assign to the file type (will be seen automatically ), then run "Scalos_FileTypes" you add the extension, fill in the descriptor (MATCH or PATTERN etc..) and save
then you create an appropriate entry in the list and rename it, if def icon exists it is shown. Below you can define how files are identified. Use "pattern", similar to magellan to identify file by ending. Then you click on the shown icon and define in it what program is used when you double-klick on it and save it. On the tab action you can define popup menu for it.
defined all archive types from XAD in "filetypes". If you change to "action" and click on "archive" you can define the context menu that is shown if you do not define a specific context menu for a filetype
Reset to Default in Scalos_Prefs resets all settings so '''BEWARE'''
<pre>
The Scalos desktop screen titlebar may be configured using the main Scalos Preference program. This oop/time_clock plugin adds some additional placeholders:
%ti, displays the current time in the default Locale format. e.g. "10:43:37"
%da, displays the date in the default Locale format. e.g. "Saturday 14 July 2001"
Using the supplied prefs program for the plugin, or editing the ASCII file ENVARC:Scalos/title_clock.prefs you can use the following standard Amiga Locale values to change the formatting
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%C - same as "%a %b %e %T %Z %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%n - insert a linefeed
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%t - insert a tab character
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
like %d %m %y or %a %d %B %Y %p
</pre>
Shutdown -> right mouse button Scalos, About, Reboot, Shutdown
ToolTypes can be added to the Scalos.info icon like
*SCALOS_PATTERNNO=<number> : background image matching the number
*SCALOS_NOTEXT : The Icon will be drawn without Text.
*SCALOS_NODRAG : The Icon will not be draggable. Its position will be fixed.
*Module iconproperties - Added SCALOS_BROWSERMODE tooltype support
runcommand parameters... in which case:
<pre>
%p = parameters
%w = directory path
%d = device-name
%% = literal percentage token
</pre>
With the help of the wbrexx.plugin Scalos gains support for more of the compatible arexx API
If an arexx command produces an error you will find the error code placed in the WORKBENCH.LASTERROR variable.
ACTIVATEWINDOW
<pre>
/* Activate the root window */
ADDRESS workbench
ACTIVATEWINDOW root
/* Activate the "Work:" partition's window if already open*/
ACTIVATEWINDOW "Work:"
</pre>
CHANGEWINDOW
<pre>
/* Change the root window; move it to position 10,30. * and change its size to 200100 pixels */
ADDRESS workbench
CHANGEWINDOW root LEFTEDGE 10 TOPEDGE 30 WIDTH 200 HEIGHT 100
/* Change the currently active window */
CHANGEWINDOW active 20 40 200 100
</pre>
Most of Scalos' issue are due to the flexibility of its' user configuring nature but if
The sort menu plugin needs to be ported from ASM to C.
IIRC Scalos has a command line option to fully replace Workbench/Wanderer.
The Theme: assign is used by both Wanderer and Scalos but I didn't have any problems using both at the same time.
The Program will be started from the Shell.
If "WB Args" is set, with the Argument "%p" will be replaced by the path of the activated Icons. The Program will started with the specified Stack value.
IconWindow: Scalos opens the window of the specified path.
PlugIn: Starts a Scalos Menu-PlugIn.
If a Menu Item with empty name is specified, Scalos displays a separator line.
It's possible to Drag&Drop an Icon in the Configuration Window. All values will be set accordingly. Entries may be dragged across the list.
Mac-like selection : This function activates a multiselection method used on MacOS or Win95. Don't have to hold down shift to drag them. Clicking on an already activated icon will
not deselect all other icons.
MMB move: The window contents may be moved using the middle mouse button.
WindowPopup title only: PopupMenu for windows can be opened only on window's title bars.
FullBench: Screen-Titles removed and Main Window set Full Size.
Scalos Prefs. Go to Settings->Scalos->Prefs and then the Misc section. Remove the tick against Full Bench. If you've enabled it, the titlebar will disappear when you select backdrop.
Default Icons saveable : The icons which Scalos generates if "show all files" is enabled, can now be saved
using "snapshot" menu option. load DefDisk first : Try to read the icons first from the DefIcons Path before using disk info.
Hide hidden files : If this function is activated all files or directories where the "hide" flag is set will not be shown.
Many of my Icons display more than once on the screen, while on the workbench all seems ok.
The Workbench filters double displayed icons, Scalos does not. Solution: please edit the ".backdrop" file and clear double lines.
Background images not scaled. GUIGfx option not set or guigfx.library and/or render.library not installed.
If working with CD's causes crashs or Scalos doesn't work correctly.
Most Filesystems doesn't support the ExAll function correctly. Disable "Use ExAll" in Scalos prefs.
Scalos doesn't start any program in the WBStartup. WBStartup Path may be set wrongly or Scalos was not started in Emulation Mode (LoadWB etc)
Some programs will not startup with error message "has not returned, wait some more"? and "unable to open your tool"
need a def_icon with the same name predefined, then create an appropriate entry in the list and rename it, if def icon exists it is shown. Below this can define how files are identified.
* either "pattern", similar to magellan to identify file by ending
* or
Then click on the shown icon and define in it what program is used when you double-click on it and save it. On the tab action you can define popup menu for it. All in all handling is of course different to magellan but can do similar
For the RAM Icon, to obtain this you have only to copy the icon in the Icon Path as "RAM.info" or "Ram Disk.info". All functions will automatically be performed
sometimes cut into half or quarters when scrolled off screen or drawers moved - settings issue probably
Sometimes leaves initial drawer window imprint on desktop when moved - settings issue
Scalos AROS released a [https://github.com/deadwood2/contrib/tree/master/scalos new build V2022-07-21] with the following changes noted:
<pre>
Fixed:
Numerous crashes when working on 64-bit with 64-bit heap
Wrong background color of Scalos logo on Scalos splash window
Backgroung image of Scalos splash window and Scalos About window is not visible
Icon labels on desktop and in drawer windows are displayed using Topaz instead of Arial font
Font.prefs are not being loaded on 64-bit
Font.prefs are being wrongly saved on 64-bit
scalos.prefs are not being loaded on x86 and x86_64, scalos is using always default preference
scalos.prefs are being saved on x86 and x86_64 in format not compatible with m68k
NewPopupmenu.prefs is wrongly written
Plugins are not loading at Scalos startup
wbrexx.plugin is crashing at startup on 64-bit
Multiple controls missing on Scalos Prefs/Icons page
System crash when clicking on def icon image on FileTypes Prefs/Recognition page
Status bar, control bar, buttons sometimes don't have images displayed
Buttons in Scalos About window have white corners rendered where they should be transparent
Crash when leaving out an icon
Crash when adding a User-defined Button to Control bar without setting it's properties in Scalos Prefs
Crash when removing any button from Control bar in Scalos Prefs
Scalos Prefs allows editing TTEngine font properties when TTEngine is not present causing crash in Icons/Labels and Text Windows/Fonts pages
deficons.prefs are not being loaded on x86 and x86_64
Reset to default in FileType Prefs and Save does not save preferences
Won't fix:
Scrollbars visible on titles of TrueType Fonts, PopupMenu, Menu, FileTypes, Pallette and Pattern pages of Scalos Preferences
Not fixed:
Wrong rendering on DualPNG icons
Refreshing drawer windows is slow
Starting Prefs/Locale or Prefs/Input from Scalos causes other preferences to fail
Desktop wallpaper is damaged where Splay window was displayed
When started from Wanderer, after saving Scalos Prefs, reload does not re-open main Scalos window
Difference in behavior between Cleanup from popup menu and Cleanup from top menu - possibly due to missing plugin, check Cleanup association in Menu Prefs
</pre>
===DOpus 4 Directory Opus===
Copy DOpus4 app to WBStartup directory folder so it starts on boot up each time
Another method is add the below to the bottom of the user-startup script in SYS:S drawer/directory
<pre>
run DOPUS:DirectoryOpus -i >NIL
</pre>
makes DOpus starts up in Iconified state at the top of Wanderer's screen. Left click on this to highlight and right mouse click to open.
Just click on the sides of either outer edges of DOpus windows and it will display the parent device/volume list.
DOpus4 saves it features in a PROGDIR:s/DirectoryOpus.CFG file which can be edited to suit anyones' needs, '''C''' bottom right button in DOpus4 and by reading the [https://arosarchives.os4depot.net/index.php?function=browse&cat=utility/filetool Dopus4 guide Manual and Arexx calls].
*[https://www.youtube.com/watch?v=DCyXDs8baSE Pt1 Introduction]
*[https://www.youtube.com/watch?v=7fiVmopiK9I Pt2 Dopus Config]
*[]
*[]
*Button little rectangle with name inside
*Bank vertical stack of buttons
Buttons
*Workbench app {f} i.e. first use {F} for all selected items with app
*AmigaDos c type apps with arguments after
*Arexx
*Command c type apps with no arguments after
Flags (most used)
*CD Destination to extract etc
*Do all files
*Output window
*Run asynchronously
*Workbench to front
*Buffer above 100000 for 64bit
Filetypes
Defines how certain files are handled like '''default tool'''
Screen
Fonts, set each element to any font
Screenmode, Workbench Use (same screen like Windows), Workbench clone (like Linux workspaces)
System
Shell startup, set to SYS:s/shell-startup
===BoingIconBar===
User chooses the apps to add to the dock at the centre bottom of the screen but has to be done manually, please use Save afterwards
Or easier edit the text file of SYS:Prefs/Env-Archive/iconbar.prefs and save
<pre>
BOING_PREFS
;Tools
SYS:System/Shell
SYS:Tools/DOpus4/DOpus4
SYS:Utilities/Editor
SYS:System/SysMon
SYS:System/Scout
Work:Extras/Internet/OWB/OWB
Work:Extras/Graphics/Lunapaint
Work:Extras/Graphics/ZunePaint
AROS:Tools/MPlayer/MPlayer
Extras:Internet/AmiFox/AmiFox
RAM Disk:Amelinium/Amelinium
</pre>
right mouse click on bottom edge of screen where boingiconbar shows - select settings which opens BoingIconBar Preferences to add apps
If no dock showing Add, to add apps click Add Program and search for the executable
another method is to drag icons to ends of the bar and move them on the Bar using the Prefs/BoingIconBar
===AmiStart===
On 32bit PCs only - auto generates the apps menu but scans the drive each time - AmiStart can choose apps you are not interested
* how to disable annoying zune/mui 'bubbles'?
try a right-click on AmiStart and release on Global settings. Then click on the bubbles gadget. Move the Show Bubbles slider all the way to the left.
===Fonts===
Install the #?.ttf files to SYS:Fonts/TrueType. Use SYS:System/FTManager to "Install Font" each #?.ttf file which will generate associated #?.otag and #?.font in SYS:Fonts. Use SYS:Prefs/Fonts to change system fonts and SYS:Prefs/Zune to change others.
To achieve our goal we will use the Setup Locale, Input, Zune and Fonts, as well as The FTManager.
Begin
The first step you should do is to get the system to know that we speak and write in another language. What you need to do is to open the setup program and choose Locale country, and list "preferred languages" to put it first and then English. If you want the tab "Time Zone" and select city of residence to set the clock correctly. Of course we save our changes and continue opening the setup program Input. This sets the keyboard language as our beginning. When the language layout was created there was no option to switch to Aros keyboard (layout switching), so to write in the language you had to hold down Alt, something you encounter in other functions. This time working with the team of Aros to create a new keyboard layout to replace the old so we can get rid of the button Alt. For now though let only selected this layout and do not turn the switch on the keyboard.
Custom Keyboard Layout
[http://repo.or.cz/w/AROS.git/tree/HEAD:/workbench/devs/keymaps keymaps are in place but unfortunately when they are not, then indeed things become a bit 'low-level' as it involves redefining some tables with values that match your keyboards]
only need to add your compiled table as new keymap.
So taking a little peek here shows that it should be possible to compile using
gcc -opc105_tr pc_105.c -nostdlib
where the pc105_gr/pc_105.c needs to be replaced with your own adjusted keymapname/c-file
[https://en.wikiversity.org/wiki/Enabling_Greek_Characters_on_Your_Keyboard General overview of Greek letters on keyboards]
Installing fonts
*[http://aminet.net/package/util/wb/EPAGrWb System jaggy]
*Outline resizable .font .otag
In this step you need to download some fonts that can support the encoding in our system. The easiest way is to run the script "Download Fonts" you'll find in the folder OWB. This script downloads from the Internet, and unpacks some fonts for OWB web browser, which is placed under the folder Fonts:TrueType. But as these can only be used by OWB and not the system, which unfortunately does not see. To make them available to the rest of the system, open the program FTManager, you will find the folder AROS: System /. From there select the field "Codepage" option "ISO-8859-7" and list the font "Arial" and "Regular" form in which you must double-click with the mouse. In the window that appears, select the bottom right the checkbox "Anti-aliasing" button and then "Install". Immediately folder Fonts: created files "arialregular.font" and "arialregular.otag", which are necessary in order to see the system font. Do the same steps if you wish for other fonts.
Final stages
After completing the above, open the folder AROS: Prefs / and run the program settings Fonts. In the new window, select the fields "Icons" and "Screen" as the font "ArialRegular" to the size you want. In the field "System" to give "s_courier", which, however, because it is not True Type Font support Antialising, and may seem a little broken. You can also use the CourierNew, if you have installed the above procedure. After you save the changes and open the Zune program settings. In this set the "ArialRegular" font fields in tabs "Windows" and "Groups", and save the changes. Reboot the system. To make sure that the above worked properly run NoWinED, which you will find under the folder AROS: Tools /. If that everything is working correctly you will see the menu and the settings window with Greek letters. You can also write in the language using the button Alt. Second program that you can try, which is fully localized, is WookieChat, which you will find in the folder AROS: Extras / Networking. And in this place all the menu and settings window works.
===Windows===
*Intuition
The window you position and resize, you right click on that windows title bar and in the dropdown menu you snapshot from there. Right click to show menu -> Window -> Snapshot Windows or All but it will NOT work if that folder has no icon (e.g. Disk.nfo) attached to it. You need a folder icon. The window information gets saved in it.
As for maximising the window using a shortcut key - Alt and up arrow key
The AROS-Shell windows can be moved, resized by editing sys:s/startup-sequence
<pre>
; run shell
run QUIET c:newshell >NIL:
</pre>
; slimmer right aros the screen
run QUIET c:newshell con:0/150//300/ >NIL:
; top right corner scr-x scr-y win-x win-y
run QUIET c:newshell con:600/150//300/ >NIL:
*EdgeSnap
Commodity EdgeSnap allows resize and position windows on your screen by dragging them to the edges but not corners of the screen and/or other windows
EdgeSnap Prefs (once pressed Use button) lets you arrange windows but not different applications in layouts half (left or right) or full size (top) and choose to adjust the border padding
There is outline to show shape taken to aid placement and space available
*Zune - AROS version of MUI
Magic Menu type functionality is implemented in IControl preferences editor: in the frame called Menus, switch type from Pull-Down to Pop-Up and/or iControl just tick the sticky menu option.
Windows outside screens causing a problem either uncheck "Offscreen move" for windows in IControl prefs editor. Or use FKey commodity and define two key shortcuts:
* the first using the command "cycle windows" (for example ALT TAB);
* the second using the command "rescue window" (for example ALT F5).
Now you can cycle windows until the one you want to rescue, and then "rescue" it: it will move back inside your screen.
How to save the window size on wanderer (snapshot all, snapshot windows)
Same for icon position on wanderer, can't save the position. Icon position cannot be saved yet, but you should be able to save the window position and size. sys:prefs - wanderer icon has option to save window size on exit but just for dh0. To get saving working on (DH1: Extras:) partitions try deleting the dh1 disk.info file, then reboot. The system should create a new dh1 icon.
* how to set up permanently 'view all files'?
As for viewing all files, removing disk.info for that disk did the job
* how to list and kill processes (xkill would be useful) ?
sys:Extras/System/Scout can kill apps
sys:Tools/Commodities/Exchange can remove available commodities
* how to restore 'go up' button in wanderer window? (it doesn't show up anymore).
If you're using Icaros, go to the theme prefs and make sure that decoration is checked. Also, some themes do not use a parent button, so try another theme. You may have to restart Aros before the theme will change.
* Is it really safe to turn off (hardware button) computer at any time (worried about USB hard disk)
yes you can turn off the computer IF none of the drives are in progress (i.e. writing). Best to use Wanderer menu option Quit otherwise
===Say narrator===
Say "Hello World" for a simple robotic voice
SPEAK: is a write-only DOS device for text-to-speech abbreviated as tts.
To check if available, type assign into the shell and at the bottom in the Devices: section should be SPEAK
Examples of use
<pre>
Copy S:Startup-Sequence SPEAK:
Echo "Hello" >SPEAK:M/R/S150/P110
Echo "DH1 EH0 L OW1" >SPEAK:A1
</pre>
Classic options are M/F, R/N, S<rate>, P<pitch>, O0/O1, A0/A1, and D0/D1. O1 recognizes lines beginning with OPT/ as option changes. A1 treats input as narrator phonemes.
Long options select a speech engine:
Echo "Hello" >SPEAK:ENGINE=narrator/VOICE=female/STYLE=natural/LANGUAGE=en-US
Supported selectors are ENGINE=, VOICE=, STYLE=, and LANGUAGE=. Values are case-sensitive backend identifiers. ENGINE=DEFAULT selects the system default. Narrator-compatible selectors continue through the classic translator/narrator pair. Other engines use speech.device. Direct phonemes require a narrator-compatible selection.
===Printing===
This needs further [http://www.aminet.net/package/docs/help/PrinterGuide drivers written], we have postscript and write to file support only
;There are no individual drivers yet for HP's Photosmart, EPSON's EPL, CANON's, Lexmark, CUPS PPD, etc.
*Postscript
Best to set Printer Prefs in the Prefs drawer to print-to-file or parallel/USB port
Save document in postscript or convert picture/text to postscript
Print using compatible Postscript printer
*printer is simply not accepting IPP connections at the moment.
Please try the following steps:
Open the printer web interface in a browser:
http://192.168.1.x/
Look for the network or protocol settings.
Enable IPP / Internet Printing Protocol.
Make sure TCP port 631 is open/enabled.
Save the settings and reboot the printer if the web interface asks for it.
ipp://192.168.1.xx:631/ipp/print
ipp://192.168.1.xxx:631/ipp/
===Files===
====File endings and datatypes====
* Check if the file has his own .info icon file with a tool set to open it. IIRC this has higher priority over the def_XYZ.info file association.
* In ENVARC:SYS/def_Text.info or whatever def_ file needs changing, use Wanderer's menu Icon -> Information and change the def_XYZ.info there. If you're on ABIv0 and want it to be applied immediately, you might have to copy it to ENV:SYS/ (or to reboot).
* Identifying file types by file ending is only a fallback. Far better it is to search for magic words, for flac files this would be "flaC" according to this [http://flac.sourceforge.net/documentation_format_overview.html documentation].
For instance, to open PDFs with arospdf not localised in the default drawer of Icaros (Work:Extras/Applications/arospdf) but localised in a custom drawer in AROS. The default tools are defined in the icons in sys:prefs/env-archive/sys e.g. def_PDF.
File type identification is done by datatype descriptors which you can find in Devs/Datatypes. The AROS build system has a tool which creates such datatype descriptors.
'''Changing of default tools of existing icons is easy as shown above. Adding of new file types is not hard, but needs knowledge of the AROS build system.'''
The enduser way would be to download the attached file, which contained two executables:
1) createdtdesc, to make a new datatype description
2) examinedtdesc, to read/show existing datatype descriptions
use 2 to get an idea on how it things are currently done in aros by providing this executable a file from the drawer sys:devs/datatypes/ (alternatively you can find the original .dtd files here).
use 1 to make your new datatype. Use the accompanied FORMAT file (also here) to read how to make your own datatype descriptor. use 2 to get hints from other datatype descriptors.
Note:
When creating a new descriptor would advise against using the pattern property, but instead use the default pattern of #? and create a Mask that matches your filetype. This requires some research in order to discover how your filetype can be recognized properly. Of course with making something like a descriptor for an ascii textfile, you would fallback to using the pattern (e.g. #?.text as the filetype cannot be determined easily otherwise).
<pre >
# name - choose wisely and informative. also used for icon's name.
# version - choose as you like as long as it complies with version rules
# basename - the 'root' datatype class. be aware that e.g. it can influence behaviour. for example when choosing binary and using tool multiview in project icon, the file will be viewed as binary file (choosing sound would tell mulitview to view the file as a soundfile). So this can influence the underlying tool being used. Could become messy if users started to modify the tool manually.
# pattern - This is the file pattern match e.g. #?.text
# Mask - A mask to identify the file. Requires knowledge of the actual file structure. For example 'M' 'Z' for an msdos executable.
# GroupdID - not supported (AROS native) files - use syst as that would be the least intrusive in case an AROS tool/program tries to load such datatyped file.
# ID - In your case, the first four characters of the name at subchapter 1 (in lower case) (or less if name is shorter).
# flags - How the mask needs to be interpreted. In your case would be mostly DTF_BINARY in combination with (wanted or not) DTF_CASE (to tell if mask used letters are case sensitive or not)
# priority - the priority of how the type is handled so that on datatype could have precedence over another? In any case, document tells it to be mostly 0.
</pre >
Now that you know each field and what it does (more or less), you write this fields in a text file for your own invented datatype, save it and create the actual dt with the tool in 1. in the end the created dt must reside in sys:devs/datatypes/ drawer.
Then you would create a default icon in sys:prefs/Env-archive/SYS drawer. Don't forget to reboot or copy .info file to ram:env/sys in order to test. also don't forget to set which tool to start f.e. c:lx or dh4:emulators/mycoolemulator
To test, open Wanderer then show all files and doubleclick on a file of type you just created. Alternatively you could use the 'open' command from shell (with file of datatype you just created as parameter).
And as a last note. it would perhaps be welcome to have a program like xicon and/or runprglist for AROS (unfortunately both without source, but something similar could be created for AROS).
Sounds complicated ?
Perhaps... but OS like windows needs a complete registry to be able to do things like this. And yes, i am aware windows has gui tools that does it (more or less) for you (by manipulating the registry). Same could be done for AROS (without integrating a registry in AROS that is ).
Would that suffice ?
red1+2: typos, reformatting.
disclaimer: please note that using these tools can screw up your currently installed support for datatypes when used incorrectly. Do not use if you do not understand what you are doing. Use at own risk.
==Network Connection==
AROS currently only has one real choice for TCP/IP networking - AROSTCP. This is a port of the AmiTCP package from AmigaOS (TM), with a number of enhancements/fixes from AROS developers.
===Wired===
Use Network Prefs to setup
=====IPv6=====
Some support
128bit IPv6 address packet
<pre>
Local FD::/8
Global 2000::/3
64:ff9b::/96
</pre>
NAT64 translates IPv6 to IPv4
DNS64
OS routing works with
<pre>
MacOS Ventura
Windows 11 with cloud account
Ubuntu Jammy Jellyfish
Android 10 (block google dns)
</pre>
====IPv4====
The top half of the IPv4 Configuration tab on the Network Prefs deals with the network card/USB and the lower half the router part.
[[File:AROS Wanderer Network Prefs DHCP.png|thumb|DHCP Settings]]
'''Upper part of IPv4 tab'''
* Click Add on the top right of the Prefs which opens a window called '''Interface'''
* Enter Name as net0 (but can be anything as long as it is consistently used in other sections)
* check mark on Active
* select device to be used using the '''right hand-side gadget''' of the box where the device name will go
* set Unit to 0
* IP Mode is default set to '''Get address from DHCP'''
* IP Mode set to Manual if DHCP does not work automatically
From the shell CLI, ifconfig -a
Under net0: section, inet starting 192.168.x.xxx
* inet or '''Address''' of network card
* netmask convert to decimal so 0x'''ffffff7f''' becomes 255.255.255.247 which is used to adjust the above '''Address''' into
* broadcast 192.168.xxx.xxx
click OK
[[File:AROS Wanderer Network Prefs Manual.png|thumb|Manual Settings]]
'''Lower part of IPv4 tab'''
* IP Mode Get address from DHCP (default)
* or changing to Manual if automatic DHCP set up does not work
* '''Gateway''' (Router Internal LAN-IP) (Default Route) = 192.168.0.1 (D-Link Netgear), 192.168.1.1 (Linksys 3com), 192.168.2.1 (SMC Microsoft), 192.168.1.254 (Belkin), 192.168.123.254 (USRobotics) else check with your router manual
* first DNS = use 208.67.222.222 (opendns) or Gateway number above (to test web browser access to router) or 212.50.160.100 (google) i.e. or whatever your ISP needs you to set
* second DNS = use 208.67.220.220 (opendns) or Gateway number above (to test web browser access to router) or 213.249.130.100 (google) i.e. or whatever your ISP needs you to set
* At the bottom of IPv4 tab, check mark the '''Start networking during system boot''' option
* Save and reboot (sometimes Network restart fails, so reboot every time to be sure)
'''an alternative way''' to AROS ifconfig -a, other OSs have similar for the same internet connection. Another connection will have different settings.
e.g. From [http://www.ncsu.edu/resnet/windows/ipconfig/ Windows], '''ipconfig /all'''
and note down the IP, subnet mask, default gateway, and DNS servers values and put these values in "manually" into AROS Network prefs.
e.g. From Linux via dhcp router have a look at etc./dhcpc/dhcpcd-eth0.info
* for manual input look at /etc/networks (IP or Gateway) and /etc/resolv.conf (DNS)
Please note that all in one routers (wired+wireless) or separate routers may need different settings
IPv4 involves routing (192,168.x.x), firewall, NAT
===Wireless===
You may have a Wifi Prefs to use for wireless setup
[[File:MyArosWirelessSetup.png|thumb|Setting up]]
[[File:MyArosWirelessTCP.png|thumb|Shell commands to work out what is happening]]
We must first make certain you have a Atheros 5k chip inside acting as the wireless wifi option. Open PCITool in Tools directory. Down left hand side are a series of numbers 0.00.0 etc. Click on some at the bottom and hopefully one of them will say Atheros AR5??? or AR242?.
or a Realtek RTL8187B, we can check using Prefs/Trident as this one is USB based
There are many similarities with the above Wired set up so please read the above section as well
* open Network/Prefs
* In '''IPv4 Configuration''' tab - click Add - enter net0 / active tick / #?.device / Unit 0 / IP Mode = manual (important if default DHCP does not work automatically)
Make sure that any extra network names (e.g. eth1 or net1) should be deleted. If net0 already st previously, change net0 so that it shows associated with the appropriate device name like atheros5000.device or realtek8180.device. Having two entries here will cause sub-net problems.
* Go to '''Wireless''' tab and click on "Add" button.
* Insert network name (SSID your wireless network name use wirelessmanager to get it), select right "encyption" that is most likely "WPA".
* Key Type set as "Passphrase". i.e. type in your password for your router (aka access key).
* Unselect (no tick) "hidden" if it is selected, then apply. You may have to tick it if wireless does not work.
* Finally, Save and '''reboot'''.
For the best chance of success, set networking to start at boot, and then reboot with the USB adapter plugged in.
===USB Ethernet===
Open SYS:Prefs/Network and in the IPv4 Configuration tag (top table covers your usb stick)
* click Add button
* set Name as net0
* Tick Active box
* enter the usb-ethernet.device e.g. dm9601eth.device, usbpegasus.device or usbasixeth.device use SYS:c/devlist, '''Scout''' or trident prefs to get the correct spelling
* set Unit to 0 (which is usual but check the messages from the bottom of the Trident prefs whilst plugging the device in to determine the unit number otherwise)
* IP Mode is set to Get address from DHCP (make sure your router is set right for that)
'''or manual'''
* IP Address of network card, i.e. 192.168.0.xx or 192.168.1.xx (xx being greater than 1)
* Subnet netmask = 255.255.255.0
* click OK
There can be sometimes be boot failures when using USB ethernet - plug the USB device in after boot and save the network prefs to make it work again.
Lower part of IPv4 tab covers the router information
* IP Mode Get address from DHCP
'''or if manual settings'''
* Gateway (IP Address of router) = usually 192.168.0.1 or 192.168.1.1 but see router manual to make sure.
* first DNS = use 8.8.8.8, 208.67.222.222 (opendns) or 212.50.160.100
* second DNS = use 8.8.4.4, 208.67.220.220 (opendns) or 213.249.130.100
===USB Tethering via Android smartphone===
Go to AROS Network Prefs (IPv4 configuration tab) and write type in "usbrndis.device" in the "device" textfield of "Interface" sub-window, which appears when you add a new device (or modify an existing one). Select "Start Network during system boot" and saved the configuration, the Connection is immediate no reboot is needed.<br>
usbrndis.device is a resident device (virtually always there) in fact, a driver is not present in DEVS:Networks <br><br>
Plug in USB cable, go to Android settings and enable "USB Tethering" <br>
A reboot should not be necessary.
When restarting AROS, the Smartphone deactivates the connection and to access the network again have to reactivate it before starting the browser.
===Solving Issues===
[[File:MyArosTCP.png|thumb|Aros network setup diagnostics - why does it not work?]]
* In Network Preferences, have '''only one''' item in the IPv4 Configuration tab
* If using manual settings, make sure all numbers are correct, especially for IP address of the card/usb (changing the last number in chain of four)
* For any USB based networking, it is often necessary to save in Prefs/Network, reboot AROS and network support can begin
* For wired, make sure that the LAN-cable is plugged in before starting the computer
* If wireless, try getting closer to the router.
* Switch off the encryption option from your router then try wifi, if successful then your ip/dns is ok. If not then your ip/dns settings are most probably wrong or need to use one or more opendns numbers
* Replace detachable wireless antenna (best wireless option to buy if you can) with a stronger antenna ie. 5 dBi or 7 dBi
* Try with another computer/laptop/machine
Program Error C:WirelessManager
* Test with another OS
* Check that Wifi works before changeover (if possible)
* Check that socket and card are working
* Check if card is too new for laptop (date code on card MMYY blue askey date 2005-2007 etc)
Are you connecting with the Router ?
Check with protection off e.g. wps and wep to see if it makes a difference.
For USB wireless - stopping and starting may be needed...
<pre>
; $VER: AROSTCP-startnet 1.0 (01/08/06)
; AROSTCP-startnet (c) The AROS Dev Team.
;
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
; stop and restart
execute "sys:system/network/AROSTCP/s/stopnet"
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
run <NIL: >NIL: wirelessmanager realtek8180.device
</pre>
What IRQ number is assigned to the device? You can check with Tools/PCITool?
It's possible the BIOS hasn't set the right IRQ number. If you have a Linux CD/DVD handy, could you check if it boots with the options "acpi=off noapic nolapic"?
If the following does nothing, this will help us figure out why networking doesn't start automatically at boot
open a shell and run the following commands:
<pre>
echo ${AROSTCP/AutoRun}
echo ${AROSTCP/WirelessAutoRun}
echo ${AROSTCP/WirelessDevice}
</pre>
Please report the output, typically it will look like this
# True (explanation this variable is related to the "Start networking during system boot" checkbox in network prefs)
# True ()
# Devs:networks/atheros5000.device unit 0
If there's a problem with the AROSTCP package. What's the output of this?
ENV:sys/packages/AROSTCP
should return a string = Sys:System/Network/AROSTCP
By the way, a quicker way to check networking is working would be to run some shell commands such as:
<pre>
ping www.google.com
ifconfig net0
</pre>
The best way to list the available networks and diagnose / troubleshoot problems with connecting to a wireless network is to run WirelessManager manually. First uncheck the "Start networking during system boot" box in the Network prefs app, then save and reboot. Then run this in a shell:
C:wirelessmanager atheros5000.device verbose
or
C:wirelessmanager realtek8180.device verbose
and capture the output
If the above does not help, could you edit the file SYS:System/Network/AROSTCP/S/Package-Startup, and change ">NIL:" to ">T:wifi.log" on the WirelessManager line and add this as well Wait 5?
<pre>
if ${AROSTCP/WirelessAutoRun} eq "True"
Run QUIET "C:WirelessManager ${AROSTCP/WirelessDevice} >T:wifi.log"
wait 5
EndIf
</pre>
Then save, reboot and post the log file (T:wifi.log) here.
<pre>
c:wirelessmanager atheros5000.device verbose
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7)
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
Then it just sits there. Not sure what a normal dump looks like, I don't see anything that looks wrong in the configuration.
</pre>
looks like the driver isn't working with that card. Has anyone else successfully used that exact model number (AR2413)?
<pre>
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7):
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
*** [wpa_sm_init] sm->pmksa=02c66fd4 ***
Own MAC address: 00:01:36:15:ae:0c
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
Added interface atheros5000.device:0
State: DISCONNECTED -> SCANNING
Started AP scan for wildcard SSID
MLME: starting scan
MLME: scan channel 1 (2412 MHz)
sana2: sending MLME frame
Then it stops. Does this mean the router is not authorizing this NIC?
IRQ 4 (A)
</pre>
apparently locking up when the first frame is sent (a scan request).
<pre>
Devs/Networks/atheros5000.device:0
Initializing interface 'Devs/Networks/atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=12):
41 69 72 4c 69 6e 6b 35 39 33 30 30 AirLink59300
PSK (ASCII passphrase) - hexdump_ascii(len=8): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='AirLink59300'
*** [wpa_sm_init] sm->pmksa=0224e444 ***
Own MAC address: 00:1f:e1:42:e3:7a
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
[eloop_reg_timeout] Timeout is at 1317686594.160000
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
[eloop_reg_timeout] Timeout is at 1317686595.060000
[eloop_reg_timeout] Timeout is at 1317686604.060000
Added interface Devs/Networks/atheros5000.device:0
[eloop_run] Starting
State: DISCONNECTED -> SCANNING
Starting AP scan for wildcard SSID
MLME: starting scan
[eloop_reg_timeout] Timeout is at 1317686594.160001
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.233000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.373000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.513000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.553000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.693000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.013000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.073000
EAPOL: disable timer tick
EAPOL: Supplicant port status: Unauthorized
MLME: scan channel 14 (2484 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.113000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.153000
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.213000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.353000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.493000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.533000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.673000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.993000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686596.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686596.073000
MLME: scan completed
</pre>
Is your network hidden? If so, did you enable the 'Hidden' checkbox in the network prefs? What distro version are you using?
<pre>
"ENV:sys/wireless.prefs" looks like this:
network={
ssid="testadhoc"
key_mgmt=NONE
wep_key0="12345"
wep_tx_keyidx=0
}
</pre>
If your router doesn't broadcast its SSID (hidden), you need to add this option to the network block of the wpa_supplicant.conf on your aros machine and make changes after # Example blocks:
scan_ssid=1
Here's a full description of all the [http://hostap.epitest.fi/gitweb/gitweb.cgi?p=hostap.git;a=blob_plain;f=wpa_supplicant/wpa_supplicant.conf config file options].
<pre>
ap_scan=1
network={
ssid="YOURESSID"
scan_ssid=1
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP
group=CCMP
psk=YOURPASSWORD
}
</pre>
<pre>
filter_ssids=1
ap_scan=2
network={
ssid="REMOVED"
scan_ssid=1
bssid=REMOVED
priority=100
mode=0
proto=RSN
key_mgmt=WPA-PSK
auth_alg=OPEN
pairwise=CCMP
group=CCMP
psk=REMOVED
}
</pre>
Error 6: Couldn't resolve host name.
Check Scout -> Devices and look at the device that you are using, in the OCnt column it should state 2 which means AROSTCP and Wirelessmanager are both accessing this driver. If 0 or 1, then uncheck the checkbox in Network prefs for starting networking at boot, save and reboot. Then run this is the shell:
C:WirelessManager realtek8180.device unit 0
some quirks setting up the wireless network as well
1) it's far better setting up either the wired OR the wireless network adapter as net0:, or weird things happen
2) it's better using fixed IP on the local network instead of DHCP
3) network setting must be placed in network setting panel in /prefs, using the wirelessmanager helped me finding available SSIDs, but not actually connecting to them
once done, reboot.
If previous setup is proving problematic
<pre >
SYS:Prefs/Env-Archive/Wireless.prefs
SYS:Prefs/Env-Archive/Zune/OWB.config
SYS:Prefs/Env-Archive/Zune/global.config
SYS:Prefs/Env-Archive/AROSTCP/WirelessDevice
SYS:Prefs/Env-Archive/AROSTCP/db/Interfaces
</pre >
Make a copy of these files and restore in case of problems.
Please try this test to check if you can connect to your router, ie established that the WiFi layer is working
̊̊̊̊Boot with networking disabled, by make sure that "Start networking at boot" in Network Prefs is unchecked (no tick).
̊ Run this in a shell: C:WirelessManager atheros5000.device VERBOSE
̊If the output of that command is too long to summarise here, you can redirect it to a file by adding >RAM:wifi.log to the end, then attach or paste that file here.
try running "status" in the shell and check that AROSTCP is listed/running
If AROStcp is not showing, then AROSTCP is not running. attempted to start it by clicking Use or Save in network prefs, or checking the "start networking at boot" box or typing into a shell.
Execute SYS:System/Network/AROSTCP/s/startnet
(run Status again afterwards).
The "cannot resolve hostname" will appear if you are blocked on the wifi network by the router as well as aros not being able to assign correct network address.
One way of testing this might be to disable the firewall in the router. you might also check the router how it sees the attempts aros do to speak to it. The easiest way to do that would be to manually give aros an IP number in the routers accepted range. and see if it shows up at all within the router.
Tests that can be undertaken to determine correct settings and functions
pciinfo
sanautil -d broadcom4400.device status
<pre >
ping <router-address> e.g. 192.168.0.1 (aka inet) or 80.237.146.33 (www.amiganews.de)
ifconfig net0
ifconfig net0 up
extras:networking/utils/sanautil/sanautil -d atheros5000.device status
WirelessManager atheros5000.device verbose >RAM:wifi.log
;to send the log to RAM disk to be read easier or if detected,
Run WirelessManager atheros5000.device >NIL:
Run WirelessManager atheros5000.device ssid="mynet1" >NIL:
C:WirelessManager realtek8180.device unit 0
</pre >
Please look at the task list in Scout, and check if WirelessManager and AROSTCP are running. Also look at the device list in Scout to check if realtek8180.device is open.
start tools/debug/sashimi, maybe it shows some debug messages when disconnection happens.
Firstly, let's take a look at what your setup most likely looks like, assuming you use a router. See diagram below:
<pre>
Internet <---------> home router <---------> computer
-----------external IP------------------internal IP-------------
</pre>
Okay, so what am I trying to show you with that diagram. A few things. Firstly, the IP address that connects you to the Internet is not the same one that connects you to your router. What happens is that your computer doesn't have a direct connection to the Internet, instead your router connects to the Internet, and your computer connects to the router.
You can see the external and internal IP addresses in these example settings...
* Default Gateway : 76.91.64.1 (external IP for ISP/Internet host)
* IP Address : 76.91.71.184 (external IP for home router)
* IP Address : 192.168.0.1 (internal IP for home router)
* Address = 192.168.0.161 (internal IP for computer)
As you can see, there are two internal IP addresses and two external IP addresses. This is because there is a client/server relationship, effectively one address is for the service (server) and one address is for the device trying to access that service (client).
The server addresses in your case are 76.91.64.1 (your ISP's address, serving the Internet), and 192.168.0.1 (your home router's address, serving your home network). The term gateway applies here, they are your gateway to those services.
Subnet masks are used along with IP addresses to determine which IP addresses are allowed access to a network. I did learn the more in-depth rules about subnet masks once (watched a CCNA vid), but I've forgotten about it. The basic level of understanding you'll need is easy to remember though. A subnet mask value of 255 means that portion of the IP address must stay constant, whereas a subnet value of 0 means any unassigned value up to 255 is allowed in the IP address.
By far the most common subnet value is 255.255.255.0. What this means is that the first three parts of the IP address you use to connect to a service must stay the same as the server/gateway address, and only the last section can change.
So if your router's internal IP address is 192.168.0.1, and the subnet mask is 255.255.255.0, the only addresses that will be allowed to be used on that network are between 192.168.0.2 and 192.168.0.255 (I think 192.168.0.0 is reserved for other uses).
Final point to make is about DHCP (a.k.a. dynamic IP) vs static IP. A server/router using DHCP gives a device that connects to it an address within the acceptable range. It usually starts with the lowest numbered free address, so with your router it'll give the first device that connects to it 192.168.0.2, the next device 192.168.0.3, and so on. Static IP addresses are where you set the IP address you want to connect with in advance.
When using static IP addresses on a router where DHCP is active, it's good to use a high number to avoid conflicts with other devices that are connected to your network, to reduce the risk that both devices will try using the same IP. That's why your current choice of 192.168.0.161 is good, unless you have over 159 devices connected on your current network!
Okay, so what's the next step. Well, if you can use ping, I'd suggest pinging 192.168.0.1. If you get a positive response it means you're connected to your router, if you don't get a response it means the connection between your router and your computer is at fault.
Documentation on configuring the AROSTCP environment further can be found [http://en.wikibooks.org/wiki/Aros/User/Networking here]
===File Sharing===
As AROS knows only a few filesystems (FFS, OFS, SFS, PFS (amiga only), FAT12, 16, 32, Microsoft NTFS (windows), UDF (Blu-ray)).
The others in regular use like MacOSX hfs+, Linux ext2/ext3 and ext4, Haiku BeFS provide a problem in transferring files.
Linux can access SFS partitions but it needs to be compiled. The latest full source are [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ here]. It compiled fine with a 2.6.30 kernel in Puppy Linux 4.31.
An alternative, is to use a FAT32 partition to share. Setup a 4G FAT32 partition using HDToolbox for sharing, and the rest of the space as SFS for an Aros install. It works very well.
Files could be transferred via TCP internet network.
====SMB2/3====
With Windows you can share one folder or all folders of the "Public" user.
On Windows what is important is to enable sharing (Network and Sharing Center).
AROS Mountlist should look lke this
<pre>
Handler = L:smb2-handler
StackSize = 65536
Priority = 5
GlobVec = -1
ACTIVATE=1
Startup = "smb://UserAcc:password@PCShare/Sharefolder"
</pre>
which could also be
"smb://UserPC:password@192.168.x.x/Public"
or
"smb://UserPC:password@Name-PC/Public"
so
"smb://UserPC:password@192.168.1.158/Folder"
or
"smb://UserPC:password@Name-PC/Folder"
After you have configured a share generates a DOSDrivers it is named "SMB0" which includes the setting, and at each reboot it is Mounted. You can still delete the DOSDriver by hand, is located in Storage/DOSDrivers, the file "ServerAutoMounts", in ENV:AROSTCP which indicates the DOSDriver to be mounted, should also be deleted.
The per-mount files are written to ENV:SMB or SYS:Storage/DOSDrivers. There is also additional file ENV:AROSTCP/ServerAutoMounts which states what will be presented to the end user.
====Old SMBFS====
e.g. to connect to a NAS share such as \\NASBOX\Shared use -:
SMBFS WORKGROUP=<YOUR WORKGROUP NAME> VOLUME=<AROS volume name to use>: SERVICE=<UNC Path to connect to>
SMBFS WORKGROUP=MYNET VOLUME=Shared: SERVICE=//NASBOX/Shared
And you will then have an icon appear on your desktop for the volume name you have chosen.
You can put the above script into wbstartup or
give it an icon, change it to a 'project' and give it the default tool c:iconx
Open a shell and type copy sys:script.info "sys:wbstartup/YOURSCRIPTNAME.info"
This should create an icon for your script file.
Now right-click on your script and select 'information'.
Change 'tool' to 'project', put 'c:iconx' into the 'default tool' box, click save
The reason being that scripts need to be opened with 'execute SCRIPTNAME' (or 'iconx') whereas the programs started from wbstartup are opened using 'run PROGRAMNAME'. It's the same as trying to start a command-line tool from the workbench by double-clicking it.
====Setup ISO images within AROS====
Use [http://archives.aros-exec.org/index.php?function=browse&cat=driver/storage DiskImage] which supports many cd image formats ISO, CCD, MDF/MDS, CUE/BIN, NRG and UIF. To mount CD or DVD images use below....
<pre >
# Rename your iso 'Unit0' (note no extension).
# Do 'View/All files' on you Aros partition. You should now see a folder called 'Diskimages'. Copy your renamed iso to there.
(Alternatively, you could type at the shell 'assign FDSK: xxx', where xxx is the location of your iso.)
# From the shell, type 'mount CD0:' and the iso should appear on the Wanderer desktop. You can now access it like a real disk.
</pre >
assign devname: dismount
Assign DOSVOLUME: remove
[http://aminet.net/package/disk/misc/unmount-0.1 unmount] most filesystems work but SFS lacks support for ACTION_DIE packet
If you are using an IcAros install, the startup scripts are set up to wipe the Diskimages directory on boot, so its worth keeping a second copy of the iso somewhere else. Alternatively, you could set up extra mountlists for additional iso images. I've made a file called iso1 in the Aros:devs directory that contains the following text:
<pre>
/* Entry for ISO image */
ISO1:
FileSystem = cdrom.handler
Device = fdsk.device
Unit = 1
LowCyl = 0
HighCyl = 0
Surfaces = 1
BlocksPerTrack = 1
DOSType = 0x41434400
Activate = 1
#
</pre>
Then I just need an iso called 'Unit1' (corresponding to the 'Unit = 1' entry in the mountlist) in Diskimages (or wherever I assign FDSK: to) and to mount I type in at the shell:
Mount iso1: from devs:iso1
Of course, if you create mountlists for ISO2, ISO3:, etc. (with the corresponding change to the 'Unit = ' line) you can have as many isos mounted as you wish. I just call mine ISO1: etc. to distinguish them from the real CD drives
==Video Guides==
Video demonstrations and tutorials covering:
:00. '''Introduction'''
::[https://www.youtube.com/@jamesmattson6813/videos Various Aros Installs],
::[https://www.youtube.com/embed/j8EmSEby0Rg AROS repo in gource, view of AROS dev commits from 1997 to 2025], [http://www.youtube.com/watch?v=Vx_zqlBow40&feature=related Gource view of AROS 1997 up to 2009],
::[http://www.youtube.com/watch?v=s1RsvEm7UrU Why an Amiga OS in 2011],
::[https://www.youtube.com/watch?v=1W886mheV74&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Johan Grip on early days of AROS x86], [https://www.youtube.com/watch?v=mXaKDhtTTqQ&t=14s&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Michel Schulz on Aros and PiStorm],
:01. '''Installation'''
::[https://www.youtube.com/watch?v=M7YjufrJqDs Aros One install], [https://www.youtube.com/watch?v=iIMguHTdC5E Aros One USB install], [https://www.youtube.com/watch?v=ZNXauy5m5Wc Aros One install], [http://vimeo.com/11013489 Modify Grub boot],
::[http://www.youtube.com/watch?v=wyQVeyXIywc&feature=channel iMica Silent Pt3], [http://www.youtube.com/watch?v=o2AnkoflY14 Wipe whole drive and Install - warning loss of data on drive],
::[http://www.youtube.com/watch?v=OVXm6_-witQ VirtualBox install], [ VMware install],
::[http://www.youtube.com/watch?v=0k2PEmT8I14 Broadway AROS Install],
::[https://www.youtube.com/watch?v=PtDiXhjSIfs Is Aros Icaros a choice?],
::[ driver install],
::[http://www.vimeo.com/10491104 HDAudio install but needs account], [],
:02. '''Amiga Basics'''
::[http://www.youtube.com/watch?v=TY8mWxwzH5o Screens tutorial],
::[https://m.youtube.com/user/AMIGASYSTEM/videos General], [ Dos Scripts tutorial], [http://www.youtube.com/watch?v=hPT7SmVEpjc OS 1.2], [http://www.youtube.com/watch?v=n6kX3FqH8Ww&feature=related OS 1.3],
:03. '''Customisation demos'''
::[https://www.youtube.com/@AMIGASYSTEM/videos Prefs tutorial], [ Decoration tutorial], [http://www.youtube.com/watch?v=Dn5C8G3aDXU Scalos],
:04. '''Setting up''' internet access and surfing the web, FTP, IRC and Mail apps
::[ Network Prefs], [ AirCOS tutorial], [ jabberwocky tutorial],
:05. '''Native bundled Games and Applications'''
::[http://www.youtube.com/watch?v=aYlFv2B-VXc 3D Games], [http://www.youtube.com/watch?v=MXK7wwhd-R0 Latest Games], [http://www.youtube.com/watch?v=RUgiVThv23Q&feature=mfu_in_order&list=UL PrBoom GL], [http://www.youtube.com/watch?v=0s7u8TPy7V4 Assault Cubes], [http://www.youtube.com/watch?v=fih6aCXKeqs Cube 2], [http://www.youtube.com/watch?v=-X0ay0MGOms DosBox on Aros], [http://www.youtube.com/watch?v=7nKduDjf14k Oct 2010],
::[http://www.youtube.com/watch?v=FziV2z_uxnQ Apps Pt 1], [http://www.youtube.com/watch?v=xs37_nfa5CI Apps Pt 2], [http://www.youtube.com/watch?v=Bn59_VvbQR0&feature=related Apps Pt 3],
::DOpus4 [http://www.youtube.com/watch?v=aSRybWjrrME DOpus 4],
::Milkytracker [http://www.youtube.com/watch?v=VxBOEPzpdKg&feature=related Laying Down Base Tracks],
::[http://www.youtube.com/watch?v=k2uKQ0-ieOE Audio Evolution 4 in action], [http://www.youtube.com/watch?v=Zq4r9k0_jZI Quick Videos],
::[http://www.youtube.com/watch?v=gGKCFZcIc0I&feature=related ScreenRecorder], [http://www.youtube.com/watch?v=974c2e-Fqak&feature=related TV out Tests],
::[http://www.youtube.com/watch?v=fjq8ct5d5IY AmiFIG], [http://www.youtube.com/watch?v=h0rHvPhYJo4&feature=youtu.be ZuneFIG],
::[http://wiki.povray.org/content/Documentation:Tutorial_Section_1 POVray Tutorial 1],
::[http://www.youtube.com/watch?v=Jk-ZNLfJsvQ pt 1, jan. 2008], [http://www.youtube.com/watch?v=nWRy33g1R7Y pt 2, feb. 2009], [http://www.youtube.com/watch?v=r5PbhCtm4vE pt 3, feb. 2010],
::[https://www.youtube.com/watch?v=G7_FJUoQ89o Hollywood programming], [], [], [],
::[], [], [],
::[], [], [],
::[], [], [],
:06. '''Commercial software available'''
::[http://www.youtube.com/watch?v=fKXY9B4R43s AntiryadGX 3D Game Editor],
::[http://www.youtube.com/watch?v=TMS9NDzwm5U BOH indie Game],
:07. '''Running classic amiga apps and games'''
:: Amiberry [], [],
::[http://vmwaros.blogspot.com/2008/11/introducing-amibridge.html Intro Amibridge], [http://www.youtube.com/watch?v=ee2PWvCZeLo Old Amiga Apps], [http://www.youtube.com/watch?v=ee2PWvCZeLo Why Janus UAE is good],
::[https://www.youtube.com/watch?v=VhlsNSYSuDg DPaint tutorial]
::[http://vmwaros.blogspot.com/2009/11/can-icaros-play-my-amiga-games-and-why.html Play Amiga Games], [https://www.youtube.com/watch?v=XTaZCNOvCnE],
::[http://www.youtube.com/watch?v=tMehS77LXQ4 Pagestream Introduction], [http://www.youtube.com/watch?v=284-w3hTzII Pagestream Tutorial 1], [http://www.youtube.com/watch?v=mlwEGwhZzl4 Pagestream Tutorial 2],
::[http://www.youtube.com/watch?v=iIcrIjPOctc Catweasel Mk4 PCI Part 1] and [http://www.youtube.com/watch?v=BaitHeL6bEA Part 2],
:08. '''Misc and History'''
::[http://www.youtube.com/watch?v=d6mDXKU29w0 Mum uses old AmigaOS Workbench 1.1 (1986)], [http://www.youtube.com/watch?v=DaRkacQ-YMg Why an Amiga 500 (1987)], [http://www.youtube.com/watch?v=k5CYsgVCzYY an Amiga 2000 (1987)],
:09. '''Misc Shows and Events'''
::[http://www.youtube.com/watch?v=klgVSWKs4kE VCF 2010], [https://www.youtube.com/watch?v=eQ3d5qR-Hv8 24:06 Jason McMullan at amiwest 2012 about AROS], [https://www.youtube.com/watch?v=jpQO7XSfAv4 Aros SMP multi core amiwest 2013], [], [https://www.youtube.com/watch?v=gFRtAAmiFbE], [https://www.youtube.com/watch?v=DjdUEyjx8GM], [https://www.youtube.com/watch?v=ydYDqZQpim8], [], [https://www.youtube.com/@uminekoshouten/featured], [https://www.youtube.com/shorts/NfoY023w-vE],
:10.
::[https://www.youtube.com/shorts/6qJTNW4-6GY]
===History===
The project was originally started by a small group of Amiga [http://www.amigahistory.co.uk/aros.html enthusiasts] in 1995. These individuals were mainly computer-based college university students at the start, though that student trend has diminished since. An interview with Aaron Digulla [http://arosshow.blogspot.com/2006/12/interview-with-aaron-digulla-who.html here]
* 1992 Commodore folds
* 1996-1998 much of the early years was concerned with exec, dos and intuition libraries.
* Early 1999, Haage & Partner used parts of the AROS code in AmigaOS 3.9.
* March 2001, floppy disk images of AROS became available.
* Early 2002, AROS changed its name from Amiga Replacement Operating System to Amiga Research Operating System
* June 2002, AROS devs decided to use Zune (MUI 3.8 rewrite) as the GUI system.
* November 2002, Eric Schwartz drew Kitty for AROS usage.
* Early 2003, AROS.org underwent a graphics facelift.
* Late 2003, GCC C compiler arrived.
* Early 2004, Aros-Exec opened.
* Early 2005, Aros Max bootable CD arrived.
* Late 2005, SFS filesystem ported and allowed fast access to apps and network support arrived
* Early 2007, AROS.org underwent another graphics facelift.
* Mid-2007, AROS changed to AROS Research Operating System after A.Inc. sued Hyperion with a trademark violation.
* Late 2007, the hard disk installer added and VmwAROS (later called Icaros Desktop) distro launched.
* Early 2009, Our first usable web browser (OWB)
* September 2010, first wireless support appears and AspireOS started as a distro
* Early 2012, the first paper-cut bugfix and Fab's Odyssey Web Browser ported
* Early 2017, work started on utilising the addition cores on modern CPUs starting with the 64bit x86 PC version
* Mid-2017, m68k port optimized for the Vampire 2 / Apollo accelerators (68080 AMMX FPGA)
* 2018 The old AROS Exec website closed and a new one opened
* 2019 AROS One x86 32bit distribution started and now with USB install version
* Early 2021, backport of more features of 32bit PC ABIv1 into 32bit PC ABIv0 (Aros One 1.5 and above)
* 2025 year of 64bit pc builds and porting 32bit applications to 64bit ABIv11
* 2026 update of [https://www.youtube.com/watch?v=6FKTL068ULM&pp=ygUPYXJvcyBhbWlnYSAyMDI2 nvidia nouveau driver for 64bit PC]
===Bounties===
To help inspire developers with both ideas and monetary incentives, rewards are offered for the successful completion of "bounties" (requests for missing/new functionality) chosen by the community and handled by [http://power2people.org power2people] (formerly done by TeamAROS). A monthly option is [http://www.power2people.org/funds/aros/ here].
Future goals for AROS include expanding its underlying retargetability to support even more diverse architectures, provide memory protection features and user level file security, SMP and many other wonderful features missing from AmigaOS — while still providing as much source level compatibility as is possible (however it is accepted that to achieve some goals code certain things may require a little recoding).
[http://www.ohloh.net/p/aros/contributors Developers] come and go as with any open source effort and we would like to thank them for their efforts...
;1996-2000:In DigullaA (coordinator), GripJ, TempletonI (BSD), SchulzM, RittauS, voordenDagL, HolmM, JohanssonT, VanIngelgomH, SteigerwaldM, BortasP, deJongK, AlfredssonJ, InnocentiB,
;2001-2005:In [http://chodorowski.com/adam/aros.html ChodorowskiA], StegerG, BergerS, HeutlingS, AlemagnaF (gcc), VerhaegenS (rexx), KielH, MatheussenKS (CAMD), SzczygielskiP, ErikssonP, LeCorfecD (Zune), BauerS (Zune), FurlongW, GustafssonJ, AndrewsN, CafferkeyN, GierichM (jpeg), PattonJ, ParsonsM, DietrichJ, SeilerT, BischoffL, LorentzenNH, AdamO, BerglundH, SmithP, HolmenD, BlomM,
;2006-2010:In FedinP, RusslerM, SzymczykS (owb), SmiechowiczK (openGL), WeissM, NorrisR, BrunnerO, WiszkowskiT, GreppinA, [http://www.fukt.bsnet.se/~bearsoft/ Bearsoft Björn Screwelius], ErbY, CharletF, HodgesC, [http://aros-exec.org/modules/newbb/viewtopic.php?topic_id=4819&forum=18&post_id=43103#forumpost43103 HokstadV], McMullanJ (m68k), WilenT (m68k),
;2011- :In MuijzenbergPHvanden, ALB42, JonesEM, weiju, DizzyofCRN, wawa, miker,
* 1996 - The linux hosted version for i386 was the first to arrive
* 1998 - i386, The native version for i386-based PC AT computers and compatibles.
* 2004 - x86/64, The native version for 64-bit (x86_64, amd64) PC computers.
* 2008 - sam440/ppc, The native version for Sam440EP, Sam440EP Flex and Sam460ex computers.
* 2009 - efika, The native version for PowerPC Efika computers.
* 2010 - m68k, The native version for m68k Amigas or WinUAE
* 2013 - raspi/armfh, early native version for ARMv6 based Raspberry Pi computers.
* 2017 - x86/64bit smp
Debugging capture serial debug at all (especially with sysdebug=all or --sysdebug=all) to see it displayed on screen
* yes, usb -> rs232 adapters can work most of the time, some of the cheapest ones are not fully compatible with all rs232 devices to capture to another device
* you will need a null modem cable (or a null modem adapter usually female to female) in addition to the usb -> rs232 adapter (usb adapter is a normal modem ie. the pins are not crossed over)
Normal modem cable - straight connection DCE
<pre>
Pin 2 -> Pin 2 RXD
Pin 3 -> Pin 3 TXD
Pin 5 -> Pin 5 GND
</pre>
Null modem cable connections DTE
<pre>
Pin 2 -> Pin 3
Pin 3 -> Pin 2
Pin 5 -> Pin 5
</pre>
(9pole SUB-D)
<pre>
serial ser: (amiga/aros) tty2 tty1USB0 (linux) COM1 (windows) (depends on the os being used)
speed baud transfer rate 9600 38400 lower baud might be more successful
data bits 8
stop bits 1
parity none
handshaking flow control - none xon/xoff (most likely) rts/cts dsr/dtr (pins not connected so should not work)
</pre>
*You cannot use compiled aros X86-64 bit software (when ready) on aros X86 32bit. PPC compiled software on X86 and so on.
*68k is tested with the UAE emulator (WinUAE) but some tests are done on native 68000 based Amigas and others.
*PPC support is very limited to certain devices.
If you use the WBStartup, you have to delete the other icons in the folder (readme etc..) and you have to add in the Icon Tooltype the parameter DONOTWAIT
If you use user-startup instead, you need to add the attached command "after assignment to LUA"
C:WBRun DH1:Extras/Utility/WeatherBar/WeatherBar >NIL:
Change the command to match your WeatherBar path.
<pre>
PATH sys:Utilities/WeatherBar ADD
run >nil: lua:amilua weatherforecast.lua
</pre>
To enter data your Country or City, ist with city_id numbers can be found [http://bulk.openweathermap.org/sample/city.list.json.gz here] or you need to go to [https://www.bbc.com/weather BBC Weather], once you type the name of your city or town in the appropriate tab, and press enter, the 7 numbers to be added in the "WeatherBar" will appear on the Browser url address bar above
Unicode v16.0 emojis are not supported but [https://github.com/jens-maus/libcodesets codesets.library] provides
<pre>
internally supported (hardcoded) charsets/codesets are: (conversions are possible from and to each codeset):
AmigaPL – Polish (Amiga)
Amiga-1251 – Cyrillic (Amiga)
ISO-8859-1 – Western European
ISO-8859-1+Euro – West European (with EURO)
ISO-8859-2 – Central/East European
ISO-8859-3 – South European
ISO-8859-4 – North European
ISO-8859-5 – Slavic languages
ISO-8859-9 – Turkish
ISO-8859-15 – West European II
ISO-8859-16 – South-Eastern European
KOI8-R – Russian
UTF-8 – Unicode
In addition, external charset table files can be stored in LIBS:Charsets or loaded by an application from PROGDIR:Charsets. The charset files included with this distributions are:
IBM866 – Cyrillic (cp866)
ISO-8859-7 – Greek (LatinGreek)
ISO-8859-10 – Nordic (Latin 6)
windows-1250 – Central/East Europe (Windows)
windows-1251 – Cyrillic (Windows)
windows-1252 – West European (Windows)
</pre>
Icaros 2.3 USB image needs a header stripped so it can work correctly
dd bs=512 skip=1 status=progress if=icaros_light_2-3-0_pendrive.bin of=/dev/sdxy && sync
Scalos
<pre>
-------------------------------
{ "STRING", "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K",
HALIGN LEFT | CENTER | RIGHT
VALIGN TOP | CENTER | BOTTOM
STYLE NORMAL | BOLD | ITALIC | BOLDITALIC
FONT // font specification - format: "fontname.font/size"
-------------------------------
arguments for STRING SRC
"diskstate",
"diskusage",
"diskusagefree",
"diskusageinuse",
"diskusagepercent",
"fibfilename",
"filecomment",
"filedate",
"fileprotection",
"filesize",
"filetime",
"filetypestring",
"iconname",
"linktarget",
"plugin" pluginname <optional plugin arguments>
"versionstring",
"volumecreateddate",
"volumecreatedtime",
"volumeordevicename",
-------------------------------
arguments for HIDE
"novolumenode",
"isempty" (some STRING)
-------------------------------
all internal commands:
"about",
"backdrop",
"cleanup",
"cleanupbyname",
"cleanupbydate",
"cleanupbysize",
"cleanupbytype",
"clearselection",
"clone",
"close",
"copy",
"cut",
"delete",
"emptytrashcan",
"executecommand",
"formatdisk",
"iconify",
"iconinfo",
"lastmsg",
"leaveout",
"makedir",
"open",
"parent",
"paste",
"putaway",
"quit",
"redraw",
"redrawall",
"rename",
"reset",
"selectall",
"showallfiles",
"showonlyicons",
"shutdown",
"sizetofit",
"snapshot",
"snapshotall",
"snapshotwindow",
"unsnapshot",
"update",
"updateall",
"viewbydate",
"viewbyicon",
"viewbysize",
"viewbytype",
"viewbytext",
</pre>
{{status|50%}}
{{BookCat}}
hxeju184seunnshd15idltm3yifo10d
4675910
4675864
2026-10-13T19:12:25Z
Jeff1138
301139
4675910
wikitext
text/x-wiki
{{ArosNav}}
==What is AROS==
Google translation
[http://translate.google.com/translate?hl=en&sl=auto&tl=de&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs German], [http://translate.google.com/translate?hl=en&sl=auto&tl=nl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Dutch], [http://translate.google.com/translate?hl=en&sl=auto&tl=fr&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs French], [http://translate.google.com/translate?hl=en&sl=auto&tl=it&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Italian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=da&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Danish],
[http://translate.google.com/translate?hl=en&sl=auto&tl=es&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Spanish], [http://translate.google.com/translate?hl=en&sl=auto&tl=hi&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Hindi], [http://translate.google.com/translate?hl=en&sl=auto&tl=zh-CN&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Chinese],
[http://translate.google.com/translate?hl=en&sl=auto&tl=ru&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Russian],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pl&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Polish], [http://translate.google.com/translate?hl=en&sl=auto&tl=ja&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Japanese], [http://translate.google.com/translate?hl=en&sl=auto&tl=ko&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Korean],
[http://translate.google.com/translate?hl=en&sl=auto&tl=pt&u=http%3A%2F%2Fen.wikibooks.org%2Fw%2Findex.php%3Ftitle%3DAros%2FUser%2FDocs Portuguese],
*Computer Hardware
*AROS (operating system)
*Applications and Games
*User
[http://www.osnews.com/story/15819 AROS] is one of the intermediate levels between the computer hardware and the user. It is an open-source, clean-room implementation of AmigaOS 3.x that can be run on many different computer architectures. It runs primarily on PC x86 32bit and 64bit but also on amiga motorola 68k and compatibles, some ARM like the Pi and Apple Silicon, RISC-V and some old PowerPC.
This page will cover enough to be able to write the downloaded image to your preferred media, to run a LiveUSB, LiveCD or LiveDVD on your office/home PC (Live meaning you can test without changing your existing setup) and, ultimately, to use it.
Intel / AMD PC hardware support mostly covers the years 2000 to 2024. At the moment, AROS is '''not''' recommended to be '''installed''' on a working vital data holding machine. Instead, writing to and booting from a '''USB stick''' could be a much better option.
AROS is an hobby OS and can co-exist with Windows(TM), MacOSX(TM), Android(TM) or Linux(TM) and act as an alternative.
Unfortunately, Aros has few developers so upgrades and improvements can take [https://sourceforge.net/p/aros/mailman/aros-cvs/ time to appear].
AROS core is now [http://en.wikibooks.org/wiki/Aros/Developer/IncompleteAPIs ~80%] finished and is usable, so keep in mind that the software is still considered ALPHA/BETA and in constant development. Currently AROS is fun to play with on a curiosity level, but it is also interesting to program. AROS has some multimedia features and has internet access.
Most importantly, use AROS to its maximum potential as it stands now, find ways to have fun with it and share your experiences.
Good Sites to visit
: [https://www.arosworld.org/home.php Aros World User forum]
: [https://arosnews.github.io/ AROS News]
: [https://www.facebook.com/ArosWorkshop/ Aros Workshop],
: [https://www.osnews.com/topic/amiga-aros/ OSNews]
: [https://www.reddit.com/r/aros/ Reddit]
: [https://archives.arosworld.org Aros Archives]
: [https://aminet.net/ Aminet]
: [http://www.amiga-news.de/en/ English translation of German site]
: [https://aros.sourceforge.io AROS] with [https://aros.sourceforge.io/download.html ABIv1 downloads]
: [https://github.com/aros-development-team/AROS Aros ABIv1 Codebase]
: [https://github.com/aros-development-team/AROS/issues register ABIv1 issues] and [https://sourceforge.net/p/aros/bugs/ old defunct bugs notification site]
: [https://sites.google.com/view/arosone Aros One x86, x64]
: [https://tinyarosdistro.flazio.com/ Tiny Aros x86 and x64]
: [https://arosnews.github.io/aros-portable/ AROS portable USB3 stick images of hosted Aros One x86 and x64 on debian]
: [http://vmwaros.blogspot.com Icaros Desktop x86 now on sabbatical, very old edition]
: [https://sites.google.com/site/arosaspireone AspireOS, of the netbook Aspire One, very old edition]
: [https://github.com/deadwood2 Deadwood's builds], [https://www.axrt.org/download/aros/v11/ v11 64bit PC builds], [https://axrt.org/downloads-aros Updated i386 32bit PC builds],
: [https://github.com/ezrec Ezrec x86 m68k mirror of old svn version]
: [http://arosalive.blogspot.co.uk/p/10-basic-aros-how-tos-tutorials.html Basic How To guides]
: [http://arosgamer.blogspot.co.uk/ AROS Playground], [http://thewetmachine.net/tag/aros/ Jess Wet Machine], [https://aroshacking.wordpress.com/ Jon Robertson's AROS Experiences and FPC Free Pascal], [],
:[http://www.apollo-accelerators.com/ Apollo Accelerators m68k], [http://www.amigablogs.net/ Amiga Blogs], [http://blog.a-eon.biz/blog/ Trevor Dickinson blog],
: [https://forum.amiga.org/ Amiga OS AOS 3.x forum]
: [http://eab.abime.net/ EAB Amiga]
: [http://www.amigaworld.net/ AmigaWorld]
: [http://www.ppa.pl/ Polish Amiga Like News]
: [http://www.apollo-core.com/ Apollo Forum]
: [https://amigaalive.blogspot.com/ AmigaAlive]
: [https://www.amigalove.com/software Disk Mags]
: [https://amigachristmastree.ultimateamiga.com/ Xmas Amiga Game Jam]
: [https://www.reddit.com/r/amiga/ Amiga]
== Distributions aka Distros ==
For end users there are distributions (ready made with selected apps aiming to be easy to use), mostly created and maintained by one person in their own workflow/style. They reuse the nightly boot compiles to suit their needs and possibly other end users. You are free to create your own if required.
* For native 64bit Intel/AMD: [https://sites.google.com/view/arosone Aros One x64], [https://tinyarosdistro.flazio.com/ Tiny Aros],
* For native 32bit Intel/AMD which will run on 64bit machines: [https://sites.google.com/view/arosone Aros One x86], [https://www.tinyaros.it/ Tiny Aros],
* For native 68k [https://sites.google.com/view/arosone Aros One m68k], [http://www.aros-platform.de/ AROS Vision],
'''Please, keep in mind that the distros listed above use a different ABI (abi v11) , which is NOT binary compatible with the official ABI V1.'''
* For hosted Linux usb drive image [https://arosnews.github.io/aros-portable/ x64 Debian hosted version of Aros One],
* For hosted ARM there is [https://github.com/jonx/AROS-AArch64/releases alpha for Apple Silicon] and [https://aros.sourceforge.io/nightly1.html RaspberryPi Pi3, Pi4, Pi400, Pi5, 500+ raspi-aarch64-system native 64bit]
AROS was originally developed on Linux but can run on an Intel-based Linux distro as an app. As time has gone on, it can be run as an app on many more operating systems (Windows, FreeBSD, Linux and limited on MacOS). This may sound strange: an OS running on top of another OS.
Basically, this is to take advantage of drivers (audio, internet, graphics, etc.) and compiler environments, in the existing OS, with which people may be already familiar. The term we use for what AROS does is "Hosted".
AROS Native is the term coined to describe AROS being run without any OS underneath it. It runs alone just like AmigaOS(TM) did. As this version does not benefit from "Hosted" drivers, dedicated ones have to be ported/written. Hence the smaller range of supported hardware / peripherals. We have other pages highlighting this support
AROS is open source so basically everyone can take part. The source is public on github and there are new commits most days. AROS is automatically compiled daily, result are the nightly builds hosted on Sourceforge. The nightly builds are only used for testing changes, testing software and the starting point for distribution maintainers or even your own distribution. They are very basic, miss some functionality and apps like web browsers and generic general appearance which can be changed.
* The [https://sourceforge.net/projects/aros/files/nightly2/ Nightly2], [http://aros.sourceforge.net/download.php nightly builds File Release Service] or [http://aros.sourceforge.net/downloads/ Sourceforge Project Web builds] are made automatically every night directly from the Github and in the past, SVN (Subversion) tree and contain the latest code for the AROS operating system. It should be noted that the builds have not been tested in any way and can be horribly broken but usually are not.
*ABIv1 standard for most nightly builds, it is where the most work is done by developers
*ABIv11 offspring aka fork of 64bit PC ABIv1 i.e. another PC 64bit build
*ABIv0 standard for PC 32bit intel / amd PC distributions for historic reasons
==Media==
AROS media tends to boot in this tier list of media types, first internal HDD SSD, CD DVD drive, and finally usb drive (last two can depend on bios boot order)
* USB .VHD
[https://sites.google.com/view/arosone Aros One x86 and x64], with md5 below
<pre>
0a656d53a9c902e9934000d8392e30ec *ArosOne-USB-1.3-64Bit.zip
7dd7119ab3e56d75ee852c137226b4d7 *ArosOne-USB-v1.2-x86_64-v11.zip
cf906eeaad4a83b3520b1896bdc6b0d3 *ArosOne-USB-v1.1-x86_64-v11.zip
e2eb8fe8cfd61c567b0152a61cf85251 *ArosOne-x86-v2.8-USB-IMG.zip
559909c75c2f56472c74267a7d075355 *ArosOne-x86-v2.7-USB-IMG.zip
93da5898508c1a8c05bb8991ab7bd117 *AROS One Image-USB-2.4.zip
59fcabd7090e47f12d54f7eb78cf0f45 *ArosOne-x86-v2.2-USB-Image.zip
24fb8de726ae8fc5fe5bac6d30f03dc5 ArosOne-x86-v2.0-USB-Image.zip
f3d725e990072edce633b59747911b6b ArosOne-x86-v1.8-USB-IMG.zip
e089a24ae310e92fcc407a0125602ce8 Aros-One x86-IMG-USB-v1.6.zip
</pre>
[https://tinyaros.flazio.com/ Tiny AROS]
22bc993625b7c75b17263c0cc7e7baaa *Tiny Aros_copy.vhd (March 2024)
There is usually a vhd image inside the zip that can be written to USB sticks which is so much faster than the old ISO written to physical CD DVD method. This .vhd can be written to an USB stick / ssd with these pieces of software below but it will erase the previous contents from the usb
Windows - [https://www.raspberrypi.com/software/ RPi Raspberry Imager, use custom and see all files], [https://hddguru.com/software/HDD-Raw-Copy-Tool/ HDD-Raw-Copy-Tool], [https://rufus.ie/ Rufus up to version 3.20 may work with VirtualBox HD vhd images with Win7 but not some Rufus 4.x versions], [https://etcher.balena.io/ Balena Etcher but may spy on you],
Linux - [https://www.raspberrypi.com/software/ Raspberry Imager Ubuntu], Suse Image / Multi writer, dd,
Mac -
* Virtual Machine .ISO or CDs DVDs
The native iso images are currently not compatible with Ventoy, Yumi, MultiBootUSB, Easy2Boot E2B, or similar
<pre>
617a905b1665128c5e05f94dcc48e7f1 *AROS-One-v1.3-64Bit-v11.zip
11c8a147fcad7ecf52ae3a43e1934b69 *ArosOne-DVD-v1.2-x86_64-v11.zip
f93053d3b9ccf304d7e6ac3389e1987b *ArosOne-DVD-v1.1-x86_64-v11.zip
86d808a40dc7be389a758799a9b4f595 *ArosOne-x86-v2.0-ISO-DVD.zip
f1fc8599ef6a39e5df394e0f41d55526 *AROS-One-x86-ISO-DVD-v1.6.zip
</pre>
You can use a virtual emulator like VirtualBox, VMWare to mount the iso image which can then be used to boot and/or install to USB.
No current software can write an AROS ISO to a Pendrive. The author of ‘Rufus’ (who used an Amiga 500 as a child) once tried, but when he saw the system composition, he said he was unable to do it.
The solution is to boot the ISO from a VM (WMware, VBox), then install the AROS build on the Pendrive, which will eventually become a Live Pendrive that can be booted on a PC.
The only precaution is that in some cases it is necessary to thoroughly clean the Pendrive of any partitions and remove any bootloader that is not AROS. The Pendrive must remain raw without any partitions.
You can clean the USB stick on a PC with a program that manages hard disks. You need to do a partition wipe. On some USB sticks, you can clean it with InstallAROS.
For some USB pendrives, please use a reputable partition editor to remove any and all partitions from a usb pendrive as HDToolbox cannot do this task sometimes with a wipe all option.
Previously the only installation option was CD-RW or DVD-RW, since the whole system can be burnt onto a single disk and can be reused when the next version is released. Good branded discs like Taiyo Yuden (later JVC) or Verbatim should be used to reduce frustration later. The days for this media is gone but kept here for information
Since nobody currently sells AROS on any other media, you will need access to a CD/DVD burner to create the installation disk yourself. After it is on a CD or DVD, then access and writing to USB pendrives becomes available (this should be viewed as an outdated or last resort alternative method now), as well as using good USB manufacturers like Sandisk, Kingston, etc. rather than some other no-names.
Try burning it to a CD-RW or DVD-RW using your CD/DVD burning program (most burning software have a burn iso option). The ideal writing speed is 2x or 4x, higher speeds can give errors and problems. Check the writing integrity of your CD or DVD if your software has an option to do so before going any further.
Standalone portable usb cd dvd drives do not boot physical burnt discs, please use an internal ide sata drive instead.
* SD-card
For [https://aros.sourceforge.io/nightly1.html ARM Pi Aros 64bit], copy the files onto a FAT32 formatted micro SD card.
==Booting==
The LiveUSB, and in the past LiveCD LiveDVD, is designed to trial (test drive) various operating systems without having to install them to your working system.
Since 2011, UEFI was introduced to replace the original PC BIOS which made booting media more confusing. Some changes in the UEFI/bios may be needed
*go into the bios using esc, f2 or f? and disable the Security -> Secure Boot and maybe apply option for Legacy IDE mode
*you may have to press F9, F10 or F12 or p on boot up to present a device boot options like USB or CD/DVD
*disable the Fast Boot config so it would recognize portable DVD-drive and changed the Boot-sequence
Secure boot was introduced by Microsoft and later consortium, control what operating systems work with Secure Boot via shims.
For Aros, it is best to disable and save the turn off change to Secure Boot (if you dual boot with Windows this will cause issues with further Window boots)
For the best experience, it is advised to install to another SSD than the one Windows resides on.
The grub part of the boot should be fully automatic, and you should see a multiple choice graphic card screen after 10 seconds for USB or 40 seconds CDs and DVDs.
If boot does not occur within a minute, please reboot and choose the VGA boot option as it relays a message stream so you can see where the issue lies.
After the grub graphics choice, AROS takes over the booting and any issues can arise here
If possible please use a branded usb pen drive as most of the time when we get reports of "crashes right after grub boot selection" it is mostly due to the recorded pendrive as they are made, notoriously on a will it work / will it fail nature, every time it is used.
<pre>
So one usb drive written may stop at a System halted. Reset the machine.
Or another pendrive will show give errors Smart Filesystem request - Volume 'Aros Live Drive' (DU0: usbscsi.device unit 0) There was an error while accessing this volume:
Or if a FAT32 partition present - FAT filesystem - Device USBSCSI0P1 has a read error on block xxxxxxxx -
</pre>
Sadly, no drive even branded are resistant or totally reliable, so the only solution is to try another pendrive, and possibly to repeat, until no errors.
It will give an indication on how reliable the usb drive could be.
=====Advice for various machines=====
Some of the stages involved and shown on the display in a typical AROS boot start up
<pre>
[MultiLoader]
[ELF Loader]
[Boot]
[HPET]
[Kernel:ACPI]
[Kernel:APIC-IA32]
[Kernel:SMP APIC]
[HiddStorage]
ACPI: ????
ACPI Error
[ACPI]AcpiOs????
[BattClock] Got RTC century offset 0x32 from ACPI
[PCI] Scanning bus ?
[AHCI] Sata
[Vesa] only if vesa is chosen as graphics option
[ATA] detect hd & cd drives
[ATA0?] ata-identity
[packet] fat.handler be.handler, etc.
[DOS]
[Storage:Bus]
[Storage:Controller]
[MSS] USB setup
[ehciInit] Port ? maps to controller ?
[I2C]
[ATI]
[drm] nouveau
[AROSTCP] if you have network driver prefs set up to start when booting
</pre>
; If boot fails, please give us some indication (pictures or videos) where the boot stops and the message(s) on screen.
AROS's native SATA/AHCI driver doesn't always work. If you get errors related to ahci.device, try disabling it. At your chosen boot entry in the GRUB menu, Press E, scroll down to the ahci.device entry, and add a # or ; at the start of that line or delete it with Ctrl-K. Then press Ctrl-X or F10 to boot.
If your disk isn't accessible at all with this change, you might need to change the SATA controller to IDE legacy mode in the BIOS: however, making this change will likely cause problems booting Windows on the same machine (if it's already installed). To disable ahci.device permanently, edit the text file "SYS:Arch/pc/grub/grub.cfg", and remove the ahci.device line from all boot entries you intend to use.
SATA AHCI Timeout while waiting for device to complete operations with BIOS SATA entry set to AHCI mode stops at "waiting for bootable media" screen, changing BIOS SATA setting back to IDE mode may allow it to continue booting
The ATA driver doesn't always work. If you get errors related to ata.device, try using the alternative in sys:devs/alt which is an older version. Press E when your chosen boot entry is highlighted in the GRUB menu, scroll down to the ata.device entry, and change it to read "module /Devs/Alt/ata.device". Then press Ctrl-X to boot. To make this change permanent, edit the text file "SYS:Arch/pc/grub/grub.cfg", and change the path to ata.device in all boot entries you intend to use.
Further options (removing the " ") to add to the GRUB menus to disable certain other components for debugging:
<pre>
Disable AHCI "AHCI=disable"
Disable NVME "NVME=disable"
Disable ATA: "ATA=disable"
Disable ATA: "ATA=nopci,nolegacy"
ATA safe mode: "ATA=nodma,32bit"
Disable IDE from SATA: "ATA=32bit,nosata2pata"
VIA / SIS with cdrom read io errors "ATA=nodma,nopoll"
noacpi all [PCI] devices to be invisible to AROS. disk drives work but network, sound won't
acpi=strict if there are issues with sound after boot
noioapic alternative to no acpi
Set AHCI "AHCI=force150/force300/force600"
Disable AHCI/SATA: comment out with a # ; or remove ahci.device line with Ctrl-K
Disable USB: comment out # ; or remove pciusb.device and poseidon.library lines with Ctrl-K
Disable native graphics: "nomonitors"
USB3 "USB=xhci"
</pre>
Other useful grub command line options - nomonitors, noacpi, vesahack, nopoll
Press Ctrl and X together (or F10) to exit and boot with the new options. Just experiment with different variations until successful. Those working options will need to be reused with every reboot of AROS until you can edit the grub.cfg and make it permanent i.e. install to hard disk or USB.
* If you use VESA mode, you can see the debug log if you add 'vesahack' to the command line. This will set up split-screen mode. In the upper half you'll see AROS screen, in the bottom - debug log.
* ACPI ie. PCI hardware - If you get crashes at early boot, try adding 'NOACPI' to the command line
If you're having boot issues and have a null modem cable and a spare pc, a boot log is always useful. Edit your grub line to include debug=serial but would try with an with sysdebug=all in the line later as it can cause issues booting on machines with sysdebug=all enabled (corrupts the cpu initialization).
However, if you feel you have found a genuine bug/fault in AROS that needs attention, please use the [http://sourceforge.net/tracker/?atid=439463&group_id=43586&func=browse bug submission form] to record as much information about what happened, why, and what hardware etc. you have so that people may try to assist you
For Virtual machines VMWare VirtualBox, etc., attach and press play to start the ISO image
If booting hasn't worked then it could be down to Bios/UEFI settings
=====nvme.device=====
Since 2018, nvme drives are standard on most machines
The requirement is that a PC can boot with legacy mode/BIOS at the moment - Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
This is still in testing and its' use should not be on or near precious own data
=====AHCI=====
Starting taking over since 2011 on a lot of machines
* Check that UEFI (replacement for PC BIOS) has options set to remove UEFI SecureBoot option and apply CSM
* SATA drive is set for Legacy or a mixture AHCI/IDE and not AHCI
AHCI sata can be very difficult to get working
Most Windows installs are already set to AHCI sata, changing this to a legacy IDE mode setting can help but please check if Windows will still boot. Some hardware like Lenovo laptops do not always like being set in legacy mode so only use as a last resort and aware of issues that can be caused.
Now as far as hardware goes on a newer machine with an NVME drive you may need to add NVME=disable as the NVME driver could potentially cause lockups.
With a 16C/32T chip machine, disable SMT and it should boot.
=====ata.device for old BIOS's =====
Pre 2010 this was the de facto standard method of providing settings to the computer at a lower level
Some adjustments to the BIOS setup options are necessary (usually by pressing a key like DEL, F1, F2, F12 or ESC, p on the very early boot up of the computer).
*Adjust booting options like moving USB hdd, CDROM higher as it is quite often disabled or placed lower by default, i.e. USB hdd, CD/DVD are placed at the top above the hard drive. Try looking here [http://www.windowsreinstall.com/articles/bios/ Windows] or [http://www.hiren.info/pages/bios-boot-cdrom Bios] or [http://www.wikihow.com/Set-Bios-to-Boot-from-a-CD-ROM Boot] or web search "BIOS BOOT CDROM"
* At the '''SAME''' time, check if the SATA/AHCI option is set to Emulate or IDE Legacy, though this can have '''issues''' with any OS already on the hard disk. If in doubt, do nothing and seek advice.
* check that under BIOS settings you '''DO NOT''' have plug&play OS selected as Aros at this point is unable to route interrupts on its own and needs the BIOS to do that.
'''Save''' options changed at the end.
PCITool can show if the motherboard chipset is in IDE mode.
Class = 0x01 means STORAGE, Subclass = 0x01 means IDE. Also ProductID 0x3a20 resolves to non-AHCI mode in Intel ICH10 documentation.
==Installing==
We have a separate section [https://en.wikibooks.org/wiki/Aros/Platforms/x86_installing here]
We have a specific section for each CPU platform under the Specific platforms in the NavBar navigation bar on the right hand side menu
error code (-6) when using the ahci.device (has writing to disk problem but not reading) is enabled. change this line in your grub and reboot
<pre>
#module /Devs/ahci.device << disable
module /Devs/Alt/ata.device << add this line instead
</pre>
==File structure overview==
AROS' directory structure is mostly identical to AmigaOS directory structure, with some additions.
AROS: or SYS: also known as DH0: (i.e. the drive partition with AROS system) has the following simplified list of the main drawers (Amigas term for directories/folders).
{| class="wikitable"
|boot:
| grub bootloader
|----
|C:
| small apps, where AROS looks first for applications/games but will look at Tools, System afterwards
|----
|Classes:
| .class as well as datatypes
|----
|Devs:
| .device .resource and in their own drawers (folders) .audio, .hidd, network, graphics
|----
|L:
| where .handler files go
|----
|Libs:
| where .library files go
|----
|Locale:
| where help guide txt readme files go
|----
|Prefs:
| applications that adjust or setup AROS functions and capabilities
|----
|S:
| startup scripts (for the aros boot process '''not''' grub) are stored here
|----
|Storage:
| place to keep old or alternative device drivers
|----
|System:
| applications associated with AROS operating system
|----
|Tools:
| extra applications
|----
|Utilities:
| extra applications
|----
|WBStartup:
| copy applications here to autostart with needed icons, drawers, data etc
|----
|}
See [[Aros/User/DOS#Drives.2C_Files.2C_Assigns.2C_Directories|DOS manual: Drives, Files, Assigns, Directories]]
=== Filesystem ===
Whilst the kernel is the heart, the filesystem is the blood of the system they are split into two categories (only a few are supported)
<pre>
Journalling - SFS PFS3 but also NTFS ZFS XFS ext4
Non-journaling - FFS FAT32(VFAT) but also exFAT BtrFS ext2
</pre>
Filesystem options for AROS to install
* SFS default
* Professional File System PFS3 [http://eab.abime.net/showthread.php?t=52234&highlight=pfs3+free&page=13 only on motorola 68k at the moment] [https://github.com/aros-development-team/AROS/blob/e34170ea87da3b32935b60ed99d837b2b903a021/rom/filesys/pfs3/fs/mmakefile.src issues to compile on other platforms]
* FFS very old now but left in for legacy usage
Other [https://archives.arosworld.org/index.php?function=browse&cat=driver/filesystem filesystems] for storage purposes
* FAT32 favorite as most OSs support
* NTFS (can lock AROS)
* exFAT there is a [https://www.jkn.me/blog/bringing-exfat-to-aros/ standalone version] as well as the fuse based one
The only filesystems that really NEED defragging (i.e. disk tidy up) are from Microsoft(TM) - exFAT/VFAT/NTFS
*SFS tries to do exactly the same thing, but in certain cases it doesn't do as well as PFS. But you can defrag SFS
*PFS *minimises* the amount of fragmentation, but does not automatically defrags as it saves files to the drive
The setup of the below filesystems is usually done by the distro maintainer but if not....
<pre>
Copy L/exfat-handler L:
DOSDriver or Mountlist entry for an exFAT partition make sure that the FileSystem and Handler are set as follows:
FileSystem = exfat-handler
DosType = 0x46415458
</pre>
<pre>
Copy L/ntfs3g-handler L:
DOSDriver or Mountlist entry for an NTFS partition make sure that the FileSystem and Handler are set as follows:
FileSystem = ntfs3g-handler
DosType = 0x4e544653
Also to make a read-only mount you can set:
Control = ro
</pre>
The Smart File System (SFS) is a journaling filesystem used on Amiga computers and AmigaOS-derived operating systems. It is designed for performance, scalability and integrity, offering improvements over standard Amiga filesystems as well as some special or unique features.
SFS is written in C and was originally created and released as freeware in 1998 by John Hendrikx. After the original author left the Amiga scene in 2000, the source code to SFS was released and its development continued by Ralph Schmidt in MorphOS.
Its development has now forked; as well as the original Amiga version, there are now versions for MorphOS, AROS, AmigaOS 3, and a version for AmigaOS 4, which have different feature sets but remain compatible to each other. Versions for AROS, AmigaOS and MorphOS are based on different branches.
In addition, there is a driver for Linux to read Amiga SFS volumes, GRUB natively supports it and there are free drivers to use it from UEFI. The Linux version is [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ independent code].
SFS (Smart File System) partially defragments itself while the filesystem is in use. The defragmentation process is almost completely stateless
AROS SFS version has a 120GB partition size limit on hard disks and DVDs current 4gig size limit.
The sources for the MorphOS 64-bit version of SFS were available but no porting to AROS has happened so far due to endian issues, etc.
SFS Tools
* GUI - arSFSDoctor,
* CLI - sfscheck , [http://www.portacall.org/ sfsundelete], sfsformat, setcache hits a usability ceiling around the 10GB / 100,000 file mark,
sfscheck dh0: seek purge fraglist defragment
If there are two simultaneous file writes in progress and you reboot machine (or it locks up or crashes) you may end up with a corrupted filesystem. Although arSFSDoctor may help, you might have to copy the files to another partition, format the partition with the errors on and copy the files back.
PFS / SFS are way more advanced and much much faster than the FFS. FFS is supported for legacy reasons only.
The Professional File System (PFS) is a filesystem originally developed commercially for the Amiga and now distributed on Aminet with a 4-clause BSD license. It is a compatible successor of AmiFileSafe (AFS), with an emphasis on added reliability and speed compared to standard Amiga filesystems. It also features multi-user abilities like the older MuFS.
PFS has so many advantages including the important things, speed, the ability to recover all deleted files even simply same name by typing the command ". Deldir" convenient if done in Directory Opus, virtually deleted files are copied normally as if they had never been deleted, other convenience is to not ever invalidate the filesystem, just put it on top of the startup-sequence command "diskvalid", which automatically corrects any irregularities in the system startup; PFS also provides a device for floppy which makes them very fast and takes advantage of the full capacity of the floppy including the area dedicated to the bootloader.
The device is split into two main areas. At the beginning of the device is the metadata section, which consists of a root block, and a generic array of blocks that can be allocated to store metadata. The rest of the device is another contiguous generic array of blocks that can be allocated to store data. The metadata section usually uses a few percent of the device, depending on the size of the device.
The metadata is stored as a tree of single blocks in the metadata section. The entire directory structure is recorded in the metadata, so the data section purely contains data from files. The metadata describes the location of data in files with extents of blocks, which makes the metadata quite compact.
When a metadata update occurs, the system looks at the block containing the metadata to be changed, and copies it to a newly allocated block from the metadata section, with the change made, then it recursively changes the metadata in the block that points to that block in the same way. This way, eventually the root block needs to be changed, which causes the atomic metadata update.
The filesystem is reasonably good at keeping files unfragmented, although there is a defragmentation tool available which will work on an online filesystem ie whilst being used.
It was the first filesystem to introduce the concept of the Recycle Bin natively at filesystem-level to the Amiga, holding the last few deleted files in a hidden directory on the disk root.
PFS version 5.3 was developed in C and a small portion of assembly code by Michiel Pelt. There are endian issues to be overcome and adapting the small amount of m68k to C before use on intel based machines, etc.
Autoupdate of files in a directory is already implemented in Wanderer, but not all file systems handle dos.library/StartNotify() in its full extent. It seems to work correctly in Ram Disk (thanks to AmberRAM handler), and it also works on SFS formatted devices. Other file systems might not yet have it implemented correctly though.
The PC equivalent of the Amiga's RDB is the master boot record (MBR).
===Installing Applications===
The typical means to install applications under AROS/AmigaOS involves simply copying/extracting the archive (.zip .lha .rar .tar.gz) file containing the applications files to your own desired location i.e. drawer/folder. Once extracted, launching it by double clicking on an icon (recommended) or using the shell (alternative). Generally, this is on a separate partition from your AROS system files, however in reality it can be any location - including RAM: if you don't want it staying around too long especially when you switch off.
At some time in the future it may be desirable for AROS to have a package-manager like subsystem able to retrieve information online about packages available for AROS and whether they update anything you currently have installed, however at the moment no such ability exists.
===User Data files===
AmigaOS has no notion of a default location to store user data files, and presently neither does AROS - though it may be desirable at some time to provide a common start location.
Some people, have extra small FAT32 partition(s) using HDToolbox, and not Qparted, to store data especially if a reinstall is ever needed. And then setup the usual Sys: (DH0:) and maybe Work: (DH1:) / Live USB (DU0:) and maybe Briefcase (DU1:) partitions.
===User Environment configuration files===
AmigaOS/AROS stores persistent system configuration data in directory assigned to ENVARC:. This, by default, points to SYS:Prefs/EnvArc.
During boot a copy is made to another assign, ENV:, which is for runtime usage. Changes to the files here will not survive a reboot.
Setting the env variables is generally done by applications themselves, or when necessary by the user using the SetEnv command. SetEnv has a SAVE switch to force the persistent copy in ENVARC: to be written also for when you are sure the change should be permanent.
Under the standard installation of AmigaOS style OSs, ENVARC: is copied to ENV: upon startup, which, if you have a hard drive installation, is in RAM:, hence, ENV: ends up being RAM:Env.
ENVARC: is the Environment Archive, which is the permanent copy of ENV:, which is the Environment. It's roughly like the Registry in Windoze.
Most programs do (and all should) store their settings in ENVARC: somewhere, and load them from ENV:. The effect of this can be seen in the Preference editors. If you Save your preferences, they go in ENVARC: and ENV:. If you click Use, they only go in ENV:. If you reboot, normally, anything saved to ENV: is lost, and is replaced with a copy of what is in ENVARC:.
you can set the default public screen for any tool started from a cli with the PUBSCREEN variable. So open the pubscreen, set PUBSCREEN to the name and start newcli for example, then the new cli window (and all following windows opened from that window) will appear on that public screen.
===Drivers===
For certain hardware, e.g audio, networking and , there is no auto setup. Just like the original Amiga OS.
For audio, use AHI in the Prefs folder to set Music and at least Unit 0 with the appropriate driver and press Save. For ethernet and wifi, please use SYS:Prefs/Network
All hardware support is placed in the Devs drawer (folder/directory). The network drivers <something.device> go in the Networks sub-drawer. Audio drivers <something.audio> are put in the AHI sub-drawer. Graphics drivers <something.hidd> are put in the Drivers sub-drawer.
==Configuring==
AROS has mainly decided on a MUI-like requester&menu clone called Zune so changing the background, icons, font, menus can be done with SYS:Prefs/Zune
AROS has several desktop GUI front ends like
* DOpus5 Magellan II, Wanderer and Scalos (medium)
* AROS Workbench, Workbook (smaller)
File / Directory managers like Dopus4, MCAmiga,
App Launch Shortcuts like FKey, BoingIconBar, right mouse click on magellan, wanderer desktop, Amistart, etc.
General usability decisions - Prefs/IControl, Prefs/Locale, Prefs/Input, Prefs/Fonts,
Select an icon with left mouse button and then right click the mouse button and selecting Icon -> Information gains access to the tooltypes tab where information can be edited
CLI in icon's tooltypes means 'run it as if it was run from shell'
If, on the other hand, the WB parameter (or no parameter) is present in Tooltypes, Wanderer will execute the binary and, if provided, the options included in Tooltypes.
WBxCLI is very useful for adding options to DOS Commands.
Important: AROS has a different way of managing icons. If you have an executable file, you will never be able to add a project icon. AROS will automatically recognise that it is an executable file and will transform the icon into a tool icon.
Icons are typically now .png pictures renamed as .info e.g. so Office application name would have a Office.png renamed as Office.info or MyApp.png as MyApp.info, etc.
Leave Out menu option to leave app icon on desktop
To select multiple icons and save their positions, click on the first icon and after while you hold the Shift key down select further icons and don't release it before SnapShot is finished. You can also select a whole group of icons by pressing the LMB at the top left of the icons and while keeping the LMB down moving the power towards the bottom right. A expanding bounding box will appear and all the icons within it will be selected.
Clean Up menu option (right mouse button -> Icons) rearranges icons in a drawer or disk window into a neater condition. To use, open the window to rearrange and select Clean Up. To keep the icons in the new positions, select all the icons (shift key or mouse selection) and select 'Snapshot' and then Window and then again with All.
In DOpus5, Scalos, wanderer, most files have an icon file associated with it. To change the default tool, select Icon menu, Information, and change the default tool string. For example, you could use Multiview, Editor and so on for most text, graphics and some sound files as long as the appropriate Datatype classes are installed. For scripts, set the tool to C:IconX
We have new Icon edit tools in progress but if you need to...
C:Join Image1.png Image2.png TO MyFile.info
is enough to make a dual state icon from two png images. You can then use Wanderer's menu Icon/Information on it to edit its fields and tooltypes.
[https://archives.arosworld.org/index.php?function=browse&cat=graphics/icon AISS toolbar images] unpack unarc them into RAM: and copy Images directory to SYS:Prefs/Presets/ AISS icons are looked for in PROGDIR:, PROGDIR:Images, SYS:Prefs/Presets/Images and then in TBImages: according to Open Amiga guidelines.
there is Demos/iconscale which could be launched from S:User-Startup with two arguments, telling it the horizontal and vertical size. IE something like
Demos/iconscale 40 40
It will shrink icons... not sure if it will be very nice though. it doesn't work for the icons on the main desktop.
there is an option to scale an icon to a bounding box afair, try iconsize followed by two numbers, like:
iconsize 32 32
Is there any way in AROS to change an icon type from Project to Tool or vice versa?
Either the SIT option of [ ProcessIcon], or the TYPE option of HandleInfo (not sure if this one works at all, please test with care).
processicon sys:pathoftheicon SIT=Project
SIT Set type of ICON. Allowed types are: "Disk", "Drawer", "Tool", "Project", "Garbage", "Device", "Kick" and "AppIcon".
Btw, are your icons, the #?.info files, writable, is the W flag set ?
'''Decoration''' is Aros' way to provides a way to hide the old Workbench 3.1 style of windows and screens. In Prefs/Appearance some decorative theming elements need work
Themes - SYS:Prefs -> Appearance
The default content of Prefs/Env-Archive/SYS/themes.var should be "themes:ice" but can be changed via the Appearance prefs, please do NOT click the Use button. Its useless. As you know, it will ask for the theme volume. Just pick the theme you want, click on Save, then reboot.
* Decoration is on. Any time trying to change theme, you get: "Please insert volume Theme: in any drive"?
You could check if you find SYS:System/Themes or if it is missing. Then you could open startup-sequence which you can find in drawer "S". There should be a line:
Assign THEMES: SYS:SYSTEM/THEMES >Nil:
This does the trick.
Open a shell and run:
Assign THEMES: SYS:SYSTEM/THEMES
Than start the Theme prefs again... this should work
* The theme is the only thing that could slow the system a bit, but it's not that performance impacting on most uses, and you can switch it off completely. Remove C:Decoration from the bottom of the file sys:s/startup-sequence.
In each theme directory is
*Env-Archive -> Zune -> global.prefs
*images -> Gadgets -> 20x20 pngs for Down etc
*menu -AmigaKey - Background - Checkmark - SubMenu and config
*system - Arrowdown, Arrowleft, Arrowright, Arrowup, etc
There is an [https://archives.arosworld.org/index.php?function=browse&cat=graphics/theme ALua/Zulu script] built for faster Wanderer skin management. You can modify config files, install new (wdz format/zipped skin files) and delete skins via the Theme Manager. This has not been updated in a long time and may not work.
Certain features are added if from Tools/Commodities like Blanker screensaver, ClickToFront and DepthMenu with .info icons are selected and dragged to /WBStartup folder
Most apps can be autostarted by copying into SYS:WBStartup directory folder
e.g. WeatherBar.zip can be downloaded, unzip and the contents of the zip copied to wbstartup folder
ClicktoFront and .info to SYS:WBStartup so always be activated when turning on the computer
or add a text line to user-startup is SYS:S (scripts version of wbstartup)
e.g. standard Amiga / AROS does not allow clicking of background windows to come to the front to make it easy to get to the window you need but it has the ability if these apps are copied again to WBStartUp or are added to SYS:S/user-startup script
run QUIET sys:Tools/Commodities/ClickToFront >Nil:
run QUIET sys:Tools/Commodities/DepthMenu >Nil:
run QUIET sys:Tools/Commodities/Blanker seconds=300 >Nil:
Exchange controls Commodities and can be opened with alt, ctrl, h
*AltKeyQ uses left Alt key to add strange letters
*AutoPoint
*Blanker screensaver
*ClickToFront allows windows to be easily brought to the front
*DepthMenu adds menu to select window easily
*NoCapsKey
*Opaque
*FKey - Although there are heaps of docks, menus and other launcher programs on the Amiga like OSs, FKey has got to be one of the quickest once learnt ways to launch programs, and it comes with the OS. In SYS:Tools/Commodities, the FKey commodity (Ctrl Alt F) allows you to make actions assigned to some combinations of keys
<pre>
ALT TAB Cycle Windows
Cycle Screens
Enlarge Window
Shrink Window
Toggle Window Size
Insert Text
Run Program
Run Arexx Script
</pre>
e.g.
<pre>
LAmiga F1 = Avail Flush
LAmiga F2 = Open Prefs
LAmiga F3 = Finder
Alt Tab = Cycle Windows
LAmiga Tab or M = Cycle Screens
Alt Up arrow = Enlarge Window
Alt Down arrow = Shrink Window
Alt Home = Toggle Window Size
= Insert Text
LAmiga e = Run Program
= Run Arexx Script
</pre>
If your FKey GUI pops up when you start your Workbench up and you don't want it to, click once on the icon, go to the Icons-Information in the menu and make sure it has the tooltype set "CX_POPUP=NO".
Now let's launch it and assign the locale switching. After you double-click on FKey icon, launch the Exchange, choose the FKey from list and click the Show button. This will invoke the FKey window. You can see the ALT TAB in list assigned to window switching. Now enter the first key combination, say, ALT Z and go to the right panel. Choose Launch the program from pulldown menu and enter SYS:Prefs/Input as an argument. Append the USE switch and english preset name to the string as shown:
SYS:Prefs/Input USE SYS:Prefs/Presets/english
Click on the New Button to add the another combination. Now set the combination for your locale as shown above, replacing English name with your preset name. Click New button again and then Save Settings. Now you can use defined combinations to switch the layouts.
There is a system wide ARexx script capability (based on regina) that can manage many file manipulation task(s) but this would work only with those program that support [https://en.wikibooks.org/wiki/Aros/Developer/Docs/Rexx ARexx] like
*Desktop - DOpus5, Scalos
*Dock - FKey,
*Files - Multiview, DOpus4,
*Internet Apps - Odyssey, WookieChat,
*General Apps -
the shell can be modified with escape strings but not needed in most cases
Common Keyboard Shortcuts
<pre>
RAlt Right Alt Key
LAlt Left Alt Key
RWinKey Right Windows Key
LWinKey Left Windows Key
RAmiga Right Amiga Key (if one)
LAmiga Left Amiga Key (if one)
</pre>
;Bootup Options
:Spacebar during boot, enters the bootmenu which allows a boot without startup sequence, etc
;Left Click
:LAmiga = LWinKey = F11
;Right Click
:RAmiga = Help = F12
;Mark
:RAmiga and B
;Cut
:RAmiga and X
;Copy
:RAmiga and C
;Paste
:RAmiga and V
;Search
:RAmiga and S
;Mouse Movement
LAmiga and together with arrow keys - shift as well at the same time as well to move faster
;Mouse Selection
LAmiga and LAlt to select
;Screen Switching
LAmiga and M or N
;HELP key
Can sometimes be mapped to F11 but can be changed via FKey
ComKeyRemapper or AmigaKeyremapper could swap RAmiga to another key press
===DOpus 5 Directory Opus Magellan II===
Dopus 5.x is a whole desktop replacement on the Amiga Workbench (Desktop)
DirectoryOpus app will assign DOpus5: to it's PROGDIR: automatically but if not add the below (edit SYS:System to suit where Dopus5 was installed) to your startup-sequence
<pre>
Assign DOpus5: SYS:System/DOpus5
DOpus5:DirectoryOpus
;DOpus5:C/LoadDB
</pre>
Left mouse button clicked twice on the desktop background brings up the Device List window.
Green strip notifies SRCE (source) and if another is open it will be red for DEST (destination). clicking on the red strip changes to green
Word list of actions with a left mouse click on the DOWN Arrow and directory stuff with < button which mirrors the icons at the top of each lister
single-key hotkeys? exactly the same as in dopus4, edit your functions (button bank, toolbar, menus etc.) and under the flags gadget is a key gadget, just click in it and press the key you want to use.
As for the extra text field... try turning off Extended lister key selection in environment / miscellaneous.
Shift and click on the icon - runs the icon
DOpus5 Magellan 2 Directory folder drawer structure
<pre>
ARexx - Arexx scripts .rexx and .dopus5 to perform tasks
Buttons -
Commands -
Desktop -
Environment - two environment files bundled:
default gets loaded if you run DOpus as a normal app
workbench gets loaded if you run DOpus as a WB Replacement (with LoadDB on startup)
Filetypes -
Groups -
Icons -
Images -
Modules - compiled tasks
Settings -
Sounds -
Themes -
WBStartup - Use this if standard SYS:WBStartup gives cannot wait error messages
</pre>
Settings -> Environment -> Display -> Workbench (Use)
*Settings -> Clock (add to title bar as well as the date)
*Toolbar -> Editor (Right Win Key together with 1) for Copy, Move, Delete, etc above the Device List
*Menu -> (Right Win Key together with 2)
*Buttons -> Editor (Right Win Key together with 3)
*Settings -> Environment (Right Win key together with 4) for Backgrounds, etc
*File Types -> (Right Win key together with 5)
*User Menus -> (Right Win key together with 6)
*Hotkeys -> Setup for quick shortcut keypresses (Right Win Key together with 7)
*Scripts -> (Right Win key together with 8)
*Icon Positioning -> (Right Win key together with 9)
Each Dopus5 theme are stored in a separate directory, named appropriately, which contains further sub directories
* Font (amiga bitmap fonts)
* Screens (jpg or any picture supported by datatypes but not animations)
* Sounds (wav but not iff 8svx )
* Icons (png newicons glowicons )
* Patterns (iff jpg png )
Just use wildcards in background filenames and you get a different picture every reboot
For example, configure in Environment -> Backgrounds -> Desktop something like this:
<pre>
Work:Pictures/Backgrounds/#?
...or
Work:Pictures/back#?.iff
...etc...
</pre>
[https://aminet.net/util/dopus arcdir and themes]
If you want to change the backdrop pic after a period of time, paste below into a text file called dopusrandbg.rexx and place in DOPus5:ARexx
<pre>
/* Changes DOpus background image forever
Start with:
Run >NIL: RX dopusrandbg.rexx
*/
if ~show("L", "rexxsupport.library") then do
if ~addlib("rexxsupport.library", 0, -30,0) then exit 10
end
/* Configure these two lines for your needs: */
minutes=1
picpath="Work:Pics/#?.iff"
address DOPUS.1
do forever
call delay 3000*minutes
dopus set background '"'picpath'"' desktop center custom
dopus refresh background custom
end
</pre>
If you don't want to use/open rexxsupport.library just for DELAY() then use the DOS Wait command
<pre>
/* random diropus backdrop changer */
/* by paul trauth, 1999 */
/* to do: non-repeatable randomness? */
options results
parse arg path
address DOPUS.1
/* get current backdrop pattern so it actually changes */
dopus query background desktop custom
currentpatt=result
lastslash=lastpos('/',currentpatt)
currentpatt=substr(currentpatt,lastslash+1,(pos('"',currentpatt,2)-lastslash-1))
dir=showdir(path,'FILE','/')
num=0
do while dir~=''
where=pos('/',dir)
if where>0 then do
file=left(dir,where-1)
dir=right(dir,length(dir)-where)
end
else do
file=dir
dir=''
end
if left(file,1) ~='.' & file~=currentpatt then
do
pics.num=file
num=num+1
end
end
which=random(0,num-1,time(s))
newbg='"'||path||'/'||pics.which||'"'
dopus set background newbg desktop tile precision exact
dopus set background on
dopus refresh background
</pre>
Clock format commands available are defined by locale. They are:
<pre>
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
</pre>
like %a %d-%b-%y %H:%M or
A WB ARexx interface, you could enter a cli command as a menu item to open a WB drawer like this...
RX "address WORKBENCH;WINDOW 'device:drawer' OPEN"
Where device:drawer is replaced by the path of the drawer to open.
The ARexx script would be capable to manage such a task but this would work only with those program that support ARexx
<pre>
dopus addappicon
dopus addtrap
dopus back
dopus checkdesktop
dopus clear
dopus command
dopus desktoppopup
dopus error
dopus front
dopus getdesktop
dopus getfiletype
dopus getstring
dopus matchdesktop
dopus progress
dopus query background, font, palette, pens
dopus read
dopus refresh all, background, icons, lister
dopus remappicon
dopus remtrap
dopus request
dopus script
dopus screen
dopus send
dopus set background, font, palette, pens
dopus setappicon
dopus version
</pre>
<pre>
lister add
lister addstem
lister copy
lister clear value
lister clearcaches
lister close
lister empty
lister findcache
lister getstring
lister iconify
lister new
lister query active all, dest source
lister query abort, busy, case, dirs, display, entries, entry, files, flags, handler, header, hide
lister query label, lock, mode, namelength, numdirs, numentries, numfiles, numseldirs, numselfiles
lister query path, proc, position, seldirs, selentries, selfiles, separate, show, sort,
lister query title, toolbar, value, visible, window
lister read
lister refresh
lister reload
lister remove
lister request
lister set busy, case, dest, display, field, flags, handler, header, hide, label, lock, mode
lister set namelength, newprogress, off, path, position, progress, separate, show, sort, source
lister set title, toolbar, value, variable
lister select
lister wait
</pre>
The '''command''' allows you to call internal DOpus commands from an ARexx script
<pre>
command all
command wait copy
command read s:startup-sequence
command source 12345 makedir name noicon
</pre>
*SFTP secure encrypted comms over internet using libssh2 and zlib (different protocol to the two below) on port 22
*FTPS secured with https like security on port 21
*FTP not secure and unencrypted protocol over internet on port 21 (should not be used today on the internet but for your own server)
===Wanderer ===
Wanderer prefs in the prefs drawer - Appearance tab and Workbench icon allows backgrounds (wallpapers) icon text sizes, colors, etc but cannot use #? or *.* in the backgrounds file entry to randomly choose pictures - [https://developers.google.com/speed/webp/docs/riff_container webp riff container] issues with this format but Multiview has none.
Enable the bar, you need to edit the text file ‘statusbar.prefs’. The change is simple: just change “False” to ‘True’.
Prefs/Env-Archive/SYS/Wanderer/statusbar.prefs
===Scalos===
[https://web.archive.org/web/20180922220139/http://scalos.noname.fr/ Scalos] is not an OS replacement, it's a Workbench replacement. It replaces the desktop and graphical file management components.
Scalos is 100% Workbench replacement with most functions working like the original Workbench ones. Undo and Redo available for most window and icon operations. Fully multitasking so every window has its own task. While loading icons, any window function (e.g. Drag&Drop) is available.
24bit color support with window patterns - Unlimited and easily configurable via tooltypes. Optimised backgroundpatterns routine so patterns can be tiled, centred or even scaled to fit into the windows. Live updating window scrolling - Supports middle mouse button panning and drawer (folder) windows can be iconified on the desktop.
Icon imagetypes with all types are supported such as backfill or complement. Configurable surrounding iconborder. Icon support also visually highlights files which are soft-links in the file system. Icon dragging is more stable and far less flickery on graphics cards. Whilst dragging, icons are displayed with text and they can become transparent over anything where they can be dropped.
Single-window lasso mode, with scrolling window contents invoked by dragging mouse with configurable qualifier key. Text icon lasso selection used to ignore "Name column selects text icons" flag. Support for backfilled thumbnail icons, with selectable color and transparency. Added option to always generate square thumbnail icons with preview icons for images - Thumbnails can be permanently saved in icons.
Supports PNG icons with alpha channel and real transparency and displays OS3.5 GlowIcons and are all scalable. Iconborders with variations (normal, shadowed, outlined).
Completely configurable, filetype-specific user-definable popup menus and tooltips. Plugin system to exchange or add features and can enhance the Workbench and make it more configurable.
Filetype plugins to display filetype-specific information. - Currently, EXIF information viewer for JPEG images is included. Plugin included for 100% support of OS3.9 Workbench features. Plugin included for AREXX API compatible to OS3.9 Workbench.
Online update with updater.module
Scalos works also as a Workbench replacement. In this case the 'emulation mode' has to be set by using Scalos' own version of LoadWB and offers
* Scalos uses the Workbench Screen for its windows instead opening a new one
* AppIcon, AppMenuItem, AppWindow functions are redirected to Scalos
* all Programs placed in "WBStartup" should start
* The Screen will be reopened in case of changes in ScreenMode and Palette settings
<pre>
v1.0 (V39.201) - November 1999
v1.1 (V39.212) - December 1999
v1.2b (39.220) - June 6, 2000
v1.2d (39.222) - 2000 (latest public beta executable)
v1.3 (40.7) (beta) - August 2, 2001
v1.3 (40.22) - September 25, 2002
v1.4 (40.32) (beta) March 31, 2005
v1.6 (41.4) - March 27, 2007
v1.7 (41.5) - August 12, 2007
v1.8 (41.6) - March 12, 2009
v1.9 (41.7) (beta) - March 15, 2010
v1.9 (41.8) (RC1) - August 25, 2012 open source
v1.9.2 (41.10) Deadwoods' AROS late 2022 32bit and 64bit build unifying the code base of ` for AROS x86 ABIv0, AROS x86_64 ABIv11 and AROS m68k
</pre>
Distros may have Scalos files under SYS:System/Scalos or Extras:Scalos. Known [https://github.com/deadwood2/AROS/issues/75 bug list],
Certain files like Menu13.prefs, Palette13.prefs, Pattern.prefs and scalos.prefs need to be in SYS:Prefs/Env-Archive/Scalos they can be found in Scalos:Storage/envarc and country drawer
or run the "Scalos Menu" preferences program. Note if already setup with sub-menu entries and then re-save your menu prefs as it will now generate a new/overwrite prefs file called "Menu13.prefs" in "envarc:scalos/". The same is also required for the new Palette prefs update, click 'Save' and a "Palette13.prefs" file will be saved in to "envarc:scalos/" directory.
<pre>
ASSIGN Scalos: SYS:xxx/xxx DEFER
ASSIGN Libs: Scalos:Libs add
;ASSIGN SYS:Devs/Datatypes Scalos:Devs/Datatypes add
Assign Theme: Scalos:Themes/Default_Theme add
Assign Locale: Scalos:Locale add
Protect Scalos:Tools/browse.script s add quiet
Protect Scalos:Tools/OpenShell s add quiet
Protect Scalos:Tools/run.script s add quiet
run Scalos:Tools/LoadWB
;Scalos:Scalos
</pre>
Add the above to SYS:S/startup-sequence or SYS:S/user-startup '''before any Wanderer entries'''
In the prefs drawer (folder) is the big prefs app Scalos_Prefs which covers these user setup areas
<pre>
About Scalos
Paths - should be preset
Startup - WBStartup drawer contents should auto run on each startup
Desktop - edit titlebar, icon layout and in misc, auto leave-out (drag icon to desktop)
Icons -
Drag and Drop -
Windows -
Text Windows - in misc, drawer sorting at start of listing if needed
TrueType Fonts - use Truetype fonts rather than system ones
Miscellaneous -
Plugins - after adding oop/title_clock.plugin %ti %da does not work, maybe needs ASCII .prefs added
Modules - ??
Menu - setup for MainMenu and PopupsMenu with New Menu, RE Name, Key: shortcut, Command Properties
FileTypes - already added def_Project icons and def_Disk (hdd sdd cd dvd etc) support
PopupMenu - tweak how popups appear
Pattern - Wallpaper backgrounds with Type DE, each pattern in the list can be edited, Save as Pattern.pre
Palette - change the color of things , Save as Palette.pre
</pre>
Scalos_Prefs - Pattern - Minimum options to be changed are
*DE Desktop/Background
*SC Screen
*TW Window/TextBackground ie Text listing showing if icon type not recognised
*IW Window/Background ie Icons showing
Workflow - In "Pattern List" tab, select New - choose a picture, highlight in list, click in number box under New button and slide to another number, click on "Defaults" tab and adjust Pattern numbers slider to choose right picture for each of the above options - Click "Pattern List" tab to check eveything is OK and click Save
Pattern List tab on Patterns Page - Allows you to compile a list of pictures (one at a time rather than a whole folder e.g. with #? or *.*), assigning a number Nr to one or more of them for easy reference. Using this number you will be able to assign the pictures to specific windows on the Defaults tab Page. If multiple pictures have the same number, one of the pictures will be chosen randomly. This will allow you to have random desktop pictures, random window backdrops etc.
Defaults tab on Patterns Page - Here you can set the defaults for the background pictures for the Desktop, Screen, Window and/or Text Mode throughout Scalos.
Randomize every time [check box] - Usually Pictures with the same number will be randomly selected as soon as the configuration loads. If this option is set, the picture will be selected as soon as a window with the same number assignment is opened.
*Fit size: The picture will be resized to the dimension of the new window.You *MUST* have set GUIGfx on. asyncron layout: Pictures will be loaded and rendered while the windows opens (Like original Workbench). If this function is 'off', pictures will always be loaded before opening the windows.
*Use friendbitmap : The picture is present twice in memory for best speed. This option has no effect if V43 picture.datatype or GUIGfx are used. Always relayout: If "Fit size" is set, the picture will be scaled everytime the window's dimensions change.
*Randomize everytime: Usually Pictures with the same number will be randomly selected as soon as the If more pictures have the same number, one of them will be chosen randomly.
Patternlist New/Delete : Add a new picture. After that you should assign a number to it. The picture will be rendered as tiles. configuration loads. If this option is set, the picture
Asyncron-Task priority: You can set the CPU priority for the Task if "asyncron layout" is set.
<pre>
Desktop: Number of the Picture for the main window.
Screen: Number of the picture for the Scalos-Screen.
Window: Number of the picture for the Scalos-windows.
TextMode: Number of the picture for the Scalos-windows in Text Mode.
</pre>
Popup Menu preferences fully configurable menus (includes ToolsDaemon and ParM launch apps import), including support for context-sensitive Popup menus configs for top pull down menus for apps, etc.
Workflow - Scalos_Prefs then Menu, New Item, New Command add name at top then in Command Properties e.g. add Workbench and location e.g. DOpus:DOpus4 for apps Command for c apps or Rexx for scripts or Plugin for or AmigaDos for modules
<pre>
DESCRIPTION NAME/A This is the title that is displayed in the top line of any popup menu
INCLUDE NAME/A Name of file to be included. Path can be relative to "Scalos:FileTypes"
POPUPMENU Starts the popup menu description section for this filetype.
</pre>
The following Subcommands are allowed inside popup menus:
<pre>
SUBMENU "NAME/A"
ENDSUBMENU
MENUENTRY "NAME/A,KEY/K,DEFAULTACTION/S"
ENDMENUENTRY
INTERNALCMD "NAME/A"
WBCMD "NAME/A,STACK/K/N,WBARGS/S,PRI=PRIORITY/K/N"
AREXXCMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
CLICMD "NAME/A,STACK/K/N,WBARGS/S,P=PRIORITY/K/N"
ICONWINDOWCMD "NAME/A"
PLUGINCMD
MENUSEPARATOR
ENDPOPUPMENU
TOOLTIP
ENDTOOLTIP
</pre>
<pre>
Starts the tooltip description section for this filetype. The following Subcommands are allowed inside popup menus:
GROUP "ORIENTATION/K"
ENDGROUP
MEMBER "HIDE/K"
ENDMEMBER
HBAR
STRING "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K"
SPACE "SIZE/N/A"
DTIMAGE "FILENAME/A"
</pre>
Each theme drawer (folder) has these further folders
<pre>
About -
Desktop -
FileTrans -
FileType -
Icons -
Menu -
Modules -
PointerIcons -
Prefs -
Sound -
Window -
</pre>
*Plugins
<pre>
devicefilter.plugin
persist.plugin should a crash or reboot occur - next time Scalos started, all windows re-opened
title_clock.plugin add digital clock to title see more below
title_envvar.plugin %ev, which can be used to display the value (a string) of the variable in the titlebar
title_freepens.plugin
volumegauge.plugin
wb39.plugin
wbrexx.plugin plugin adds a Workbench 3.5+ compatible AREXX interface to Scalos internals
xtwindows.plugin left or right ALT or left or right SHIFT keys when open/close windows
filetype.plugin then run FileTypes-prefs and customize the filetypes (eg import from a DefIcons-brainfile)
menu.plugin
</pre>
*Modules - delete, empty_trashcan, execute, find, format_disk, information, iconproperties, newdrawer, reboot, rename, systeminfo, windowproperties
*Tools - scripts like LoadWB, quit.rexx, open_volume.rexx,
In Scalos_Prefs->Filetype->Recognition you can define the filetypes and on "Action" you define specific context menu for all filetypes defined in recognition (similar to magellan)
there is the same you must show all first (list is only limited) so you created a file type AAABBB, you need to have def_AAABBB icon
Associating files with "Scalos_FileTypes" is very simple, practically it is very similar to Dopus4, first you create the Def_icons to assign to the file type (will be seen automatically ), then run "Scalos_FileTypes" you add the extension, fill in the descriptor (MATCH or PATTERN etc..) and save
then you create an appropriate entry in the list and rename it, if def icon exists it is shown. Below you can define how files are identified. Use "pattern", similar to magellan to identify file by ending. Then you click on the shown icon and define in it what program is used when you double-klick on it and save it. On the tab action you can define popup menu for it.
defined all archive types from XAD in "filetypes". If you change to "action" and click on "archive" you can define the context menu that is shown if you do not define a specific context menu for a filetype
Reset to Default in Scalos_Prefs resets all settings so '''BEWARE'''
<pre>
The Scalos desktop screen titlebar may be configured using the main Scalos Preference program. This oop/time_clock plugin adds some additional placeholders:
%ti, displays the current time in the default Locale format. e.g. "10:43:37"
%da, displays the date in the default Locale format. e.g. "Saturday 14 July 2001"
Using the supplied prefs program for the plugin, or editing the ASCII file ENVARC:Scalos/title_clock.prefs you can use the following standard Amiga Locale values to change the formatting
%a - abbreviated weekday name
%A - weekday name
%b - abbreviated month name
%B - month name
%c - same as "%a %b %d %H:%M:%S %Y"
%C - same as "%a %b %e %T %Z %Y"
%d - day number with leading 0s
%D - same as "%m/%d/%y"
%e - day number with leading spaces
%h - abbreviated month name
%H - hour using 24-hour style with leading 0s
%I - hour using 12-hour style with leading 0s
%j - julian date
%m - month number with leading 0s
%M - the number of minutes with leading 0s
%n - insert a linefeed
%p - AM or PM strings
%q - hour using 24-hour style
%Q - hour using 12-hour style
%r - same as "%I:%M:%S %p"
%R - same as "%H:%M"
%S - number of seconds with leadings 0s
%t - insert a tab character
%T - same as "%H:%M:%S"
%U - week number, taking Sunday as first day of week
%w - weekday number
%W - week number, taking Monday as first day of week
%x - same as "%m/%d/%y"
%X - same as "%H:%M:%S"
%y - year using two digits with leading 0s
%Y - year using four digits with leading 0s
like %d %m %y or %a %d %B %Y %p
</pre>
Shutdown -> right mouse button Scalos, About, Reboot, Shutdown
ToolTypes can be added to the Scalos.info icon like
*SCALOS_PATTERNNO=<number> : background image matching the number
*SCALOS_NOTEXT : The Icon will be drawn without Text.
*SCALOS_NODRAG : The Icon will not be draggable. Its position will be fixed.
*Module iconproperties - Added SCALOS_BROWSERMODE tooltype support
runcommand parameters... in which case:
<pre>
%p = parameters
%w = directory path
%d = device-name
%% = literal percentage token
</pre>
With the help of the wbrexx.plugin Scalos gains support for more of the compatible arexx API
If an arexx command produces an error you will find the error code placed in the WORKBENCH.LASTERROR variable.
ACTIVATEWINDOW
<pre>
/* Activate the root window */
ADDRESS workbench
ACTIVATEWINDOW root
/* Activate the "Work:" partition's window if already open*/
ACTIVATEWINDOW "Work:"
</pre>
CHANGEWINDOW
<pre>
/* Change the root window; move it to position 10,30. * and change its size to 200100 pixels */
ADDRESS workbench
CHANGEWINDOW root LEFTEDGE 10 TOPEDGE 30 WIDTH 200 HEIGHT 100
/* Change the currently active window */
CHANGEWINDOW active 20 40 200 100
</pre>
Most of Scalos' issue are due to the flexibility of its' user configuring nature but if
The sort menu plugin needs to be ported from ASM to C.
IIRC Scalos has a command line option to fully replace Workbench/Wanderer.
The Theme: assign is used by both Wanderer and Scalos but I didn't have any problems using both at the same time.
The Program will be started from the Shell.
If "WB Args" is set, with the Argument "%p" will be replaced by the path of the activated Icons. The Program will started with the specified Stack value.
IconWindow: Scalos opens the window of the specified path.
PlugIn: Starts a Scalos Menu-PlugIn.
If a Menu Item with empty name is specified, Scalos displays a separator line.
It's possible to Drag&Drop an Icon in the Configuration Window. All values will be set accordingly. Entries may be dragged across the list.
Mac-like selection : This function activates a multiselection method used on MacOS or Win95. Don't have to hold down shift to drag them. Clicking on an already activated icon will
not deselect all other icons.
MMB move: The window contents may be moved using the middle mouse button.
WindowPopup title only: PopupMenu for windows can be opened only on window's title bars.
FullBench: Screen-Titles removed and Main Window set Full Size.
Scalos Prefs. Go to Settings->Scalos->Prefs and then the Misc section. Remove the tick against Full Bench. If you've enabled it, the titlebar will disappear when you select backdrop.
Default Icons saveable : The icons which Scalos generates if "show all files" is enabled, can now be saved
using "snapshot" menu option. load DefDisk first : Try to read the icons first from the DefIcons Path before using disk info.
Hide hidden files : If this function is activated all files or directories where the "hide" flag is set will not be shown.
Many of my Icons display more than once on the screen, while on the workbench all seems ok.
The Workbench filters double displayed icons, Scalos does not. Solution: please edit the ".backdrop" file and clear double lines.
Background images not scaled. GUIGfx option not set or guigfx.library and/or render.library not installed.
If working with CD's causes crashs or Scalos doesn't work correctly.
Most Filesystems doesn't support the ExAll function correctly. Disable "Use ExAll" in Scalos prefs.
Scalos doesn't start any program in the WBStartup. WBStartup Path may be set wrongly or Scalos was not started in Emulation Mode (LoadWB etc)
Some programs will not startup with error message "has not returned, wait some more"? and "unable to open your tool"
need a def_icon with the same name predefined, then create an appropriate entry in the list and rename it, if def icon exists it is shown. Below this can define how files are identified.
* either "pattern", similar to magellan to identify file by ending
* or
Then click on the shown icon and define in it what program is used when you double-click on it and save it. On the tab action you can define popup menu for it. All in all handling is of course different to magellan but can do similar
For the RAM Icon, to obtain this you have only to copy the icon in the Icon Path as "RAM.info" or "Ram Disk.info". All functions will automatically be performed
sometimes cut into half or quarters when scrolled off screen or drawers moved - settings issue probably
Sometimes leaves initial drawer window imprint on desktop when moved - settings issue
Scalos AROS released a [https://github.com/deadwood2/contrib/tree/master/scalos new build V2022-07-21] with the following changes noted:
<pre>
Fixed:
Numerous crashes when working on 64-bit with 64-bit heap
Wrong background color of Scalos logo on Scalos splash window
Backgroung image of Scalos splash window and Scalos About window is not visible
Icon labels on desktop and in drawer windows are displayed using Topaz instead of Arial font
Font.prefs are not being loaded on 64-bit
Font.prefs are being wrongly saved on 64-bit
scalos.prefs are not being loaded on x86 and x86_64, scalos is using always default preference
scalos.prefs are being saved on x86 and x86_64 in format not compatible with m68k
NewPopupmenu.prefs is wrongly written
Plugins are not loading at Scalos startup
wbrexx.plugin is crashing at startup on 64-bit
Multiple controls missing on Scalos Prefs/Icons page
System crash when clicking on def icon image on FileTypes Prefs/Recognition page
Status bar, control bar, buttons sometimes don't have images displayed
Buttons in Scalos About window have white corners rendered where they should be transparent
Crash when leaving out an icon
Crash when adding a User-defined Button to Control bar without setting it's properties in Scalos Prefs
Crash when removing any button from Control bar in Scalos Prefs
Scalos Prefs allows editing TTEngine font properties when TTEngine is not present causing crash in Icons/Labels and Text Windows/Fonts pages
deficons.prefs are not being loaded on x86 and x86_64
Reset to default in FileType Prefs and Save does not save preferences
Won't fix:
Scrollbars visible on titles of TrueType Fonts, PopupMenu, Menu, FileTypes, Pallette and Pattern pages of Scalos Preferences
Not fixed:
Wrong rendering on DualPNG icons
Refreshing drawer windows is slow
Starting Prefs/Locale or Prefs/Input from Scalos causes other preferences to fail
Desktop wallpaper is damaged where Splay window was displayed
When started from Wanderer, after saving Scalos Prefs, reload does not re-open main Scalos window
Difference in behavior between Cleanup from popup menu and Cleanup from top menu - possibly due to missing plugin, check Cleanup association in Menu Prefs
</pre>
===DOpus 4 Directory Opus===
Copy DOpus4 app to WBStartup directory folder so it starts on boot up each time
Another method is add the below to the bottom of the user-startup script in SYS:S drawer/directory
<pre>
run DOPUS:DirectoryOpus -i >NIL
</pre>
makes DOpus starts up in Iconified state at the top of Wanderer's screen. Left click on this to highlight and right mouse click to open.
Just click on the sides of either outer edges of DOpus windows and it will display the parent device/volume list.
DOpus4 saves it features in a PROGDIR:s/DirectoryOpus.CFG file which can be edited to suit anyones' needs, '''C''' bottom right button in DOpus4 and by reading the [https://arosarchives.os4depot.net/index.php?function=browse&cat=utility/filetool Dopus4 guide Manual and Arexx calls].
*[https://www.youtube.com/watch?v=DCyXDs8baSE Pt1 Introduction]
*[https://www.youtube.com/watch?v=7fiVmopiK9I Pt2 Dopus Config]
*[]
*[]
*Button little rectangle with name inside
*Bank vertical stack of buttons
Buttons
*Workbench app {f} i.e. first use {F} for all selected items with app
*AmigaDos c type apps with arguments after
*Arexx
*Command c type apps with no arguments after
Flags (most used)
*CD Destination to extract etc
*Do all files
*Output window
*Run asynchronously
*Workbench to front
*Buffer above 100000 for 64bit
Filetypes
Defines how certain files are handled like '''default tool'''
Screen
Fonts, set each element to any font
Screenmode, Workbench Use (same screen like Windows), Workbench clone (like Linux workspaces)
System
Shell startup, set to SYS:s/shell-startup
===BoingIconBar===
User chooses the apps to add to the dock at the centre bottom of the screen but has to be done manually, please use Save afterwards
Or easier edit the text file of SYS:Prefs/Env-Archive/iconbar.prefs and save
<pre>
BOING_PREFS
;Tools
SYS:System/Shell
SYS:Tools/DOpus4/DOpus4
SYS:Utilities/Editor
SYS:System/SysMon
SYS:System/Scout
Work:Extras/Internet/OWB/OWB
Work:Extras/Graphics/Lunapaint
Work:Extras/Graphics/ZunePaint
AROS:Tools/MPlayer/MPlayer
Extras:Internet/AmiFox/AmiFox
RAM Disk:Amelinium/Amelinium
</pre>
right mouse click on bottom edge of screen where boingiconbar shows - select settings which opens BoingIconBar Preferences to add apps
If no dock showing Add, to add apps click Add Program and search for the executable
another method is to drag icons to ends of the bar and move them on the Bar using the Prefs/BoingIconBar
===AmiStart===
On 32bit PCs only - auto generates the apps menu but scans the drive each time - AmiStart can choose apps you are not interested
* how to disable annoying zune/mui 'bubbles'?
try a right-click on AmiStart and release on Global settings. Then click on the bubbles gadget. Move the Show Bubbles slider all the way to the left.
===Fonts===
Install the #?.ttf files to SYS:Fonts/TrueType. Use SYS:System/FTManager to "Install Font" each #?.ttf file which will generate associated #?.otag and #?.font in SYS:Fonts. Use SYS:Prefs/Fonts to change system fonts and SYS:Prefs/Zune to change others.
To achieve our goal we will use the Setup Locale, Input, Zune and Fonts, as well as The FTManager.
Begin
The first step you should do is to get the system to know that we speak and write in another language. What you need to do is to open the setup program and choose Locale country, and list "preferred languages" to put it first and then English. If you want the tab "Time Zone" and select city of residence to set the clock correctly. Of course we save our changes and continue opening the setup program Input. This sets the keyboard language as our beginning. When the language layout was created there was no option to switch to Aros keyboard (layout switching), so to write in the language you had to hold down Alt, something you encounter in other functions. This time working with the team of Aros to create a new keyboard layout to replace the old so we can get rid of the button Alt. For now though let only selected this layout and do not turn the switch on the keyboard.
Custom Keyboard Layout
[http://repo.or.cz/w/AROS.git/tree/HEAD:/workbench/devs/keymaps keymaps are in place but unfortunately when they are not, then indeed things become a bit 'low-level' as it involves redefining some tables with values that match your keyboards]
only need to add your compiled table as new keymap.
So taking a little peek here shows that it should be possible to compile using
gcc -opc105_tr pc_105.c -nostdlib
where the pc105_gr/pc_105.c needs to be replaced with your own adjusted keymapname/c-file
[https://en.wikiversity.org/wiki/Enabling_Greek_Characters_on_Your_Keyboard General overview of Greek letters on keyboards]
Installing fonts
*[http://aminet.net/package/util/wb/EPAGrWb System jaggy]
*Outline resizable .font .otag
In this step you need to download some fonts that can support the encoding in our system. The easiest way is to run the script "Download Fonts" you'll find in the folder OWB. This script downloads from the Internet, and unpacks some fonts for OWB web browser, which is placed under the folder Fonts:TrueType. But as these can only be used by OWB and not the system, which unfortunately does not see. To make them available to the rest of the system, open the program FTManager, you will find the folder AROS: System /. From there select the field "Codepage" option "ISO-8859-7" and list the font "Arial" and "Regular" form in which you must double-click with the mouse. In the window that appears, select the bottom right the checkbox "Anti-aliasing" button and then "Install". Immediately folder Fonts: created files "arialregular.font" and "arialregular.otag", which are necessary in order to see the system font. Do the same steps if you wish for other fonts.
Final stages
After completing the above, open the folder AROS: Prefs / and run the program settings Fonts. In the new window, select the fields "Icons" and "Screen" as the font "ArialRegular" to the size you want. In the field "System" to give "s_courier", which, however, because it is not True Type Font support Antialising, and may seem a little broken. You can also use the CourierNew, if you have installed the above procedure. After you save the changes and open the Zune program settings. In this set the "ArialRegular" font fields in tabs "Windows" and "Groups", and save the changes. Reboot the system. To make sure that the above worked properly run NoWinED, which you will find under the folder AROS: Tools /. If that everything is working correctly you will see the menu and the settings window with Greek letters. You can also write in the language using the button Alt. Second program that you can try, which is fully localized, is WookieChat, which you will find in the folder AROS: Extras / Networking. And in this place all the menu and settings window works.
===Windows===
*Intuition
The window you position and resize, you right click on that windows title bar and in the dropdown menu you snapshot from there. Right click to show menu -> Window -> Snapshot Windows or All but it will NOT work if that folder has no icon (e.g. Disk.nfo) attached to it. You need a folder icon. The window information gets saved in it.
As for maximising the window using a shortcut key - Alt and up arrow key
The AROS-Shell windows can be moved, resized by editing sys:s/startup-sequence
<pre>
; run shell
run QUIET c:newshell >NIL:
</pre>
; slimmer right aros the screen
run QUIET c:newshell con:0/150//300/ >NIL:
; top right corner scr-x scr-y win-x win-y
run QUIET c:newshell con:600/150//300/ >NIL:
*EdgeSnap
Commodity EdgeSnap allows resize and position windows on your screen by dragging them to the edges but not corners of the screen and/or other windows
EdgeSnap Prefs (once pressed Use button) lets you arrange windows but not different applications in layouts half (left or right) or full size (top) and choose to adjust the border padding
There is outline to show shape taken to aid placement and space available
*Zune - AROS version of MUI
Magic Menu type functionality is implemented in IControl preferences editor: in the frame called Menus, switch type from Pull-Down to Pop-Up and/or iControl just tick the sticky menu option.
Windows outside screens causing a problem either uncheck "Offscreen move" for windows in IControl prefs editor. Or use FKey commodity and define two key shortcuts:
* the first using the command "cycle windows" (for example ALT TAB);
* the second using the command "rescue window" (for example ALT F5).
Now you can cycle windows until the one you want to rescue, and then "rescue" it: it will move back inside your screen.
How to save the window size on wanderer (snapshot all, snapshot windows)
Same for icon position on wanderer, can't save the position. Icon position cannot be saved yet, but you should be able to save the window position and size. sys:prefs - wanderer icon has option to save window size on exit but just for dh0. To get saving working on (DH1: Extras:) partitions try deleting the dh1 disk.info file, then reboot. The system should create a new dh1 icon.
* how to set up permanently 'view all files'?
As for viewing all files, removing disk.info for that disk did the job
* how to list and kill processes (xkill would be useful) ?
sys:Extras/System/Scout can kill apps
sys:Tools/Commodities/Exchange can remove available commodities
* how to restore 'go up' button in wanderer window? (it doesn't show up anymore).
If you're using Icaros, go to the theme prefs and make sure that decoration is checked. Also, some themes do not use a parent button, so try another theme. You may have to restart Aros before the theme will change.
* Is it really safe to turn off (hardware button) computer at any time (worried about USB hard disk)
yes you can turn off the computer IF none of the drives are in progress (i.e. writing). Best to use Wanderer menu option Quit otherwise
===Say narrator===
Say "Hello World" for a simple robotic voice
SPEAK: is a write-only DOS device for text-to-speech abbreviated as tts.
To check if available, type assign into the shell and at the bottom in the Devices: section should be SPEAK
Examples of use
<pre>
Copy S:Startup-Sequence SPEAK:
Echo "Hello" >SPEAK:M/R/S150/P110
Echo "DH1 EH0 L OW1" >SPEAK:A1
</pre>
Classic options are M/F, R/N, S<rate>, P<pitch>, O0/O1, A0/A1, and D0/D1. O1 recognizes lines beginning with OPT/ as option changes. A1 treats input as narrator phonemes.
Long options select a speech engine:
Echo "Hello" >SPEAK:ENGINE=narrator/VOICE=female/STYLE=natural/LANGUAGE=en-US
Supported selectors are ENGINE=, VOICE=, STYLE=, and LANGUAGE=. Values are case-sensitive backend identifiers. ENGINE=DEFAULT selects the system default. Narrator-compatible selectors continue through the classic translator/narrator pair. Other engines use speech.device. Direct phonemes require a narrator-compatible selection.
===Printing===
This needs further [http://www.aminet.net/package/docs/help/PrinterGuide drivers written], we have postscript and write to file support only
;There are no individual drivers yet for HP's Photosmart, EPSON's EPL, CANON's, Lexmark, CUPS PPD, etc.
*Postscript
Best to set Printer Prefs in the Prefs drawer to print-to-file or parallel/USB port
Save document in postscript or convert picture/text to postscript
Print using compatible Postscript printer
*printer is simply not accepting IPP connections at the moment.
Please try the following steps:
Open the printer web interface in a browser:
http://192.168.1.x/
Look for the network or protocol settings.
Enable IPP / Internet Printing Protocol.
Make sure TCP port 631 is open/enabled.
Save the settings and reboot the printer if the web interface asks for it.
ipp://192.168.1.xx:631/ipp/print
ipp://192.168.1.xxx:631/ipp/
===Files===
====File endings and datatypes====
* Check if the file has his own .info icon file with a tool set to open it. IIRC this has higher priority over the def_XYZ.info file association.
* In ENVARC:SYS/def_Text.info or whatever def_ file needs changing, use Wanderer's menu Icon -> Information and change the def_XYZ.info there. If you're on ABIv0 and want it to be applied immediately, you might have to copy it to ENV:SYS/ (or to reboot).
* Identifying file types by file ending is only a fallback. Far better it is to search for magic words, for flac files this would be "flaC" according to this [http://flac.sourceforge.net/documentation_format_overview.html documentation].
For instance, to open PDFs with arospdf not localised in the default drawer of Icaros (Work:Extras/Applications/arospdf) but localised in a custom drawer in AROS. The default tools are defined in the icons in sys:prefs/env-archive/sys e.g. def_PDF.
File type identification is done by datatype descriptors which you can find in Devs/Datatypes. The AROS build system has a tool which creates such datatype descriptors.
'''Changing of default tools of existing icons is easy as shown above. Adding of new file types is not hard, but needs knowledge of the AROS build system.'''
The enduser way would be to download the attached file, which contained two executables:
1) createdtdesc, to make a new datatype description
2) examinedtdesc, to read/show existing datatype descriptions
use 2 to get an idea on how it things are currently done in aros by providing this executable a file from the drawer sys:devs/datatypes/ (alternatively you can find the original .dtd files here).
use 1 to make your new datatype. Use the accompanied FORMAT file (also here) to read how to make your own datatype descriptor. use 2 to get hints from other datatype descriptors.
Note:
When creating a new descriptor would advise against using the pattern property, but instead use the default pattern of #? and create a Mask that matches your filetype. This requires some research in order to discover how your filetype can be recognized properly. Of course with making something like a descriptor for an ascii textfile, you would fallback to using the pattern (e.g. #?.text as the filetype cannot be determined easily otherwise).
<pre >
# name - choose wisely and informative. also used for icon's name.
# version - choose as you like as long as it complies with version rules
# basename - the 'root' datatype class. be aware that e.g. it can influence behaviour. for example when choosing binary and using tool multiview in project icon, the file will be viewed as binary file (choosing sound would tell mulitview to view the file as a soundfile). So this can influence the underlying tool being used. Could become messy if users started to modify the tool manually.
# pattern - This is the file pattern match e.g. #?.text
# Mask - A mask to identify the file. Requires knowledge of the actual file structure. For example 'M' 'Z' for an msdos executable.
# GroupdID - not supported (AROS native) files - use syst as that would be the least intrusive in case an AROS tool/program tries to load such datatyped file.
# ID - In your case, the first four characters of the name at subchapter 1 (in lower case) (or less if name is shorter).
# flags - How the mask needs to be interpreted. In your case would be mostly DTF_BINARY in combination with (wanted or not) DTF_CASE (to tell if mask used letters are case sensitive or not)
# priority - the priority of how the type is handled so that on datatype could have precedence over another? In any case, document tells it to be mostly 0.
</pre >
Now that you know each field and what it does (more or less), you write this fields in a text file for your own invented datatype, save it and create the actual dt with the tool in 1. in the end the created dt must reside in sys:devs/datatypes/ drawer.
Then you would create a default icon in sys:prefs/Env-archive/SYS drawer. Don't forget to reboot or copy .info file to ram:env/sys in order to test. also don't forget to set which tool to start f.e. c:lx or dh4:emulators/mycoolemulator
To test, open Wanderer then show all files and doubleclick on a file of type you just created. Alternatively you could use the 'open' command from shell (with file of datatype you just created as parameter).
And as a last note. it would perhaps be welcome to have a program like xicon and/or runprglist for AROS (unfortunately both without source, but something similar could be created for AROS).
Sounds complicated ?
Perhaps... but OS like windows needs a complete registry to be able to do things like this. And yes, i am aware windows has gui tools that does it (more or less) for you (by manipulating the registry). Same could be done for AROS (without integrating a registry in AROS that is ).
Would that suffice ?
red1+2: typos, reformatting.
disclaimer: please note that using these tools can screw up your currently installed support for datatypes when used incorrectly. Do not use if you do not understand what you are doing. Use at own risk.
==Network Connection==
AROS currently only has one real choice for TCP/IP networking - AROSTCP. This is a port of the AmiTCP package from AmigaOS (TM), with a number of enhancements/fixes from AROS developers.
===Wired===
Use Network Prefs to setup
=====IPv6=====
Some support
128bit IPv6 address packet
<pre>
Local FD::/8
Global 2000::/3
64:ff9b::/96
</pre>
NAT64 translates IPv6 to IPv4
DNS64
OS routing works with
<pre>
MacOS Ventura
Windows 11 with cloud account
Ubuntu Jammy Jellyfish
Android 10 (block google dns)
</pre>
====IPv4====
The top half of the IPv4 Configuration tab on the Network Prefs deals with the network card/USB and the lower half the router part.
[[File:AROS Wanderer Network Prefs DHCP.png|thumb|DHCP Settings]]
'''Upper part of IPv4 tab'''
* Click Add on the top right of the Prefs which opens a window called '''Interface'''
* Enter Name as net0 (but can be anything as long as it is consistently used in other sections)
* check mark on Active
* select device to be used using the '''right hand-side gadget''' of the box where the device name will go
* set Unit to 0
* IP Mode is default set to '''Get address from DHCP'''
* IP Mode set to Manual if DHCP does not work automatically
From the shell CLI, ifconfig -a
Under net0: section, inet starting 192.168.x.xxx
* inet or '''Address''' of network card
* netmask convert to decimal so 0x'''ffffff7f''' becomes 255.255.255.247 which is used to adjust the above '''Address''' into
* broadcast 192.168.xxx.xxx
click OK
[[File:AROS Wanderer Network Prefs Manual.png|thumb|Manual Settings]]
'''Lower part of IPv4 tab'''
* IP Mode Get address from DHCP (default)
* or changing to Manual if automatic DHCP set up does not work
* '''Gateway''' (Router Internal LAN-IP) (Default Route) = 192.168.0.1 (D-Link Netgear), 192.168.1.1 (Linksys 3com), 192.168.2.1 (SMC Microsoft), 192.168.1.254 (Belkin), 192.168.123.254 (USRobotics) else check with your router manual
* first DNS = use 208.67.222.222 (opendns) or Gateway number above (to test web browser access to router) or 212.50.160.100 (google) i.e. or whatever your ISP needs you to set
* second DNS = use 208.67.220.220 (opendns) or Gateway number above (to test web browser access to router) or 213.249.130.100 (google) i.e. or whatever your ISP needs you to set
* At the bottom of IPv4 tab, check mark the '''Start networking during system boot''' option
* Save and reboot (sometimes Network restart fails, so reboot every time to be sure)
'''an alternative way''' to AROS ifconfig -a, other OSs have similar for the same internet connection. Another connection will have different settings.
e.g. From [http://www.ncsu.edu/resnet/windows/ipconfig/ Windows], '''ipconfig /all'''
and note down the IP, subnet mask, default gateway, and DNS servers values and put these values in "manually" into AROS Network prefs.
e.g. From Linux via dhcp router have a look at etc./dhcpc/dhcpcd-eth0.info
* for manual input look at /etc/networks (IP or Gateway) and /etc/resolv.conf (DNS)
Please note that all in one routers (wired+wireless) or separate routers may need different settings
IPv4 involves routing (192,168.x.x), firewall, NAT
===Wireless===
You may have a Wifi Prefs to use for wireless setup
[[File:MyArosWirelessSetup.png|thumb|Setting up]]
[[File:MyArosWirelessTCP.png|thumb|Shell commands to work out what is happening]]
We must first make certain you have a Atheros 5k chip inside acting as the wireless wifi option. Open PCITool in Tools directory. Down left hand side are a series of numbers 0.00.0 etc. Click on some at the bottom and hopefully one of them will say Atheros AR5??? or AR242?.
or a Realtek RTL8187B, we can check using Prefs/Trident as this one is USB based
There are many similarities with the above Wired set up so please read the above section as well
* open Network/Prefs
* In '''IPv4 Configuration''' tab - click Add - enter net0 / active tick / #?.device / Unit 0 / IP Mode = manual (important if default DHCP does not work automatically)
Make sure that any extra network names (e.g. eth1 or net1) should be deleted. If net0 already st previously, change net0 so that it shows associated with the appropriate device name like atheros5000.device or realtek8180.device. Having two entries here will cause sub-net problems.
* Go to '''Wireless''' tab and click on "Add" button.
* Insert network name (SSID your wireless network name use wirelessmanager to get it), select right "encyption" that is most likely "WPA".
* Key Type set as "Passphrase". i.e. type in your password for your router (aka access key).
* Unselect (no tick) "hidden" if it is selected, then apply. You may have to tick it if wireless does not work.
* Finally, Save and '''reboot'''.
For the best chance of success, set networking to start at boot, and then reboot with the USB adapter plugged in.
===USB Ethernet===
Open SYS:Prefs/Network and in the IPv4 Configuration tag (top table covers your usb stick)
* click Add button
* set Name as net0
* Tick Active box
* enter the usb-ethernet.device e.g. dm9601eth.device, usbpegasus.device or usbasixeth.device use SYS:c/devlist, '''Scout''' or trident prefs to get the correct spelling
* set Unit to 0 (which is usual but check the messages from the bottom of the Trident prefs whilst plugging the device in to determine the unit number otherwise)
* IP Mode is set to Get address from DHCP (make sure your router is set right for that)
'''or manual'''
* IP Address of network card, i.e. 192.168.0.xx or 192.168.1.xx (xx being greater than 1)
* Subnet netmask = 255.255.255.0
* click OK
There can be sometimes be boot failures when using USB ethernet - plug the USB device in after boot and save the network prefs to make it work again.
Lower part of IPv4 tab covers the router information
* IP Mode Get address from DHCP
'''or if manual settings'''
* Gateway (IP Address of router) = usually 192.168.0.1 or 192.168.1.1 but see router manual to make sure.
* first DNS = use 8.8.8.8, 208.67.222.222 (opendns) or 212.50.160.100
* second DNS = use 8.8.4.4, 208.67.220.220 (opendns) or 213.249.130.100
===USB Tethering via Android smartphone===
Go to AROS Network Prefs (IPv4 configuration tab) and write type in "usbrndis.device" in the "device" textfield of "Interface" sub-window, which appears when you add a new device (or modify an existing one). Select "Start Network during system boot" and saved the configuration, the Connection is immediate no reboot is needed.<br>
usbrndis.device is a resident device (virtually always there) in fact, a driver is not present in DEVS:Networks <br><br>
Plug in USB cable, go to Android settings and enable "USB Tethering" <br>
A reboot should not be necessary.
When restarting AROS, the Smartphone deactivates the connection and to access the network again have to reactivate it before starting the browser.
===Solving Issues===
[[File:MyArosTCP.png|thumb|Aros network setup diagnostics - why does it not work?]]
* In Network Preferences, have '''only one''' item in the IPv4 Configuration tab
* If using manual settings, make sure all numbers are correct, especially for IP address of the card/usb (changing the last number in chain of four)
* For any USB based networking, it is often necessary to save in Prefs/Network, reboot AROS and network support can begin
* For wired, make sure that the LAN-cable is plugged in before starting the computer
* If wireless, try getting closer to the router.
* Switch off the encryption option from your router then try wifi, if successful then your ip/dns is ok. If not then your ip/dns settings are most probably wrong or need to use one or more opendns numbers
* Replace detachable wireless antenna (best wireless option to buy if you can) with a stronger antenna ie. 5 dBi or 7 dBi
* Try with another computer/laptop/machine
Program Error C:WirelessManager
* Test with another OS
* Check that Wifi works before changeover (if possible)
* Check that socket and card are working
* Check if card is too new for laptop (date code on card MMYY blue askey date 2005-2007 etc)
Are you connecting with the Router ?
Check with protection off e.g. wps and wep to see if it makes a difference.
For USB wireless - stopping and starting may be needed...
<pre>
; $VER: AROSTCP-startnet 1.0 (01/08/06)
; AROSTCP-startnet (c) The AROS Dev Team.
;
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
; stop and restart
execute "sys:system/network/AROSTCP/s/stopnet"
Run <NIL: >NIL: AROSTCP
WaitForPort AROSTCP
If NOT Warn
; echo "Stack online"
Else
echo "Wait for Stack Failed"
EndIf
run <NIL: >NIL: wirelessmanager realtek8180.device
</pre>
What IRQ number is assigned to the device? You can check with Tools/PCITool?
It's possible the BIOS hasn't set the right IRQ number. If you have a Linux CD/DVD handy, could you check if it boots with the options "acpi=off noapic nolapic"?
If the following does nothing, this will help us figure out why networking doesn't start automatically at boot
open a shell and run the following commands:
<pre>
echo ${AROSTCP/AutoRun}
echo ${AROSTCP/WirelessAutoRun}
echo ${AROSTCP/WirelessDevice}
</pre>
Please report the output, typically it will look like this
# True (explanation this variable is related to the "Start networking during system boot" checkbox in network prefs)
# True ()
# Devs:networks/atheros5000.device unit 0
If there's a problem with the AROSTCP package. What's the output of this?
ENV:sys/packages/AROSTCP
should return a string = Sys:System/Network/AROSTCP
By the way, a quicker way to check networking is working would be to run some shell commands such as:
<pre>
ping www.google.com
ifconfig net0
</pre>
The best way to list the available networks and diagnose / troubleshoot problems with connecting to a wireless network is to run WirelessManager manually. First uncheck the "Start networking during system boot" box in the Network prefs app, then save and reboot. Then run this in a shell:
C:wirelessmanager atheros5000.device verbose
or
C:wirelessmanager realtek8180.device verbose
and capture the output
If the above does not help, could you edit the file SYS:System/Network/AROSTCP/S/Package-Startup, and change ">NIL:" to ">T:wifi.log" on the WirelessManager line and add this as well Wait 5?
<pre>
if ${AROSTCP/WirelessAutoRun} eq "True"
Run QUIET "C:WirelessManager ${AROSTCP/WirelessDevice} >T:wifi.log"
wait 5
EndIf
</pre>
Then save, reboot and post the log file (T:wifi.log) here.
<pre>
c:wirelessmanager atheros5000.device verbose
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7)
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
Then it just sits there. Not sure what a normal dump looks like, I don't see anything that looks wrong in the configuration.
</pre>
looks like the driver isn't working with that card. Has anyone else successfully used that exact model number (AR2413)?
<pre>
Initializing interface 'atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=7):
65 63 68 65 6c 6f 6e echelon
PSK (ASCII passphrase) - hexdump_ascii(len=14): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='echelon'
*** [wpa_sm_init] sm->pmksa=02c66fd4 ***
Own MAC address: 00:01:36:15:ae:0c
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
Added interface atheros5000.device:0
State: DISCONNECTED -> SCANNING
Started AP scan for wildcard SSID
MLME: starting scan
MLME: scan channel 1 (2412 MHz)
sana2: sending MLME frame
Then it stops. Does this mean the router is not authorizing this NIC?
IRQ 4 (A)
</pre>
apparently locking up when the first frame is sent (a scan request).
<pre>
Devs/Networks/atheros5000.device:0
Initializing interface 'Devs/Networks/atheros5000.device:0' conf 'ENV:Wireless.prefs' driver 'default' ctrl_interface 'N/A' bridge 'N/A'
Configuration file 'ENV:Wireless.prefs' -> 'ENV:Wireless.prefs'
Reading configuration file 'ENV:Wireless.prefs'
Line: 1 - start of a new network block
ssid - hexdump_ascii(len=12):
41 69 72 4c 69 6e 6b 35 39 33 30 30 AirLink59300
PSK (ASCII passphrase) - hexdump_ascii(len=8): [REMOVED]
key_mgmt: 0x2
PSK (from passphrase) - hexdump(len=32): [REMOVED]
Priority group 0
id=0 ssid='AirLink59300'
*** [wpa_sm_init] sm->pmksa=0224e444 ***
Own MAC address: 00:1f:e1:42:e3:7a
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
[eloop_reg_timeout] Timeout is at 1317686594.160000
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: Supplicant port status: Unauthorized
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: Supplicant port status: Unauthorized
EAPOL: Supplicant port status: Unauthorized
[eloop_reg_timeout] Timeout is at 1317686595.060000
[eloop_reg_timeout] Timeout is at 1317686604.060000
Added interface Devs/Networks/atheros5000.device:0
[eloop_run] Starting
State: DISCONNECTED -> SCANNING
Starting AP scan for wildcard SSID
MLME: starting scan
[eloop_reg_timeout] Timeout is at 1317686594.160001
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.233000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.373000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.513000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.553000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.693000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686594.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686594.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.013000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.073000
EAPOL: disable timer tick
EAPOL: Supplicant port status: Unauthorized
MLME: scan channel 14 (2484 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.113000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.153000
MLME: scan channel 1 (2412 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.193000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.213000
MLME: scan channel 2 (2417 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.253000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.293000
MLME: scan channel 3 (2422 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.333000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.353000
MLME: scan channel 4 (2427 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.393000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.433000
MLME: scan channel 5 (2432 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.473000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.493000
MLME: scan channel 6 (2437 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.533000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.573000
MLME: scan channel 7 (2442 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.613000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.653000
MLME: scan channel 8 (2447 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.673000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.713000
MLME: scan channel 9 (2452 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.753000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.793000
MLME: scan channel 10 (2457 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.833000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.853000
MLME: scan channel 11 (2462 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.893000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.933000
MLME: scan channel 12 (2467 MHz)
[eloop_reg_timeout] Timeout is at 1317686595.973000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686595.993000
MLME: scan channel 13 (2472 MHz)
[eloop_reg_timeout] Timeout is at 1317686596.033000
sana2: sending MLME frame
[eloop_reg_timeout] Timeout is at 1317686596.073000
MLME: scan completed
</pre>
Is your network hidden? If so, did you enable the 'Hidden' checkbox in the network prefs? What distro version are you using?
<pre>
"ENV:sys/wireless.prefs" looks like this:
network={
ssid="testadhoc"
key_mgmt=NONE
wep_key0="12345"
wep_tx_keyidx=0
}
</pre>
If your router doesn't broadcast its SSID (hidden), you need to add this option to the network block of the wpa_supplicant.conf on your aros machine and make changes after # Example blocks:
scan_ssid=1
Here's a full description of all the [http://hostap.epitest.fi/gitweb/gitweb.cgi?p=hostap.git;a=blob_plain;f=wpa_supplicant/wpa_supplicant.conf config file options].
<pre>
ap_scan=1
network={
ssid="YOURESSID"
scan_ssid=1
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP
group=CCMP
psk=YOURPASSWORD
}
</pre>
<pre>
filter_ssids=1
ap_scan=2
network={
ssid="REMOVED"
scan_ssid=1
bssid=REMOVED
priority=100
mode=0
proto=RSN
key_mgmt=WPA-PSK
auth_alg=OPEN
pairwise=CCMP
group=CCMP
psk=REMOVED
}
</pre>
Error 6: Couldn't resolve host name.
Check Scout -> Devices and look at the device that you are using, in the OCnt column it should state 2 which means AROSTCP and Wirelessmanager are both accessing this driver. If 0 or 1, then uncheck the checkbox in Network prefs for starting networking at boot, save and reboot. Then run this is the shell:
C:WirelessManager realtek8180.device unit 0
some quirks setting up the wireless network as well
1) it's far better setting up either the wired OR the wireless network adapter as net0:, or weird things happen
2) it's better using fixed IP on the local network instead of DHCP
3) network setting must be placed in network setting panel in /prefs, using the wirelessmanager helped me finding available SSIDs, but not actually connecting to them
once done, reboot.
If previous setup is proving problematic
<pre >
SYS:Prefs/Env-Archive/Wireless.prefs
SYS:Prefs/Env-Archive/Zune/OWB.config
SYS:Prefs/Env-Archive/Zune/global.config
SYS:Prefs/Env-Archive/AROSTCP/WirelessDevice
SYS:Prefs/Env-Archive/AROSTCP/db/Interfaces
</pre >
Make a copy of these files and restore in case of problems.
Please try this test to check if you can connect to your router, ie established that the WiFi layer is working
̊̊̊̊Boot with networking disabled, by make sure that "Start networking at boot" in Network Prefs is unchecked (no tick).
̊ Run this in a shell: C:WirelessManager atheros5000.device VERBOSE
̊If the output of that command is too long to summarise here, you can redirect it to a file by adding >RAM:wifi.log to the end, then attach or paste that file here.
try running "status" in the shell and check that AROSTCP is listed/running
If AROStcp is not showing, then AROSTCP is not running. attempted to start it by clicking Use or Save in network prefs, or checking the "start networking at boot" box or typing into a shell.
Execute SYS:System/Network/AROSTCP/s/startnet
(run Status again afterwards).
The "cannot resolve hostname" will appear if you are blocked on the wifi network by the router as well as aros not being able to assign correct network address.
One way of testing this might be to disable the firewall in the router. you might also check the router how it sees the attempts aros do to speak to it. The easiest way to do that would be to manually give aros an IP number in the routers accepted range. and see if it shows up at all within the router.
Tests that can be undertaken to determine correct settings and functions
pciinfo
sanautil -d broadcom4400.device status
<pre >
ping <router-address> e.g. 192.168.0.1 (aka inet) or 80.237.146.33 (www.amiganews.de)
ifconfig net0
ifconfig net0 up
extras:networking/utils/sanautil/sanautil -d atheros5000.device status
WirelessManager atheros5000.device verbose >RAM:wifi.log
;to send the log to RAM disk to be read easier or if detected,
Run WirelessManager atheros5000.device >NIL:
Run WirelessManager atheros5000.device ssid="mynet1" >NIL:
C:WirelessManager realtek8180.device unit 0
</pre >
Please look at the task list in Scout, and check if WirelessManager and AROSTCP are running. Also look at the device list in Scout to check if realtek8180.device is open.
start tools/debug/sashimi, maybe it shows some debug messages when disconnection happens.
Firstly, let's take a look at what your setup most likely looks like, assuming you use a router. See diagram below:
<pre>
Internet <---------> home router <---------> computer
-----------external IP------------------internal IP-------------
</pre>
Okay, so what am I trying to show you with that diagram. A few things. Firstly, the IP address that connects you to the Internet is not the same one that connects you to your router. What happens is that your computer doesn't have a direct connection to the Internet, instead your router connects to the Internet, and your computer connects to the router.
You can see the external and internal IP addresses in these example settings...
* Default Gateway : 76.91.64.1 (external IP for ISP/Internet host)
* IP Address : 76.91.71.184 (external IP for home router)
* IP Address : 192.168.0.1 (internal IP for home router)
* Address = 192.168.0.161 (internal IP for computer)
As you can see, there are two internal IP addresses and two external IP addresses. This is because there is a client/server relationship, effectively one address is for the service (server) and one address is for the device trying to access that service (client).
The server addresses in your case are 76.91.64.1 (your ISP's address, serving the Internet), and 192.168.0.1 (your home router's address, serving your home network). The term gateway applies here, they are your gateway to those services.
Subnet masks are used along with IP addresses to determine which IP addresses are allowed access to a network. I did learn the more in-depth rules about subnet masks once (watched a CCNA vid), but I've forgotten about it. The basic level of understanding you'll need is easy to remember though. A subnet mask value of 255 means that portion of the IP address must stay constant, whereas a subnet value of 0 means any unassigned value up to 255 is allowed in the IP address.
By far the most common subnet value is 255.255.255.0. What this means is that the first three parts of the IP address you use to connect to a service must stay the same as the server/gateway address, and only the last section can change.
So if your router's internal IP address is 192.168.0.1, and the subnet mask is 255.255.255.0, the only addresses that will be allowed to be used on that network are between 192.168.0.2 and 192.168.0.255 (I think 192.168.0.0 is reserved for other uses).
Final point to make is about DHCP (a.k.a. dynamic IP) vs static IP. A server/router using DHCP gives a device that connects to it an address within the acceptable range. It usually starts with the lowest numbered free address, so with your router it'll give the first device that connects to it 192.168.0.2, the next device 192.168.0.3, and so on. Static IP addresses are where you set the IP address you want to connect with in advance.
When using static IP addresses on a router where DHCP is active, it's good to use a high number to avoid conflicts with other devices that are connected to your network, to reduce the risk that both devices will try using the same IP. That's why your current choice of 192.168.0.161 is good, unless you have over 159 devices connected on your current network!
Okay, so what's the next step. Well, if you can use ping, I'd suggest pinging 192.168.0.1. If you get a positive response it means you're connected to your router, if you don't get a response it means the connection between your router and your computer is at fault.
Documentation on configuring the AROSTCP environment further can be found [http://en.wikibooks.org/wiki/Aros/User/Networking here]
===File Sharing===
As AROS knows only a few filesystems (FFS, OFS, SFS, PFS (amiga only), FAT12, 16, 32, Microsoft NTFS (windows), UDF (Blu-ray)).
The others in regular use like MacOSX hfs+, Linux ext2/ext3 and ext4, Haiku BeFS provide a problem in transferring files.
Linux can access SFS partitions but it needs to be compiled. The latest full source are [http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/ here]. It compiled fine with a 2.6.30 kernel in Puppy Linux 4.31.
An alternative, is to use a FAT32 partition to share. Setup a 4G FAT32 partition using HDToolbox for sharing, and the rest of the space as SFS for an Aros install. It works very well.
Files could be transferred via TCP internet network.
====SMB2/3====
With Windows you can share one folder or all folders of the "Public" user.
On Windows what is important is to enable sharing (Network and Sharing Center).
AROS Mountlist should look lke this
<pre>
Handler = L:smb2-handler
StackSize = 65536
Priority = 5
GlobVec = -1
ACTIVATE=1
Startup = "smb://UserAcc:password@PCShare/Sharefolder"
</pre>
which could also be
"smb://UserPC:password@192.168.x.x/Public"
or
"smb://UserPC:password@Name-PC/Public"
so
"smb://UserPC:password@192.168.1.158/Folder"
or
"smb://UserPC:password@Name-PC/Folder"
After you have configured a share generates a DOSDrivers it is named "SMB0" which includes the setting, and at each reboot it is Mounted. You can still delete the DOSDriver by hand, is located in Storage/DOSDrivers, the file "ServerAutoMounts", in ENV:AROSTCP which indicates the DOSDriver to be mounted, should also be deleted.
The per-mount files are written to ENV:SMB or SYS:Storage/DOSDrivers. There is also additional file ENV:AROSTCP/ServerAutoMounts which states what will be presented to the end user.
====Old SMBFS====
e.g. to connect to a NAS share such as \\NASBOX\Shared use -:
SMBFS WORKGROUP=<YOUR WORKGROUP NAME> VOLUME=<AROS volume name to use>: SERVICE=<UNC Path to connect to>
SMBFS WORKGROUP=MYNET VOLUME=Shared: SERVICE=//NASBOX/Shared
And you will then have an icon appear on your desktop for the volume name you have chosen.
You can put the above script into wbstartup or
give it an icon, change it to a 'project' and give it the default tool c:iconx
Open a shell and type copy sys:script.info "sys:wbstartup/YOURSCRIPTNAME.info"
This should create an icon for your script file.
Now right-click on your script and select 'information'.
Change 'tool' to 'project', put 'c:iconx' into the 'default tool' box, click save
The reason being that scripts need to be opened with 'execute SCRIPTNAME' (or 'iconx') whereas the programs started from wbstartup are opened using 'run PROGRAMNAME'. It's the same as trying to start a command-line tool from the workbench by double-clicking it.
====Setup ISO images within AROS====
Use [http://archives.aros-exec.org/index.php?function=browse&cat=driver/storage DiskImage] which supports many cd image formats ISO, CCD, MDF/MDS, CUE/BIN, NRG and UIF. To mount CD or DVD images use below....
<pre >
# Rename your iso 'Unit0' (note no extension).
# Do 'View/All files' on you Aros partition. You should now see a folder called 'Diskimages'. Copy your renamed iso to there.
(Alternatively, you could type at the shell 'assign FDSK: xxx', where xxx is the location of your iso.)
# From the shell, type 'mount CD0:' and the iso should appear on the Wanderer desktop. You can now access it like a real disk.
</pre >
assign devname: dismount
Assign DOSVOLUME: remove
[http://aminet.net/package/disk/misc/unmount-0.1 unmount] most filesystems work but SFS lacks support for ACTION_DIE packet
If you are using an IcAros install, the startup scripts are set up to wipe the Diskimages directory on boot, so its worth keeping a second copy of the iso somewhere else. Alternatively, you could set up extra mountlists for additional iso images. I've made a file called iso1 in the Aros:devs directory that contains the following text:
<pre>
/* Entry for ISO image */
ISO1:
FileSystem = cdrom.handler
Device = fdsk.device
Unit = 1
LowCyl = 0
HighCyl = 0
Surfaces = 1
BlocksPerTrack = 1
DOSType = 0x41434400
Activate = 1
#
</pre>
Then I just need an iso called 'Unit1' (corresponding to the 'Unit = 1' entry in the mountlist) in Diskimages (or wherever I assign FDSK: to) and to mount I type in at the shell:
Mount iso1: from devs:iso1
Of course, if you create mountlists for ISO2, ISO3:, etc. (with the corresponding change to the 'Unit = ' line) you can have as many isos mounted as you wish. I just call mine ISO1: etc. to distinguish them from the real CD drives
==Video Guides==
Video demonstrations and tutorials covering:
:00. '''Introduction'''
::[https://www.youtube.com/@jamesmattson6813/videos Various Aros Installs],
::[https://www.youtube.com/embed/j8EmSEby0Rg AROS repo in gource, view of AROS dev commits from 1997 to 2025], [http://www.youtube.com/watch?v=Vx_zqlBow40&feature=related Gource view of AROS 1997 up to 2009],
::[http://www.youtube.com/watch?v=s1RsvEm7UrU Why an Amiga OS in 2011],
::[https://www.youtube.com/watch?v=1W886mheV74&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Johan Grip on early days of AROS x86], [https://www.youtube.com/watch?v=mXaKDhtTTqQ&t=14s&pp=ygUPYW1pZ2EgYXJvcyAyMDI2 Michel Schulz on Aros and PiStorm],
:01. '''Installation'''
::[https://www.youtube.com/watch?v=M7YjufrJqDs Aros One install], [https://www.youtube.com/watch?v=iIMguHTdC5E Aros One USB install], [https://www.youtube.com/watch?v=ZNXauy5m5Wc Aros One install], [http://vimeo.com/11013489 Modify Grub boot],
::[http://www.youtube.com/watch?v=wyQVeyXIywc&feature=channel iMica Silent Pt3], [http://www.youtube.com/watch?v=o2AnkoflY14 Wipe whole drive and Install - warning loss of data on drive],
::[http://www.youtube.com/watch?v=OVXm6_-witQ VirtualBox install], [ VMware install],
::[http://www.youtube.com/watch?v=0k2PEmT8I14 Broadway AROS Install],
::[https://www.youtube.com/watch?v=PtDiXhjSIfs Is Aros Icaros a choice?],
::[ driver install],
::[http://www.vimeo.com/10491104 HDAudio install but needs account], [],
:02. '''Amiga Basics'''
::[http://www.youtube.com/watch?v=TY8mWxwzH5o Screens tutorial],
::[https://m.youtube.com/user/AMIGASYSTEM/videos General], [ Dos Scripts tutorial], [http://www.youtube.com/watch?v=hPT7SmVEpjc OS 1.2], [http://www.youtube.com/watch?v=n6kX3FqH8Ww&feature=related OS 1.3],
:03. '''Customisation demos'''
::[https://www.youtube.com/@AMIGASYSTEM/videos Prefs tutorial], [ Decoration tutorial], [http://www.youtube.com/watch?v=Dn5C8G3aDXU Scalos],
:04. '''Setting up''' internet access and surfing the web, FTP, IRC and Mail apps
::[ Network Prefs], [ AirCOS tutorial], [ jabberwocky tutorial],
:05. '''Native bundled Games and Applications'''
::[http://www.youtube.com/watch?v=aYlFv2B-VXc 3D Games], [http://www.youtube.com/watch?v=MXK7wwhd-R0 Latest Games], [http://www.youtube.com/watch?v=RUgiVThv23Q&feature=mfu_in_order&list=UL PrBoom GL], [http://www.youtube.com/watch?v=0s7u8TPy7V4 Assault Cubes], [http://www.youtube.com/watch?v=fih6aCXKeqs Cube 2], [http://www.youtube.com/watch?v=-X0ay0MGOms DosBox on Aros], [http://www.youtube.com/watch?v=7nKduDjf14k Oct 2010],
::[http://www.youtube.com/watch?v=FziV2z_uxnQ Apps Pt 1], [http://www.youtube.com/watch?v=xs37_nfa5CI Apps Pt 2], [http://www.youtube.com/watch?v=Bn59_VvbQR0&feature=related Apps Pt 3],
::DOpus4 [http://www.youtube.com/watch?v=aSRybWjrrME DOpus 4],
::Milkytracker [http://www.youtube.com/watch?v=VxBOEPzpdKg&feature=related Laying Down Base Tracks],
::[http://www.youtube.com/watch?v=k2uKQ0-ieOE Audio Evolution 4 in action], [http://www.youtube.com/watch?v=Zq4r9k0_jZI Quick Videos],
::[http://www.youtube.com/watch?v=gGKCFZcIc0I&feature=related ScreenRecorder], [http://www.youtube.com/watch?v=974c2e-Fqak&feature=related TV out Tests],
::[http://www.youtube.com/watch?v=fjq8ct5d5IY AmiFIG], [http://www.youtube.com/watch?v=h0rHvPhYJo4&feature=youtu.be ZuneFIG],
::[http://wiki.povray.org/content/Documentation:Tutorial_Section_1 POVray Tutorial 1],
::[http://www.youtube.com/watch?v=Jk-ZNLfJsvQ pt 1, jan. 2008], [http://www.youtube.com/watch?v=nWRy33g1R7Y pt 2, feb. 2009], [http://www.youtube.com/watch?v=r5PbhCtm4vE pt 3, feb. 2010],
::[https://www.youtube.com/watch?v=G7_FJUoQ89o Hollywood programming], [], [], [],
::[], [], [],
::[], [], [],
::[], [], [],
:06. '''Commercial software available'''
::[http://www.youtube.com/watch?v=fKXY9B4R43s AntiryadGX 3D Game Editor],
::[http://www.youtube.com/watch?v=TMS9NDzwm5U BOH indie Game],
:07. '''Running classic amiga apps and games'''
:: Amiberry [], [],
::[http://vmwaros.blogspot.com/2008/11/introducing-amibridge.html Intro Amibridge], [http://www.youtube.com/watch?v=ee2PWvCZeLo Old Amiga Apps], [http://www.youtube.com/watch?v=ee2PWvCZeLo Why Janus UAE is good],
::[https://www.youtube.com/watch?v=VhlsNSYSuDg DPaint tutorial]
::[http://vmwaros.blogspot.com/2009/11/can-icaros-play-my-amiga-games-and-why.html Play Amiga Games], [https://www.youtube.com/watch?v=XTaZCNOvCnE],
::[http://www.youtube.com/watch?v=tMehS77LXQ4 Pagestream Introduction], [http://www.youtube.com/watch?v=284-w3hTzII Pagestream Tutorial 1], [http://www.youtube.com/watch?v=mlwEGwhZzl4 Pagestream Tutorial 2],
::[http://www.youtube.com/watch?v=iIcrIjPOctc Catweasel Mk4 PCI Part 1] and [http://www.youtube.com/watch?v=BaitHeL6bEA Part 2],
:08. '''Misc and History'''
::[http://www.youtube.com/watch?v=d6mDXKU29w0 Mum uses old AmigaOS Workbench 1.1 (1986)], [http://www.youtube.com/watch?v=DaRkacQ-YMg Why an Amiga 500 (1987)], [http://www.youtube.com/watch?v=k5CYsgVCzYY an Amiga 2000 (1987)],
:09. '''Misc Shows and Events'''
::[http://www.youtube.com/watch?v=klgVSWKs4kE VCF 2010], [https://www.youtube.com/watch?v=eQ3d5qR-Hv8 24:06 Jason McMullan at amiwest 2012 about AROS], [https://www.youtube.com/watch?v=jpQO7XSfAv4 Aros SMP multi core amiwest 2013], [], [https://www.youtube.com/watch?v=gFRtAAmiFbE], [https://www.youtube.com/watch?v=DjdUEyjx8GM], [https://www.youtube.com/watch?v=ydYDqZQpim8], [], [https://www.youtube.com/@uminekoshouten/featured], [https://www.youtube.com/shorts/NfoY023w-vE],
:10.
::[https://www.youtube.com/shorts/6qJTNW4-6GY]
===History===
The project was originally started by a small group of Amiga [http://www.amigahistory.co.uk/aros.html enthusiasts] in 1995. These individuals were mainly computer-based college university students at the start, though that student trend has diminished since. An interview with Aaron Digulla [http://arosshow.blogspot.com/2006/12/interview-with-aaron-digulla-who.html here]
* 1992 Commodore folds
* 1996-1998 much of the early years was concerned with exec, dos and intuition libraries.
* Early 1999, Haage & Partner used parts of the AROS code in AmigaOS 3.9.
* March 2001, floppy disk images of AROS became available.
* Early 2002, AROS changed its name from Amiga Replacement Operating System to Amiga Research Operating System
* June 2002, AROS devs decided to use Zune (MUI 3.8 rewrite) as the GUI system.
* November 2002, Eric Schwartz drew Kitty for AROS usage.
* Early 2003, AROS.org underwent a graphics facelift.
* Late 2003, GCC C compiler arrived.
* Early 2004, Aros-Exec opened.
* Early 2005, Aros Max bootable CD arrived.
* Late 2005, SFS filesystem ported and allowed fast access to apps and network support arrived
* Early 2007, AROS.org underwent another graphics facelift.
* Mid-2007, AROS changed to AROS Research Operating System after A.Inc. sued Hyperion with a trademark violation.
* Late 2007, the hard disk installer added and VmwAROS (later called Icaros Desktop) distro launched.
* Early 2009, Our first usable web browser (OWB)
* September 2010, first wireless support appears and AspireOS started as a distro
* Early 2012, the first paper-cut bugfix and Fab's Odyssey Web Browser ported
* Early 2017, work started on utilising the addition cores on modern CPUs starting with the 64bit x86 PC version
* Mid-2017, m68k port optimized for the Vampire 2 / Apollo accelerators (68080 AMMX FPGA)
* 2018 The old AROS Exec website closed and a new one opened
* 2019 AROS One x86 32bit distribution started and now with USB install version
* Early 2021, backport of more features of 32bit PC ABIv1 into 32bit PC ABIv0 (Aros One 1.5 and above)
* 2025 year of 64bit pc builds and porting 32bit applications to 64bit ABIv11
* 2026 update of [https://www.youtube.com/watch?v=6FKTL068ULM&pp=ygUPYXJvcyBhbWlnYSAyMDI2 nvidia nouveau driver for 64bit PC]
===Bounties===
To help inspire developers with both ideas and monetary incentives, rewards are offered for the successful completion of "bounties" (requests for missing/new functionality) chosen by the community and handled by [http://power2people.org power2people] (formerly done by TeamAROS). A monthly option is [http://www.power2people.org/funds/aros/ here].
Future goals for AROS include expanding its underlying retargetability to support even more diverse architectures, provide memory protection features and user level file security, SMP and many other wonderful features missing from AmigaOS — while still providing as much source level compatibility as is possible (however it is accepted that to achieve some goals code certain things may require a little recoding).
[http://www.ohloh.net/p/aros/contributors Developers] come and go as with any open source effort and we would like to thank them for their efforts...
;1996-2000:In DigullaA (coordinator), GripJ, TempletonI (BSD), SchulzM, RittauS, voordenDagL, HolmM, JohanssonT, VanIngelgomH, SteigerwaldM, BortasP, deJongK, AlfredssonJ, InnocentiB,
;2001-2005:In [http://chodorowski.com/adam/aros.html ChodorowskiA], StegerG, BergerS, HeutlingS, AlemagnaF (gcc), VerhaegenS (rexx), KielH, MatheussenKS (CAMD), SzczygielskiP, ErikssonP, LeCorfecD (Zune), BauerS (Zune), FurlongW, GustafssonJ, AndrewsN, CafferkeyN, GierichM (jpeg), PattonJ, ParsonsM, DietrichJ, SeilerT, BischoffL, LorentzenNH, AdamO, BerglundH, SmithP, HolmenD, BlomM,
;2006-2010:In FedinP, RusslerM, SzymczykS (owb), SmiechowiczK (openGL), WeissM, NorrisR, BrunnerO, WiszkowskiT, GreppinA, [http://www.fukt.bsnet.se/~bearsoft/ Bearsoft Björn Screwelius], ErbY, CharletF, HodgesC, [http://aros-exec.org/modules/newbb/viewtopic.php?topic_id=4819&forum=18&post_id=43103#forumpost43103 HokstadV], McMullanJ (m68k), WilenT (m68k),
;2011- :In MuijzenbergPHvanden, ALB42, JonesEM, weiju, DizzyofCRN, wawa, miker,
* 1996 - The linux hosted version for i386 was the first to arrive
* 1998 - i386, The native version for i386-based PC AT computers and compatibles.
* 2004 - x86/64, The native version for 64-bit (x86_64, amd64) PC computers.
* 2008 - sam440/ppc, The native version for Sam440EP, Sam440EP Flex and Sam460ex computers.
* 2009 - efika, The native version for PowerPC Efika computers.
* 2010 - m68k, The native version for m68k Amigas or WinUAE
* 2013 - raspi/armfh, early native version for ARMv6 based Raspberry Pi computers.
* 2017 - x86/64bit smp
Debugging capture serial debug at all (especially with sysdebug=all or --sysdebug=all) to see it displayed on screen
* yes, usb -> rs232 adapters can work most of the time, some of the cheapest ones are not fully compatible with all rs232 devices to capture to another device
* you will need a null modem cable (or a null modem adapter usually female to female) in addition to the usb -> rs232 adapter (usb adapter is a normal modem ie. the pins are not crossed over)
Normal modem cable - straight connection DCE
<pre>
Pin 2 -> Pin 2 RXD
Pin 3 -> Pin 3 TXD
Pin 5 -> Pin 5 GND
</pre>
Null modem cable connections DTE
<pre>
Pin 2 -> Pin 3
Pin 3 -> Pin 2
Pin 5 -> Pin 5
</pre>
(9pole SUB-D)
<pre>
serial ser: (amiga/aros) tty2 tty1USB0 (linux) COM1 (windows) (depends on the os being used)
speed baud transfer rate 9600 38400 lower baud might be more successful
data bits 8
stop bits 1
parity none
handshaking flow control - none xon/xoff (most likely) rts/cts dsr/dtr (pins not connected so should not work)
</pre>
*You cannot use compiled aros X86-64 bit software (when ready) on aros X86 32bit. PPC compiled software on X86 and so on.
*68k is tested with the UAE emulator (WinUAE) but some tests are done on native 68000 based Amigas and others.
*PPC support is very limited to certain devices.
If you use the WBStartup, you have to delete the other icons in the folder (readme etc..) and you have to add in the Icon Tooltype the parameter DONOTWAIT
If you use user-startup instead, you need to add the attached command "after assignment to LUA"
C:WBRun DH1:Extras/Utility/WeatherBar/WeatherBar >NIL:
Change the command to match your WeatherBar path.
<pre>
PATH sys:Utilities/WeatherBar ADD
run >nil: lua:amilua weatherforecast.lua
</pre>
To enter data your Country or City, ist with city_id numbers can be found [http://bulk.openweathermap.org/sample/city.list.json.gz here] or you need to go to [https://www.bbc.com/weather BBC Weather], once you type the name of your city or town in the appropriate tab, and press enter, the 7 numbers to be added in the "WeatherBar" will appear on the Browser url address bar above
Unicode v16.0 emojis are not supported but [https://github.com/jens-maus/libcodesets codesets.library] provides
<pre>
internally supported (hardcoded) charsets/codesets are: (conversions are possible from and to each codeset):
AmigaPL – Polish (Amiga)
Amiga-1251 – Cyrillic (Amiga)
ISO-8859-1 – Western European
ISO-8859-1+Euro – West European (with EURO)
ISO-8859-2 – Central/East European
ISO-8859-3 – South European
ISO-8859-4 – North European
ISO-8859-5 – Slavic languages
ISO-8859-9 – Turkish
ISO-8859-15 – West European II
ISO-8859-16 – South-Eastern European
KOI8-R – Russian
UTF-8 – Unicode
In addition, external charset table files can be stored in LIBS:Charsets or loaded by an application from PROGDIR:Charsets. The charset files included with this distributions are:
IBM866 – Cyrillic (cp866)
ISO-8859-7 – Greek (LatinGreek)
ISO-8859-10 – Nordic (Latin 6)
windows-1250 – Central/East Europe (Windows)
windows-1251 – Cyrillic (Windows)
windows-1252 – West European (Windows)
</pre>
Icaros 2.3 USB image needs a header stripped so it can work correctly
dd bs=512 skip=1 status=progress if=icaros_light_2-3-0_pendrive.bin of=/dev/sdxy && sync
Scalos
<pre>
-------------------------------
{ "STRING", "ID/K,TEXT/K,SRC/K,TEXTPEN/K,HALIGN/K,STYLE/K,FONT/K,VALIGN/K",
HALIGN LEFT | CENTER | RIGHT
VALIGN TOP | CENTER | BOTTOM
STYLE NORMAL | BOLD | ITALIC | BOLDITALIC
FONT // font specification - format: "fontname.font/size"
-------------------------------
arguments for STRING SRC
"diskstate",
"diskusage",
"diskusagefree",
"diskusageinuse",
"diskusagepercent",
"fibfilename",
"filecomment",
"filedate",
"fileprotection",
"filesize",
"filetime",
"filetypestring",
"iconname",
"linktarget",
"plugin" pluginname <optional plugin arguments>
"versionstring",
"volumecreateddate",
"volumecreatedtime",
"volumeordevicename",
-------------------------------
arguments for HIDE
"novolumenode",
"isempty" (some STRING)
-------------------------------
all internal commands:
"about",
"backdrop",
"cleanup",
"cleanupbyname",
"cleanupbydate",
"cleanupbysize",
"cleanupbytype",
"clearselection",
"clone",
"close",
"copy",
"cut",
"delete",
"emptytrashcan",
"executecommand",
"formatdisk",
"iconify",
"iconinfo",
"lastmsg",
"leaveout",
"makedir",
"open",
"parent",
"paste",
"putaway",
"quit",
"redraw",
"redrawall",
"rename",
"reset",
"selectall",
"showallfiles",
"showonlyicons",
"shutdown",
"sizetofit",
"snapshot",
"snapshotall",
"snapshotwindow",
"unsnapshot",
"update",
"updateall",
"viewbydate",
"viewbyicon",
"viewbysize",
"viewbytype",
"viewbytext",
</pre>
{{status|50%}}
{{BookCat}}
5d1qbu0clug9rkcb5zrxnhnm0f5zo7j
Talk:Radiation Oncology
1
14443
4675972
4646376
2026-10-14T05:57:23Z
Jcb
90773
4675972
wikitext
text/x-wiki
This book was born on: September 8, 2004.
==Instructions for Authors==
'''See [[Radiation Oncology/Standards | a list of standards]] for this wikibook.'''
==Template Usage==
*Template for Table of Contents '''<nowiki>{{Radiation Oncology:TOC}}</nowiki>'''
:Prior versions used <nowiki>{{:Radiation Oncology:TOC}}</nowiki>. The above version, which uses the Template namespace (Template/Radiation Oncology:TOC) is preferred.
*Add link to edit a template <nowiki>{{</nowiki>Radiation Oncology:Template Edit|''page name''|''text''}}
**where ''page name'' is the module name alone without the name space, such that http://en.wikibooks.org/wiki/Radiation_Oncology:Introduction would be ''Introduction''.
**where ''text'' is the text you want to appear after the word Edit in the box, such as "Edit this", or "Edit Table of Contents"
:—[[User:Brim|Brim]] 01:35, 19 Sep 2004 (UTC)
==Listing of templates==
To see a list of templates used in the Radiation Oncology wiki, use [http://en.wikibooks.org/w/index.php?title=Special%3APrefixindex&from=Radiation+Oncology&namespace=10 this link].
:''Note:'' older templates used the naming scheme Radiation Oncology/''subject'':TOC or Radiation Oncology/''subject''/TOC. Not all have been moved to the Template namespace.
A partial listing of older templates is below:
Note: all are preceded by a colon, e.g. <nowiki>{{:Radiation Oncology:TOC}}</nowiki>
*Radiation Oncology:TOC - general table of contents header
*Radiation Oncology:Colorectal_staging - common staging used for colon/rectum/small bowel
*Radiation Oncology/Head & Neck/Node staging
*Radiation Oncology/Head & Neck/Stage grouping
Sections with table of contents templates:
*Radiation Oncology/Prostate:TOC - table of contents header for prostate
*Radiation Oncology/Breast:TOC
*Radiation Oncology/NHL:TOC - Non-Hodgkin lymphoma
*Radiation Oncology/Hodgkin/TOC - Hodgkin's lymphoma
*Radiation Oncology/Lung/NSCLC:TOC - Non-small cell lung
*Radiation Oncology/Lung/SCLC:TOC - Small cell lung
*Radiation Oncology/Thyroid:TOC - Thyroid
It's suggested that you add the link '''<nowiki>{{:Radiation Oncology:Template Edit|Radiation Oncology/Prostate:TOC|the prostate table of contents bar}}</nowiki>''' to the top of a main page for a section (i.e. Prostate) that has subpages that use a table of contents template specific for that section. This will allow easy editing of the table of contents bar so it can be kept in sync with the section main page.
To make creating table of contents pages for subpages easier, you can copy fill-in-the-blank templates using the substitute command '''subst:'''.
*For the main page for a section, use '''<nowiki>{{subst::Radiation Oncology:TOC1}}</nowiki>'''
*For the table of contents bar for a section, use '''<nowiki>{{subst::Radiation Oncology:TOC2}}</nowiki>'''
:Example:
Let's say you wanted to create a section called "Earlobe tumors" which was large enough that you needed multiple subpages.
#Create the page "Radiation Oncology/Earlobe tumors".
#Type '''<nowiki>{{subst::Radiation Oncology:TOC1}}</nowiki>''' and save the page.
#Edit the page, replacing the ___INSERT TEXT HERE___ as appropriate, create the subsections that you would like, and save the page.
#Now edit the table of contents bar for this section (Radiation Oncology/Earlobe tumors:TOC), which you can do by following the link "edit the ___ table of contents bar."
#Type '''<nowiki>{{subst::Radiation Oncology:TOC2}}</nowiki>''' and save the page.
#Edit the page.
==Table example==
{|border=1
|+'''FLIPI'''
!colspan=2|Risk Factors: Five factors calculate FLIPI risk
|-
|1. Age > 60 years||'''low risk'''
|-
|2. Ann Arbor stage III-IV||0-1 factors
|-
|3. Hemoglobin < 12 g/dL||'''intermediate risk'''
|-
|4. Number of nodal areas > 5||2 factors
|-
|5. LDH > normal limits||'''high risk'''
|-
| ||3+ factors
|}
== Footnotes ==
Recommend the '''<nowiki><ref> </ref> and <references/></nowiki>''' method of generating footnotes and references. Please see guidelines at [http://en.wikipedia.org/wiki/Wikipedia:Footnotes Footnotes].
Example:
<br>in text:
<br><nowiki><ref>Insert reference here</ref></nowiki>
<br><nowiki><ref name="multiple">Insert reference here</ref></nowiki>
<br><nowiki><ref name="multiple/"> (to insert another instance of the same reference)</nowiki>
<br>insert a Notes or References section at the bottom of the page:
<br><nowiki><references /></nowiki>
You are also encouraged to use '''<nowiki>{{subst:Footnotes|100%}}</nowiki>''' which inserts the following text
<nowiki><!--See http://en.wikipedia.org/wiki/Wikipedia:Footnotes for an explanation of how
to generate footnotes using the <ref(erences/)> tags-->
<references/></blockquote></nowiki>
== Talk section ==
Brim,
Hope here.
Just wondering if you mind significant contributions... I already have a WikiWiki internally that has a large quantity of site-specific information, which I've been updating for ~1 year. It's not advertised and WikiBooks might be the way to go for a generalized resource. Any concerns about merging the two over time?
Also, what is the goal of this Wiki? Comprehensive text with everything (a la Perez) or more focused on specifics relating to evidence based treatment?
[[Hope]]
:Hi Hope. Welcome aboard and thank you for your contributions so far to the Radiation Oncology Wikibook.
Ideally and eventually this should be a comprehensive text, but the main [[radiation Oncology/Introduction|goal]] is ease of use. I'd rather the text be easy to read (bullet points) rather than have lengthy paragraphs, so in that regard it would be different from major print textbooks.
Really I see its main utility as being a repository of important radiation oncology articles, which would make it useful as a study guide for boards. I think it's important to give full citations for all articles mentioned. Now Wikipedia and Wikibooks both support links to PubMed by using the syntax '''<nowiki>{{PMID|12829145}}</nowiki>''' which produces the result {{PMID|12829145}}. I've been inconsistent with how I've been formatting articles, but you can look some of the chapters in the book to see in general how I've been formatting them. Once the book grows, there should probably be some policy on a recommended format.
In addition to listing the results of key articles, I would eventually like it to include treatment recommendations (i.e. how to treat advanced breast cancer) and radiation techniques (with pictures). I've also put Radiation Biology and Radiation Physics on the table of contents listing so that they may also be added at some time.
Since the project is still in its very early stages, how it develops exactly remains to be seen.
What I would definitely like to avoid is having it become like the oncology-related articles on [[w:Wikipedia|Wikipedia]] which are written very simply in layman's terms and read like general interest newspaper articles. The scope of this text should be for the cancer specialist.
I would really welcome any contributions you can make to this project. It would be great to try to merge your previous WikiWiki work over to here. Just be careful about copyright since Wikibooks requires that its articles be licensed under the GNU Free Documentation License. In the spirit of Wiki, [[w:be bold|be bold]] and if you see a way that this book needs to be changed, go for it, or ask me on my [[User_talk:Brim|talk page]].
Once again, welcome. By the way, do you also contribute on Wikipedia?
:—[[User:Brim|Brim]] 16:36, 18 Feb 2005 (UTC)
P.S. Say hello to Kat for me.
---
I'll let Cat know you said hello.
Basically, it sounds like this wikiwiki is similar in many ways to the wikiwiki I already have going. I will probably start shifting some of the content over as I can. I'll probably maintain both for a while, just to see how this one goes.
I haven't submitted much to Wikipedia, mostly because nothing has really struck my fancy there.
I'm on Pediatrics right now, so I'll probably start with that for the next few articles.
[[Hope]]
---
I just noticed you (Brim) wrote "Really I see its main utility as being a repository of important radiation oncology articles, which would make it useful as a study guide for boards." To what depth should these pages go? Would you want to keep it to just randomized evidence if available, or major studies? Or to whatever depth one has interest of entering information? As an example, I have done a project looking at predicting outcomes after radical prostatectomy, so I have somewhere all the studies that have developed predictive models. I could write it up as a subarticle. Or just add the 2-3 major prognostic models. [[User:Tdvorak|Tdvorak]] 17:00, 22 Jun 2005 (UTC)
*I think the general rule should be that good quality articles (i.e. randomized control trials) are preferred, but that any article that is valuable or of historical interest can or should be included. Often, there are major important articles that are retrospective studies. These may be followed then by data from randomized studies. If a non-randomized article is important for historical reasons or otherwise, it should be included. The main obstacle we should avoid is to have this wikibook get bogged down with too much information. The wiki shouldn't be a list of "all articles about prostate cancer." That would defeat its purpose of being an easy-to-use reference. I guess for now, with the wiki being in its relatively early stages, it would be better to err on the side of including articles that you think are important. Later, as the wiki grows, we may need to eliminate some redundant articles. Since we're not limited by space as we would be in a print textbook, we may elect to just move less-important artices to subpages of the main article (i.e. a page called "other prostate articles") while keeping the important articles in easy-to-find places. As for your idea about the predictive models after RP, there might be enough information for that all to go on its own page. You could list the 2-3 major prognostic models at the top so they're easier to spot. — [[User:Brim|Brim]] 02:57, 24 Jun 2005 (UTC)
Is it a coincidence that the rad onc page seems to be the most comprehensive of any of the medical specialties on Wiki?
:no, i think we have the most computer time during the work day
---
It seems that the [[Radiation_Oncology#Treatment_toxicity|Treatment Toxicity]] and the [[Radiation_Oncology#Supportive_Care|Supportive Care]] sections have a fair amount of overlap. I wonder what's the best way of handling it? I am thinking of combining them under each organ, and then having 3 sections - tolerance, acute toxicity & treatment, and long-term toxicity & treatment. --[[User:Tdvorak|Tdvorak]] 02:21, 7 August 2007 (UTC)
:I think the '''treatment toxicity''' section should be concerned with the risks of radiation complications and treatment planning aspects. For instance, data on esophagitis, data on lung V20, genitourinary toxicity, rectal tolerance, etc. It's more academic in scope, like the chapters on treatment. On the other hand '''Supportive Care''' is more of a field guide on how to deal with toxicities when they occur: a listing of helpful medicines and treatments, etc., that you can turn to as a handy reference. I think the sections function better separately since they're not commonly used together; but it would be helpful to have hyperlinks between related section. [[User:Brim|Brim]] 19:55, 10 August 2007 (UTC)
== ARRO list of key papers ==
Here's a useful link:
*[http://www.astro.org/arro/resources/key_papers/ Key articles in radiation oncology]
== Wikibooks Statistics ==
* [http://stats.wikimedia.org/wikibooks/EN/TablesWikipediaEN.htm Overall Wikibooks statistics]
* [http://stats.wikimedia.org/wikibooks/EN/Wikibooks_EN.htm Statistics per Wikibook]
== Recognition ==
''Publication References''
*'''EORTC; 2007''' {{PMID|18065746}} -- "Adjuvant radiotherapy after surgery for pathologically advanced prostate cancer." (Van der Kwast TH, J Clin Oncol. 2007 Dec 10;25(35):5671-2.)
**Reference #8: link to [[Radiation_Oncology/Prostate/Randomized]]
''Mentions of the Radiation Oncology wikibook in the media:''
*'''January 9, 2006''' - Newsweek article
{{cquote|In the Wikibooks project, anybody can help write school textbooks by, say, augmenting the chapter on Saint Sava in "Serbian History" or the brachytherapy section in "[[Radiation Oncology]]."|15px|15px|Benjamin Sutherland|"The People's Encyclopedia", ''[http://www.msnbc.msn.com/id/10682396/site/newsweek/ Newsweek: International Edition]'', January 9, 2006}}
''On Wikibooks:''
*'''June 23, 2006''' - Added to [[Template:Highlighted|Hot picks]] list
*'''May 9, 2008''' - [[Wikibooks:Featured_books|Featured Book]]
''On the web:''
*[http://www.medmatrix.org/_SPages/Radiation_Oncology.asp Media Matrix] website - 5 stars
== Redesigned front page ==
It looks great. I've been on holiday, so haven't been able to see it. I'm very glad the book became featured; it's fantastic :). Regards, —[[User:Celestianpower|Cel<span style="color: green;">es</span>tianpower]] <sup>[[user talk:Celestianpower|háblame]]</sup> 18:25, 11 May 2008 (UTC)
:Thank you! I am glad you suggested it. I have been thinking about reorganizing it for a while and this was a good impetus.
pk7f0xcklfve4khycrfgor98tpr3o2q
Cookbook:Mirin
102
25890
4675914
4536304
2026-10-13T22:34:02Z
ZFT
950842
/* Recipes */
4675914
wikitext
text/x-wiki
__notoc__
{{Ingredient summary
| Image = [[File:Mirinbowl.jpg|300px]]
}}
{{ingredient}} | [[Cookbook:Alcoholic Drink|Alcoholic Drink]]
'''Mirin''' is a sweet Japanese rice-based wine, commonly used in [[Cookbook:Cuisine of Japan|Japanese cooking]].<ref name=":1">{{Cite book |last=McGee |first=Harold |url=https://www.google.com/books/edition/On_Food_and_Cooking/bKVCtH4AjwgC?hl=en&gbpv=0 |title=On Food and Cooking: The Science and Lore of the Kitchen |date=2007-03-20 |publisher=Simon and Schuster |isbn=978-1-4165-5637-4 |language=en}}</ref><ref name=":2">{{Cite web |title=Mirin - A Cook's Guide to Japanese Sweet Cooking Wine |url=https://www.diversivore.com/the-pantry/mirin/ |access-date=2025-09-03 |website=diversivore |language=en-CA}}</ref><ref name=":0">{{Cite book |last=Labensky |first=Sarah R. |url=https://books.google.com/books?id=E3t-swEACAAJ&newbks=0&hl=en |title=On Cooking: A Textbook of Culinary Fundamentals |last2=Hause |first2=Alan M. |last3=Martel |first3=Priscilla |date=2018-01-18 |publisher=Pearson |isbn=978-0-13-444190-0 |language=en}}</ref><ref name=":4">{{Cite web |last=Chen |first=Namiko Hirasawa |date=2022-04-07 |title=Mirin (Japanese Sweet Rice Wine) |url=https://www.justonecookbook.com/mirin/ |access-date=2025-09-03 |website=Just One Cookbook |language=en-US}}</ref> It is not the same thing as [[Cookbook:Sake|sake]].<ref name=":2" />
== Characteristics ==
Mirin is produced by combining cooked glutinous rice, koji mold, and shochu (a liquor made from rice wine).<ref name=":1" /><ref name=":0" /><ref name=":7">{{Cite web |last=Omura |first=Yuto |date=2023-12-19 |title=Mirin 101: What It Is, What It Does, Substitutions and More |url=https://sudachirecipes.com/mirin/ |access-date=2025-09-03 |website=Sudachi |language=en-US}}</ref> The mold converts the rice starch to glucose and various aromatics, while the shochu prevents the production of excess alcohol, retaining the sweetness.<ref name=":1" /><ref name=":4" /><ref name=":7" /> Finally, it is filtered and clarified.<ref name=":1" />
The final product has an alcohol content of about 14% (lower than that of sake),<ref name=":2" /><ref name=":4" /><ref name=":5">{{Cite web |last=Black |first=Julia |date=2017-08-21 |title=What Is Mirin? And What to Use If You Can't Find Any |url=https://www.bonappetit.com/story/what-is-mirin-how-to-substitute |access-date=2025-09-03 |website=Bon Appétit |language=en-US}}</ref> as well as a high sugar content and sweetness.<ref name=":1" /><ref name=":0" /><ref name=":5" /><ref name=":6">{{Cite web |last=Everyone |date=2020-01-10 |title=Mirin - Asian Ingredients Glossary |url=https://thewoksoflife.com/mirin/ |access-date=2025-09-03 |website=The Woks of Life |language=en-US}}</ref> The flavor is described as rich and layered,<ref name=":7" /> and the color is light golden.<ref name=":2" />
=== Varieties ===
Products marketed as mirin are typically available in a few varieties. '''Hon mirin''' ("true mirin") is a higher grade made using the production process described above,<ref name=":4" /><ref name=":3">{{Cite web |title=How to Stock a Japanese Pantry: 13 Indispensable Ingredients |url=https://www.seriouseats.com/japanese-cooking-pantry-staples |access-date=2025-09-03 |website=Serious Eats |language=en}}</ref> meaning they are aged and have the full alcohol content and complex flavor.<ref name=":2" /> This style should generally contain only rice, the koji, shochu, and perhaps a small amount of salt, with no added sugar.<ref name=":2" /> '''Shio mirin''' ("salt mirin") is similar, but with added salt such that it is not drinkable as a beverage in itself.<ref name=":2" />
Because of various restrictions on alcoholic beverages, as well as the higher price tag of hon mirins, a number of mirin approximants are produced.<ref name=":4" /><ref name=":7" /><ref name=":6" /> '''Aji-mirin''' or '''mirin-style condiment/seasoning''' is made with alcohol (~8%), starch or glucose syrup, rice, and added salt.<ref name=":2" /><ref name=":4" /><ref name=":6" /><ref name=":3" /> '''Mirin-like condiments''', sometimes called '''kotteri mirin''', contain little to no alcohol, approximating the flavor of mirin with starch syrups and rice seasonings.<ref name=":2" /><ref name=":4" /> This variety has lower complexity of flavor and is very sweet.<ref name=":2" />
Note that the labeling can vary somewhat for all these products, so checking the ingredients is the best way to know what type of product you are getting.<ref name=":2" /><ref name=":7" />
== Selection and storage ==
Given the different varieties, the cook will need to decide which grade of mirin is suitable for their purpose. Lower grades, such as mirin-like condiments, may be adequate for some dishes, while other preparations may need higher-grade mirins.<ref name=":6" />
The best place to look for mirin is grocery stores catering to east Asian (and especially Japanese) cuisines,<ref name=":2" /><ref name=":4" /> though unsalted, alcoholic varieties may be harder to source, depending on the regulations in a given region.<ref name=":2" /> Check the ingredient list to help confirm which variety of mirin it is.<ref name=":2" />
Hon mirin, containing alcohol, can generally be stably stored in the dark at cool room temperature for several months; it may darken as it ages.<ref name=":2" /><ref name=":4" /><ref name=":6" /> You can store it in the fridge if desired,<ref name=":3" /> but the sugar may crystallize.<ref name=":4" /> No- or low-alcohol varieties should be stored in the refrigerator after opening or according to the manufacturer directions.<ref name=":4" />
== Use ==
Mirin's primary role in cooking is to complement the final dish using its alcohol, sweetness, and the complex flavor from fermentation.<ref name=":2" /><ref name=":4" /><ref name=":7" /> It also adds a characteristic glossiness.<ref name=":2" /><ref name=":4" /><ref name=":7" /> One very well-known application for mirin is teriyaki sauce,<ref name=":5" /> which is one of several sauces made with it.<ref name=":4" /><ref name=":5" /><ref name=":6" />
== Substitution ==
The general recommendation for achieving results with the best flavor is to buy the highest-quality mirin you can find and afford—aim for hon mirin when possible.<ref name=":7" /> If you can't get a higher grade, you can try a lower grade (e.g. aji mirin) or try one of several substitutions.<ref name=":2" /><ref name=":7" /><ref name=":3" /> If you can get a different rice wine like sake or Chinese Shaoxing, try dissolving sugar in the wine at a 3:1 volume ratio of wine to sugar in order to sweeten it.<ref name=":2" /><ref name=":4" /><ref name=":7" /><ref name=":6" /> You can also try a white wine, sherry, or marsala,<ref name=":7" /><ref name=":5" /><ref name=":6" /> but the flavors will be different due to the use of grapes.<ref name=":2" />
==Recipes==
<div style="column-count:3">
<categorytree mode="all" hideprefix="always" hideroot="on">Recipes using mirin</categorytree>
</div>
== References ==
rhmy53ffan3e6j73xcdo1jynbb3js1g
4675915
4675914
2026-10-13T22:34:31Z
ZFT
950842
/* Recipes */
4675915
wikitext
text/x-wiki
__notoc__
{{Ingredient summary
| Image = [[File:Mirinbowl.jpg|300px]]
}}
{{ingredient}} | [[Cookbook:Alcoholic Drink|Alcoholic Drink]]
'''Mirin''' is a sweet Japanese rice-based wine, commonly used in [[Cookbook:Cuisine of Japan|Japanese cooking]].<ref name=":1">{{Cite book |last=McGee |first=Harold |url=https://www.google.com/books/edition/On_Food_and_Cooking/bKVCtH4AjwgC?hl=en&gbpv=0 |title=On Food and Cooking: The Science and Lore of the Kitchen |date=2007-03-20 |publisher=Simon and Schuster |isbn=978-1-4165-5637-4 |language=en}}</ref><ref name=":2">{{Cite web |title=Mirin - A Cook's Guide to Japanese Sweet Cooking Wine |url=https://www.diversivore.com/the-pantry/mirin/ |access-date=2025-09-03 |website=diversivore |language=en-CA}}</ref><ref name=":0">{{Cite book |last=Labensky |first=Sarah R. |url=https://books.google.com/books?id=E3t-swEACAAJ&newbks=0&hl=en |title=On Cooking: A Textbook of Culinary Fundamentals |last2=Hause |first2=Alan M. |last3=Martel |first3=Priscilla |date=2018-01-18 |publisher=Pearson |isbn=978-0-13-444190-0 |language=en}}</ref><ref name=":4">{{Cite web |last=Chen |first=Namiko Hirasawa |date=2022-04-07 |title=Mirin (Japanese Sweet Rice Wine) |url=https://www.justonecookbook.com/mirin/ |access-date=2025-09-03 |website=Just One Cookbook |language=en-US}}</ref> It is not the same thing as [[Cookbook:Sake|sake]].<ref name=":2" />
== Characteristics ==
Mirin is produced by combining cooked glutinous rice, koji mold, and shochu (a liquor made from rice wine).<ref name=":1" /><ref name=":0" /><ref name=":7">{{Cite web |last=Omura |first=Yuto |date=2023-12-19 |title=Mirin 101: What It Is, What It Does, Substitutions and More |url=https://sudachirecipes.com/mirin/ |access-date=2025-09-03 |website=Sudachi |language=en-US}}</ref> The mold converts the rice starch to glucose and various aromatics, while the shochu prevents the production of excess alcohol, retaining the sweetness.<ref name=":1" /><ref name=":4" /><ref name=":7" /> Finally, it is filtered and clarified.<ref name=":1" />
The final product has an alcohol content of about 14% (lower than that of sake),<ref name=":2" /><ref name=":4" /><ref name=":5">{{Cite web |last=Black |first=Julia |date=2017-08-21 |title=What Is Mirin? And What to Use If You Can't Find Any |url=https://www.bonappetit.com/story/what-is-mirin-how-to-substitute |access-date=2025-09-03 |website=Bon Appétit |language=en-US}}</ref> as well as a high sugar content and sweetness.<ref name=":1" /><ref name=":0" /><ref name=":5" /><ref name=":6">{{Cite web |last=Everyone |date=2020-01-10 |title=Mirin - Asian Ingredients Glossary |url=https://thewoksoflife.com/mirin/ |access-date=2025-09-03 |website=The Woks of Life |language=en-US}}</ref> The flavor is described as rich and layered,<ref name=":7" /> and the color is light golden.<ref name=":2" />
=== Varieties ===
Products marketed as mirin are typically available in a few varieties. '''Hon mirin''' ("true mirin") is a higher grade made using the production process described above,<ref name=":4" /><ref name=":3">{{Cite web |title=How to Stock a Japanese Pantry: 13 Indispensable Ingredients |url=https://www.seriouseats.com/japanese-cooking-pantry-staples |access-date=2025-09-03 |website=Serious Eats |language=en}}</ref> meaning they are aged and have the full alcohol content and complex flavor.<ref name=":2" /> This style should generally contain only rice, the koji, shochu, and perhaps a small amount of salt, with no added sugar.<ref name=":2" /> '''Shio mirin''' ("salt mirin") is similar, but with added salt such that it is not drinkable as a beverage in itself.<ref name=":2" />
Because of various restrictions on alcoholic beverages, as well as the higher price tag of hon mirins, a number of mirin approximants are produced.<ref name=":4" /><ref name=":7" /><ref name=":6" /> '''Aji-mirin''' or '''mirin-style condiment/seasoning''' is made with alcohol (~8%), starch or glucose syrup, rice, and added salt.<ref name=":2" /><ref name=":4" /><ref name=":6" /><ref name=":3" /> '''Mirin-like condiments''', sometimes called '''kotteri mirin''', contain little to no alcohol, approximating the flavor of mirin with starch syrups and rice seasonings.<ref name=":2" /><ref name=":4" /> This variety has lower complexity of flavor and is very sweet.<ref name=":2" />
Note that the labeling can vary somewhat for all these products, so checking the ingredients is the best way to know what type of product you are getting.<ref name=":2" /><ref name=":7" />
== Selection and storage ==
Given the different varieties, the cook will need to decide which grade of mirin is suitable for their purpose. Lower grades, such as mirin-like condiments, may be adequate for some dishes, while other preparations may need higher-grade mirins.<ref name=":6" />
The best place to look for mirin is grocery stores catering to east Asian (and especially Japanese) cuisines,<ref name=":2" /><ref name=":4" /> though unsalted, alcoholic varieties may be harder to source, depending on the regulations in a given region.<ref name=":2" /> Check the ingredient list to help confirm which variety of mirin it is.<ref name=":2" />
Hon mirin, containing alcohol, can generally be stably stored in the dark at cool room temperature for several months; it may darken as it ages.<ref name=":2" /><ref name=":4" /><ref name=":6" /> You can store it in the fridge if desired,<ref name=":3" /> but the sugar may crystallize.<ref name=":4" /> No- or low-alcohol varieties should be stored in the refrigerator after opening or according to the manufacturer directions.<ref name=":4" />
== Use ==
Mirin's primary role in cooking is to complement the final dish using its alcohol, sweetness, and the complex flavor from fermentation.<ref name=":2" /><ref name=":4" /><ref name=":7" /> It also adds a characteristic glossiness.<ref name=":2" /><ref name=":4" /><ref name=":7" /> One very well-known application for mirin is teriyaki sauce,<ref name=":5" /> which is one of several sauces made with it.<ref name=":4" /><ref name=":5" /><ref name=":6" />
== Substitution ==
The general recommendation for achieving results with the best flavor is to buy the highest-quality mirin you can find and afford—aim for hon mirin when possible.<ref name=":7" /> If you can't get a higher grade, you can try a lower grade (e.g. aji mirin) or try one of several substitutions.<ref name=":2" /><ref name=":7" /><ref name=":3" /> If you can get a different rice wine like sake or Chinese Shaoxing, try dissolving sugar in the wine at a 3:1 volume ratio of wine to sugar in order to sweeten it.<ref name=":2" /><ref name=":4" /><ref name=":7" /><ref name=":6" /> You can also try a white wine, sherry, or marsala,<ref name=":7" /><ref name=":5" /><ref name=":6" /> but the flavors will be different due to the use of grapes.<ref name=":2" />
==Recipes==
<div style="column-count:2">
<categorytree mode="all" hideprefix="always" hideroot="on">Recipes using mirin</categorytree>
</div>
== References ==
nftbc1j86oz95gurkejw96t549dgb3x
Haskell/Lists II
0
26158
4675925
4627630
2026-10-13T23:02:17Z
Luciérnaga de conocimiento
3401314
4675925
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Elementary Haskell}}
Earlier, we learned that Haskell builds lists via the cons operator <code>(:)</code> and the empty list <code>[]</code>. We saw how we can work on lists bit by bit using a combination of recursion and pattern matching. In this chapter and the next, we will consider more in-depth techniques for list processing and discover some new notation. We will get our first taste of Haskell features like infinite lists, list comprehensions, and higher-order functions.
{{body note|Throughout this chapter, you will read and write functions which sum, subtract, and multiply elements of lists. For simplicity's sake, we will pretend that list elements are of type <code>Integer</code>. However, as you will recall from the discussions on [[../Type basics II|Type basics II]], there are many different types within the Num typeclass. As an exercise of sorts, you could figure out what the type signatures of such functions would be if we made them polymorphic, allowing for the list elements to have any type in the class <code>Num</code>. To check your signatures, just omit them temporarily, load the functions into GHCi, use :t and let type inference guide you.
}}
==Rebuilding lists==
Here's a function that doubles every element from a list of integers:
<syntaxhighlight lang="haskell">
doubleList :: [Integer] -> [Integer]
doubleList [] = []
doubleList (n:ns) = (2 * n) : doubleList ns
</syntaxhighlight>
Here, the base case is the empty list which evaluates to an empty list. In the recursive case, doubleList ''builds up a new list'' by using <code>(:)</code>. The first element of this new list is twice the head of the argument, and we obtain the rest of the result by recursively calling doubleList on the tail of the argument. When the tail gets to an empty list, the base case will be invoked and recursion will stop.<ref>Had we forgotten the base case, once the recursion got to an empty list the (x:xs) pattern match would fail, and we would get an error.</ref>
Let's study the evaluation of an example expression:
<syntaxhighlight lang="haskell">
doubleList [1,2,3,4]
</syntaxhighlight>
We can work it out longhand by substituting the argument into the function definition, just like schoolbook algebra:
<syntaxhighlight lang="haskell">
doubleList 1:[2,3,4] = (1*2) : doubleList (2 : [3,4])
= (1*2) : (2*2) : doubleList (3 : [4])
= (1*2) : (2*2) : (3*2) : doubleList (4 : [])
= (1*2) : (2*2) : (3*2) : (4*2) : doubleList []
= (1*2) : (2*2) : (3*2) : (4*2) : []
= 2 : 4 : 6 : 8 : []
= [2, 4, 6, 8]
</syntaxhighlight>
Thus, we rebuilt the original list replacing every element by its double.
In this longhand evaluation exercise, the ''moment'' at which we choose to evaluate the multiplications does not affect the result. We could just as well have evaluated the doublings immediately after each recursive call of doubleList.<ref>…as long as none of the calculations result in an error or nontermination, which are not problems in this case.</ref>
Haskell uses this flexibility on evaluation order in some important ways. As a ''pure'' functional programming language, the compiler makes most of the decisions about when to actually evaluate things. As a ''lazy'' language, Haskell usually defers evaluation until a final value is needed (which may sometimes never occur).<ref>The compiler may sometimes evaluate things sooner in order to improve efficiency.</ref> From the programmer's point of view, evaluation order rarely matters.<ref>One exception is the case of ''infinite lists'' (!) which we will consider in a short while.</ref>
=== Generalizing ===
To triple each element in a list, we could follow the same strategy as with <code>doubleList</code>:
<syntaxhighlight lang="haskell">
tripleList :: [Integer] -> [Integer]
tripleList [] = []
tripleList (n:ns) = (3 * n) : tripleList ns
</syntaxhighlight>
But we don't want to write a new list-multiplying function for every different multiplier (such as multiplying the elements of a list by 4, 8, 17 etc.). So, let's make a general function to allow multiplication by ''any'' number. Our new function will take two arguments: the multiplicand as well as a list of <code>Integer</code>s to multiply:
<syntaxhighlight lang="haskell">
multiplyList :: Integer -> [Integer] -> [Integer]
multiplyList _ [] = []
multiplyList m (n:ns) = (m * n) : multiplyList m ns
</syntaxhighlight>
This example deploys <code>_</code> as a "don't care" pattern. The multiplicand is not used for the base case, so we ignore that argument instead of giving it a name (like <code>m</code>, <code>n</code>, or <code>ns</code>).
We can test <code>multiplyList</code> to see that it works as expected:
{{Haskell/GHCi|1=
Prelude> multiplyList 17 [1,2,3,4]
[17,34,51,68]
}}
{{Exercises|1=
Write the following functions and test them out. Don't forget the type signatures.
# takeInt returns the first ''n'' items in a list. So, <code>takeInt 4 [11,21,31,41,51,61]</code> returns <code>[11,21,31,41]</code>.
# dropInt drops the first ''n'' items in a list and returns the rest. So, <code>dropInt 3 [11,21,31,41,51]</code> returns <code>[41,51]</code>.
# sumInt returns the sum of the items in a list.
# scanSum adds the items in a list and returns a list of the running totals. So, <code>scanSum [2,3,4,5]</code> returns <code>[2,5,9,14]</code>.
# diffs returns a list of the differences between adjacent items. So, <code>diffs [3,5,6,8]</code> returns <code>[2,1,2]</code>. (Hints: one solution involves writing an auxiliary function which takes two lists and calculates the difference between corresponding elements. Alternatively, you might explore the fact that lists with at least two elements can be matched to a <code>(x:y:ys)</code> pattern.)
The first three functions are in Prelude under the names <code>take</code>, <code>drop</code>, and <code>sum</code>.
}}
== Generalizing even further ==
In this chapter, we started with a function constrained to multiplying the elements by <code>2</code>. Then, we recognized that we could avoid hard-coding a new function for each multiplicand by making <code>multiplyList</code> to easily use any <code>Integer</code>. Now, what if we wanted a different operator such as addition or to compute the square of each element?
We can generalize still further using a key functionality of Haskell. However, because the solution can seem surprising, we will approach it in a somewhat roundabout way. Consider the type signature of <code>multiplyList</code>:
<syntaxhighlight lang="haskell">
multiplyList :: Integer -> [Integer] -> [Integer]
</syntaxhighlight>
The first thing to know is that the <code>-></code> arrow in type signatures is ''right associative''. That means we can read this signature as:
<syntaxhighlight lang="haskell">
multiplyList :: Integer -> ([Integer] -> [Integer])
</syntaxhighlight>
How should we understand that? It tells us that <code>multiplyList</code> is a function that takes ''one'' <code>Integer</code> argument and evaluates to ''another function''. The function thus returned, then, takes a list of <code>Integer</code>s and returns another list of <code>Integer</code>s.
Consider our old <code>doubleList</code> function redefined in terms of <code>multiplyList</code>:
<syntaxhighlight lang="haskell">
doubleList :: [Integer] -> [Integer]
doubleList xs = multiplyList 2 xs
</syntaxhighlight>
Writing this way, we can clearly cancel out the `xs`:
<syntaxhighlight lang="haskell">
doubleList = multiplyList 2
</syntaxhighlight>
This definition style (with no argument variables) is called ''point-free'' style. Our definition now says that applying only one argument to <code>multiplyList</code> doesn't fail to evaluate, rather it gives us a more specific function of type <code>[Integer] -> [Integer]</code> instead of finishing with a final <code>[Integer]</code> value.
We now see that functions in Haskell behave much like any other value. Functions can return other functions, and functions can stand alone as objects without mentioning their arguments. Functions seem almost like normal constants. Can we use functions themselves as ''arguments'' even? Yes, and that's the key to the next step in generalizing <code>multiplyList</code>. We need a function that takes any other appropriate function and applies the given function to the elements of a list:
<syntaxhighlight lang="haskell">
applyToIntegers :: (Integer -> Integer) -> [Integer] -> [Integer]
applyToIntegers _ [] = []
applyToIntegers f (n:ns) = (f n) : applyToIntegers f ns
</syntaxhighlight>
With <code>applyToIntegers</code>, we can take ''any'' <code>Integer -> Integer</code> function and apply it to the elements of a list of <code>Integer</code>s. We can thus use this generalized function to redefine <code>multiplyList</code>:
<syntaxhighlight lang="haskell">
multiplyList :: Integer -> [Integer] -> [Integer]
multiplyList m = applyToIntegers ((*) m)
</syntaxhighlight>
That uses the <code>(*)</code> function with a single initial argument to create a new function which is ready to take one more argument (which, in this use case, will come from the numbers in a given list).
=== Currying ===
If all this abstraction confuses you, consider a concrete example: When we multiply 5 * 7 in Haskell, the <code>(*)</code> function doesn't just take two arguments at once, it actually first takes the 5 and returns a new ''5*'' function; and that new function ''then'' takes a second argument and multiplies that by 5. So, for our example, we then give the 7 as an argument to the 5* function, and ''that'' returns us our final evaluated number (35).
So, '''all functions in Haskell really take only one argument'''. However, when we know how many intermediate functions we will generate to reach a final result, we can ''treat'' functions ''as if'' they take many arguments. The number of arguments we generally talk about functions taking is actually the number of one-argument functions we get between the first argument and a final, non-functional result value.
The process of creating intermediate functions when feeding arguments into a complex function is called ''currying'' (named after Haskell Curry, also the namesake of the Haskell programming language).
== The <code>map</code> function ==
While <code>applyToIntegers</code> has type <code>(Integer -> Integer) -> [Integer] -> [Integer]</code>, the definition itself contains nothing specific to integers. To use the same logic with other types of lists, we could define versions such as <code>applyToChars</code>, <code>applyToStrings</code> and so on. They would all have the same definition but different type signatures. We can avoid all that redundancy with the final step in generalizing: making a fully polymorphic version with signature <code>(a -> b) -> [a] -> [b]</code>. Prelude already has this function, and it is called <code>map</code>:
<syntaxhighlight lang="haskell">
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = (f x) : map f xs
</syntaxhighlight>
With <code>map</code>, we can effortlessly implement functions as different as...
<syntaxhighlight lang="haskell">
multiplyList :: Integer -> [Integer] -> [Integer]
multiplyList m = map ((*) m)
</syntaxhighlight>
... and...
<syntaxhighlight lang="haskell">
heads :: [[a]] -> [a]
heads = map head
</syntaxhighlight>
{{Haskell/GHCi|1=
Prelude> heads [[1,2,3,4],[4,3,2,1],[5,10,15]]
[1,4,5]
}}
<code>map</code> is the general solution for applying a function to each and every element of a list. Our original <code>doubleList</code> problem was simply a specific version of <code>map</code>. Functions like <code>map</code> which take other functions as arguments are called ''higher-order functions''. We will learn about more higher-order functions for list processing in the next chapter.
{{Exercises|1=
# Use <code>map</code> to build functions that, given a list xs of Ints, return:
#* A list that is the element-wise negation of xs.
#* A list of lists of Ints xss that, for each element of xs, contains the divisors of xs. You can use the following function to get the divisors: <pre>divisors p = [ f | f <- [1..p], p `mod` f == 0 ]</pre>
#* The element-wise negation of xss.
# Implement a Run Length Encoding (RLE) encoder and decoder.
#* The idea of RLE is simple; given some input:<pre>"aaaabbaaa"</pre> compress it by taking the length of each run of characters:<code>(4,'a'), (2, 'b'), (3, 'a')</code>
#* The <code>concat</code> and <code>group</code> functions might be helpful. In order to use <code>group</code>, import the Data.List module by typing <code>:m Data.List</code> at the ghci prompt or by adding <code>import Data.List</code> to your Haskell source code file.
#* What is the type of your <code>encode</code> and <code>decode</code> functions?
<!-- Commenting out the bonus exercises -- as things stand, read/show are probably a bit too much of a distraction at this point. -->
<!-- #* How would you convert the list of tuples (e.g. <code>[(4,'a'), (6,'b')]</code>) into a string (e.g. "4a6b")?
#* (bonus) Assuming numeric characters are forbidden in the original string, how would you parse that string back into a list of tuples? -->
}}
==Tips and Tricks==
A few miscellaneous notes about lists in Haskell:
===Dot Dot Notation===
Haskell has a convenient shorthand for writing ordered lists of regularly-spaced integers. Some examples to illustrate it:
<syntaxhighlight lang="haskell">
Code Result
---- ------
[1..10] [1,2,3,4,5,6,7,8,9,10]
[2,4..10] [2,4,6,8,10]
[5,4..1] [5,4,3,2,1]
[1,3..10] [1,3,5,7,9]
</syntaxhighlight>
The same notation works with characters and even with floating point numbers. Unfortunately, floating-point numbers are problematic due to rounding errors. Try this:
<syntaxhighlight lang="haskell">
[0,0.1 .. 1]
</syntaxhighlight>
{{body note|The <code>..</code> notation ''only'' works with sequences with fixed differences between consecutive elements. For instance, you cannot write...
<syntaxhighlight lang="haskell">
[0,1,1,2,3,5,8..100]
</syntaxhighlight>
... and expect to magically get back the rest of the Fibonacci series.<ref>http://en.wikipedia.org/wiki/Fibonacci_number</ref>
}}
===Infinite Lists===
Thanks to lazy evaluation, Haskell lists can be ''infinite''. For example, the following generates the infinite list of integers starting with 1:
<syntaxhighlight lang="haskell">
[1..]
</syntaxhighlight>
(If you try this in GHCi, remember you can stop an evaluation with Ctrl-c).
The same effect could be achieved with a recursive function:
<syntaxhighlight lang="haskell">
intsFrom n = n : intsFrom (n + 1) -- note there is no base case!
positiveInts = intsFrom 1
</syntaxhighlight>
Infinite lists are useful in practice because Haskell's lazy evaluation never actually evaluates more than it needs at any given moment. In most cases, we can treat an infinite list like an ordinary one. The program will only go into an infinite loop when evaluation requires all the values in the list. So, we can't sort or print an infinite list, but:
<syntaxhighlight lang="haskell">
evens = doubleList [1..]
</syntaxhighlight>
will define "evens" to be the infinite list [2,4,6,8..], and we can ''then'' pass "evens" into other functions that only need to evaluate part of the list for their ''final'' result. Haskell will know to only use the portion of the infinite list needed in the end.
Compared to hard-coding a long finite list, it's often more convenient to define an infinite list and then take the first few items. An infinite list can also be a handy alternative to the traditional endless loop at the top level of an interactive program.
===A note about <code>head</code> and <code>tail</code>===
Given the choice of using either the <code>( : )</code> pattern or <code>head</code>/<code>tail</code> to split lists, pattern matching is almost always preferable. It may be tempting to use <code>head</code> and <code>tail</code> due to simplicity and terseness, but it is too easy to forget that they fail on empty lists (and runtime crashes are never good). We do have a Prelude function, <code>null :: [a] -> Bool</code>, which returns <code>True</code> for empty lists and <code>False</code> otherwise, so that provides a sane way of checking for empty lists without pattern matching; but matching an empty list tends to be cleaner and clearer than the corresponding if-then-else expression using <code>null</code>.
{{Exercises|1=
#With respect to your solutions to the first set of exercises in this chapter, is there any difference between <code>scanSum (takeInt 10 [1..])</code> and <code>takeInt 10 (scanSum [1..])</code>?
#Write functions that, when applied to lists, give the ''last'' element of the list and the list with the last element dropped (without using <code>reverse</code>).<br/>This functionality is provided by Prelude through the <code>last</code> and <code>init</code> functions. Like <code>head</code> and <code>tail</code>, they blow up when given empty lists.
}}
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Elementary Haskell}}
{{BookCat}}
itqorctgtnmi3cl6vzzwv8m5x4wv52t
Haskell/Simple input and output
0
27116
4675904
4628105
2026-10-13T18:59:55Z
Luciérnaga de conocimiento
3401314
4675904
wikitext
text/x-wiki
{{clear}}
{{Haskell minitoc|chapter=Haskell Basics}}
== Back to the real world ==
Beyond internally calculating values, we want our programs to interact with the world. The most common beginners' program in any language simply displays a "hello world" greeting on the screen. Here's a Haskell version:
<syntaxhighlight lang="haskell">
Prelude> putStrLn "Hello, World!"
</syntaxhighlight>
<code>putStrLn</code> is one of the standard Prelude tools. As the "putStr" part of the name suggests, it takes a <code>String</code> as an argument and prints it to the screen. We could use <code>putStr</code> on its own, but we usually include the "Ln" part so to also print a line break. Thus, whatever else is printed next will appear on a new line.
So now you should be thinking, "what is the type of the putStrLn function?" It takes a <code>String</code> and gives… um… what? What do we call that? The program doesn't get something back that it can use in another function. Instead, the result involves having the computer change the screen. In other words, it does something in the world outside of the program. What type could that have? Let's see what GHCi tells us:
<syntaxhighlight lang="haskell">
Prelude> :t putStrLn
putStrLn :: String -> IO ()
</syntaxhighlight>
"IO" stands for "input and output". Wherever there is <code>IO</code> in a type, interaction with the world outside the program is involved. We'll call these <code>IO</code> values ''actions''. The other part of the <code>IO</code> type, in this case <code>()</code>, is the type of the return value of the action; that is, the type of what it gives back to the program (as opposed to what it does outside the program). <code>()</code> (pronounced as "unit") is a type that only contains one value also called <code>()</code> (effectively a tuple with zero elements). Since <code>putStrLn</code> sends output to the world but doesn't return anything to the program, <code>()</code> is used as a placeholder. We might read <code>IO ()</code> as "action which returns <code>()</code>".
A few more examples of when we use IO:
* print a string to the screen
* read a string from a keyboard
* write data to a file
* read data from a file
What makes IO actually work? Lots of things happen behind the scenes to take us from <code>putStrLn</code> to pixels in the screen, but we don't need to understand any of the details to write our programs. A complete Haskell program is actually a big IO action. In a compiled program, this action is called <code>main</code> and has type <code>IO ()</code>. From this point of view, to write a Haskell program is to combine actions and functions to form the overall action <code>main</code> that will be executed when the program is run. The compiler takes care of instructing the computer on how to do this.
{{Exercises|1=
Back in the Type Basics chapter, we mentioned that the type of the [[Haskell/Type_basics#Real world example: openWindow|<code>openWindow</code> function]] had been simplified. What do you think its type should actually be?
}}
== Sequencing actions with ''do'' ==
'''do''' notation provides a convenient means of putting actions together (which is essential in doing useful things with Haskell). Consider the following program:
{{Haskell/Example|1=What is your name?|2=<syntaxhighlight lang="haskell">
main = do
putStrLn "Please enter your name:"
name <- getLine
putStrLn ("Hello, " ++ name ++ ", how are you?")
</syntaxhighlight>}}
{{body note|1=
Even though <code>do</code> notation looks very different from the Haskell code we have seen so far, it is just syntactic sugar for a handful of functions, the most important of them being the <code>(>>=)</code> operator. We could explain how those functions work and ''then'' introduce <code>do</code> notation. However, there are several topics we would need to cover before we can give a convincing explanation. Jumping in with <code>do</code> right now is a pragmatic shortcut that will allow you to start writing complete programs with IO right away. We will see how <code>do</code> works later in the book, beginning with the [[../Understanding monads/]] chapter.
}}
Before we get into how ''do'' works, take a look at <code>getLine</code>. It goes to the outside world (to the terminal in this case) and brings back a <code>String</code>. What is its type?
<syntaxhighlight lang="haskell">
Prelude> :t getLine
getLine :: IO String
</syntaxhighlight>
That means <code>getLine</code> is an IO action that, when run, will return a <code>String</code>. But what about the input? While functions have types like <code>a -> b</code> which reflect that they take arguments and give back results, <code>getLine</code> doesn't actually take an argument. It takes as input whatever is in the line in the terminal. However, that line in the outside world isn't a defined value with a type until we bring it into the Haskell program.
The program doesn't know the state of the outside world until runtime, so it cannot predict the exact results of IO actions. To manage the relationship of these IO actions to other aspects of a program, the actions must be executed in a predictable sequence defined in advance in the code. With regular functions that do not perform IO, the exact sequencing of execution is less of an issue — as long as the results eventually go to the right places.
In our name program, we're sequencing three actions: a <code>putStrLn</code> with a greeting, a <code>getLine</code>, and another <code>putStrLn</code>. With the <code>getLine</code>, we use <code><-</code> notation which assigns a variable name to stand for the returned value. We cannot know what the value will be in advance, but we know it will use the specified variable name, so we can then use the variable elsewhere (in this case, to prepare the final message being printed). The final action defines the type of the whole <code>do</code> block. Here, the final action is the result of a <code>putStrLn</code>, and so our whole program has type <code>IO ()</code>.
{{Exercises|1=
Write a program which asks the user for the base and height of a right angled triangle, calculates its area, and prints it to the screen.
The interaction should look something like:
<pre>
The base?
3.3
The height?
5.4
The area of that triangle is 8.91
</pre>
You will need to use the function <code>read</code> to convert user strings like "3.3" into numbers like 3.3 and the function <code>show</code> to convert a number into string.
}}
=== Left arrow clarifications ===
While actions like <code>getLine</code> are almost always used to get values, we are not obliged to actually get them. For example, we could write something like this:
{{Haskell/Example|1=executing <code>getLine</code> directly|2=<syntaxhighlight lang="haskell">
main = do
putStrLn "Please enter your name:"
getLine
putStrLn "Hello, how are you?"
</syntaxhighlight>}}
In this case, we don't use the input at all, but we still give the user the experience of entering their name. By omitting the <code><-</code>, the action will happen, but the data won't be stored or accessible to the program.
==== <code><-</code> can be used with any action except the last ====
There are very few restrictions on which actions can have values
obtained from them. Consider the following example where we put the
results of each action into a variable (except the last... more on that
later):
{{Haskell/Example|1=putting all results into a variable|2=<syntaxhighlight lang="haskell">
main = do
x <- putStrLn "Please enter your name:"
name <- getLine
putStrLn ("Hello, " ++ name ++ ", how are you?")
</syntaxhighlight>}}
The variable <code>x</code> gets the value out
of its action, but that isn't useful in this case because
the action returns the unit value <code>()</code>. So while we could technically get the value out
of any action, it isn't always worth it.
So, what about the final action? Why can't we get a value out of that? Let's see what happens
when we try:
{{HaskellExample|1=getting the value out of the last action|2=
<syntaxhighlight lang="haskell">
main = do
x <- putStrLn "Please enter your name:"
name <- getLine
y <- putStrLn ("Hello, " ++ name ++ ", how are you?")
</syntaxhighlight>
Whoops! Error!
{{HaskellGHCi|1=
HaskellWikibook.hs:5:2:
The last statement in a 'do' construct must be an expression
}}
}}
Making sense of this requires a somewhat deeper understanding of Haskell than we currently have. Suffice it to
say, after any line where you use <code><-</code> to get the value of an action, Haskell expects another action, so the final action cannot have any <code><-</code>s.
=== Controlling actions ===
Normal Haskell constructions like <code>'''if/then/else'''</code>
can be used within the <code>'''do'''</code> notation, but you need to take some
care here. For instance, in a simple "guess the number" program, we have:
<syntaxhighlight lang="haskell">
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
if (read guess) < num
then do putStrLn "Too low!"
doGuessing num
else if (read guess) > num
then do putStrLn "Too high!"
doGuessing num
else putStrLn "You Win!"
</syntaxhighlight>
Remember that the <code>'''if/then/else'''</code> construction takes three arguments:
the condition, the "then" branch, and the "else" branch. The condition needs to have type <code>Bool</code>,
and the two branches can have any type, provided that they have the ''same'' type. The type of the entire <code>'''if/then/else'''</code>
construction is then the type of the two branches.
In the outermost comparison, we have <code>(read guess) < num</code> as the condition.
That has the correct type. Let's now consider the "then" branch. The code here is:
<syntaxhighlight lang="haskell">
do putStrLn "Too low!"
doGuessing num
</syntaxhighlight>
Here, we are sequencing two actions: <code>putStrLn</code> and
<code>doGuessing</code>. The first has type <code>IO ()</code>, which is fine. The
second also has type <code>IO ()</code>, which is fine. The type result of the
entire computation is precisely the type of the final computation.
Thus, the type of the "then" branch is also <code>IO ()</code>. A similar
argument shows that the type of the "else" branch is also <code>IO ()</code>.
This means the type of the entire <code>'''if/then/else'''</code>
construction is <code>IO ()</code>, which is what we want.
Note: be careful if you find yourself thinking, "Well, I already started
a <code>'''do'''</code> block; I don't need another one." We can't have code like:
<syntaxhighlight lang="haskell">
do if (read guess) < num
then putStrLn "Too low!"
doGuessing num
else ...
</syntaxhighlight>
Here, since we didn't repeat the <code>'''do'''</code>, the compiler doesn't know
that the <code>putStrLn</code> and <code>doGuessing</code> calls are supposed to be
sequenced, and the compiler will think you're trying to call
<code>putStrLn</code> with three arguments: the string, the function
<code>doGuessing</code> and the integer <code>num</code>, and thus reject the program.
{{Exercises|1=
Write a program that asks the user for his or her name. If the name is
one of Simon, John or Phil, tell the user that you think Haskell is a
great programming language. If the name is Koen, tell them that you
think debugging Haskell is fun (Koen Classen is one of the people who
works on Haskell debugging); otherwise, tell the user that you don't know who he or she is.
(As far as syntax goes there are a few different ways to do it; write at least a version using <code>if</code> / <code>then</code> / <code>else</code>.)
}}
== Actions under the microscope ==
Actions may look easy up to now, but they are a common stumbling block for new Haskellers. If you have run into trouble working with actions, see if any of your problems or questions match any of the cases below. We suggest skimming this section now, then come back here when you actually experience trouble.
=== Mind your action types ===
One temptation might be to simplify our program for getting a name and printing it back out. Here is one unsuccessful attempt:
{{HaskellExample|Why doesn't this work?|
<syntaxhighlight lang="haskell">
main =
do putStrLn "What is your name? "
putStrLn ("Hello " ++ getLine)
</syntaxhighlight>
Ouch! Error!
{{Haskell/GHCi|1=
HaskellWikiBook.hs:3:26:
Couldn't match expected type `[Char]'
against inferred type `IO String'
}}
}}
Let us boil the example above down to its simplest form. Would you expect this program to compile?
{{HaskellExample|1=This still does not work|2=<syntaxhighlight lang="haskell">
main =
do putStrLn getLine
</syntaxhighlight>}}
For the most part, this is the same (attempted) program, except that we've stripped off the superfluous "What is your name" prompt as well as the polite "Hello". One trick to understanding this is to reason about it in terms of types. Let us compare:
<syntaxhighlight lang="haskell">
putStrLn :: String -> IO ()
getLine :: IO String
</syntaxhighlight>
We can use the same mental machinery we learned in [[../Type basics/]] to figure how this went wrong. <code>putStrLn</code> is expecting a <code>String</code> as input. We do not have a <code>String</code>; we have something tantalisingly close: an <code>IO String</code>. This represents an action that will ''give'' us a <code>String</code> when it's run. To obtain the <code>String</code> that <code>putStrLn</code> wants, we need to run the action, and we do that with the ever-handy left arrow, <code><-</code>.
{{Haskell/Example|1=This time it works|2=
<syntaxhighlight lang="haskell">
main =
do name <- getLine
putStrLn name
</syntaxhighlight>
Working our way back up to the fancy example:
<syntaxhighlight lang="haskell">
main =
do putStrLn "What is your name? "
name <- getLine
putStrLn ("Hello " ++ name)
</syntaxhighlight>
}}
Now the name is the String we are looking for and everything is rolling again.
=== Mind your expression types too ===
So, we've made a big deal out of the idea that you can't use actions in situations that don't call for them. The converse of this is that you can't use non-actions in situations that expect actions. Say we want to greet the user, but this time we're so excited to meet them, we just have to SHOUT their name out:
{{HaskellExample|1=Exciting but incorrect. Why?|2=
<syntaxhighlight lang="haskell">
import Data.Char (toUpper)
main =
do name <- getLine
loudName <- makeLoud name
putStrLn ("Hello " ++ loudName ++ "!")
putStrLn ("Oh boy! Am I excited to meet you, " ++ loudName)
-- Don't worry too much about this function; it just converts a String to uppercase
makeLoud :: String -> String
makeLoud s = map toUpper s
</syntaxhighlight>
This goes wrong...
{{HaskellGHCi|1=
Couldn't match expected type `IO' against inferred type `[]'
Expected type: IO t
Inferred type: String
In a 'do' expression: loudName <- makeLoud name
}}
}}
This is similar to the problem we ran into above: we've got a mismatch between something expecting an IO type and something which does not produce IO. This time, the trouble is the left arrow <code><-</code>; we're trying to left-arrow a value of <code>makeLoud name</code>, which really isn't left arrow material. It's basically the same mismatch we saw in the previous section, except now we're trying to use regular old String (the loud name) as an IO String. The latter is an action, something to be run, whereas the former is just an expression minding its own business. We cannot simply use <code>loudName = makeLoud name</code> because a <code>do</code> sequences ''actions'', and <code>loudName = makeLoud name</code> is not an action.
So how do we extricate ourselves from this mess? We have a number of options:
* We could find a way to turn <code>makeLoud</code> into an action, to make it return <code>IO String</code>. However, we don't want to make actions go out into the world for no reason. Within our program, we can reliably verify how everything is working. When actions engage the outside world, our results are much less predictable. An IO <code>makeLoud</code> would be misguided. Consider another issue too: what if we wanted to use makeLoud from some other, non-IO, function? We really don't want to engage IO actions except when absolutely necessary.
* We could use a special code called <code>return</code> to promote the loud name into an action, writing something like <code>loudName <- return (makeLoud name)</code>. This is slightly better. We at least leave the <code>makeLoud</code> function itself nice and IO-free whilst using it in an IO-compatible fashion. That's still moderately clunky because, by virtue of left arrow, we're implying that there's action to be had -- how exciting! -- only to let our reader down with a somewhat anticlimactic <code>return</code> (note: we will learn more about appropriate uses for <code>return</code> in later chapters).
* Or we could use a let binding...
It turns out that Haskell has a special extra-convenient syntax for let bindings in actions. It looks a little like this:
{{HaskellExample|1=<code>let</code> bindings in <code>do</code> blocks.|2=<syntaxhighlight lang="haskell">
main =
do name <- getLine
let loudName = makeLoud name
putStrLn ("Hello " ++ loudName ++ "!")
putStrLn ("Oh boy! Am I excited to meet you, " ++ loudName)
</syntaxhighlight>}}
If you're paying attention, you might notice that the let binding above is missing an <code>in</code>. This is because <code>let</code> bindings inside <code>do</code> blocks do not require the <code>in</code> keyword. You could very well use it, but then you'd have messy extra do blocks. For what it's worth, the following two blocks of code are equivalent.
{|class="wikitable"
!|sweet
!|unsweet
|-
||
<syntaxhighlight lang="haskell">
do name <- getLine
let loudName = makeLoud name
putStrLn ("Hello " ++ loudName ++ "!")
putStrLn (
"Oh boy! Am I excited to meet you, "
++ loudName)
</syntaxhighlight>
||
<syntaxhighlight lang="haskell">
do name <- getLine
let loudName = makeLoud name
in do putStrLn ("Hello " ++ loudName ++ "!")
putStrLn (
"Oh boy! Am I excited to meet you, "
++ loudName)
</syntaxhighlight>
|}
{{Exercises|
# Why does the unsweet version of the let binding require an extra <code>do</code> keyword?
# Do you always need the extra <code>do</code>?
# (extra credit) Curiously, <code>let</code> without <code>in</code> is exactly how we wrote things when we were playing with the interpreter in the beginning of this book. Why is it ok to omit the <code>in</code> keyword in the interpreter but needed (outside of ''do'' blocks) in a source file?
}}
== Learn more ==
At this point, you have the fundamentals needed to do some fancier input/output. Here are some IO-related topics you may want to check in parallel with the main track of this course.
* You could continue the sequential track, learning more about [[../Type Declarations/|types]] and eventually [[../Understanding monads/|monads]].
* Alternately: you could start learning about building graphical user interfaces in the [[../GUI/]] chapter
* For more IO-related functionality, you could also consider learning more about the [[../Hierarchical libraries/IO|System.IO library]]
{{Haskell navigation|chapter=Haskell Basics}}
{{Auto category}}
2d6h4yvgngeeqhbglng5zzn3r1j1put
4675906
4675904
2026-10-13T19:04:06Z
Luciérnaga de conocimiento
3401314
4675906
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Haskell Basics}}
== Back to the real world ==
Beyond internally calculating values, we want our programs to interact with the world. The most common beginners' program in any language simply displays a "hello world" greeting on the screen. Here's a Haskell version:
<syntaxhighlight lang="haskell">
Prelude> putStrLn "Hello, World!"
</syntaxhighlight>
<code>putStrLn</code> is one of the standard Prelude tools. As the "putStr" part of the name suggests, it takes a <code>String</code> as an argument and prints it to the screen. We could use <code>putStr</code> on its own, but we usually include the "Ln" part so to also print a line break. Thus, whatever else is printed next will appear on a new line.
So now you should be thinking, "what is the type of the putStrLn function?" It takes a <code>String</code> and gives… um… what? What do we call that? The program doesn't get something back that it can use in another function. Instead, the result involves having the computer change the screen. In other words, it does something in the world outside of the program. What type could that have? Let's see what GHCi tells us:
<syntaxhighlight lang="haskell">
Prelude> :t putStrLn
putStrLn :: String -> IO ()
</syntaxhighlight>
"IO" stands for "input and output". Wherever there is <code>IO</code> in a type, interaction with the world outside the program is involved. We'll call these <code>IO</code> values ''actions''. The other part of the <code>IO</code> type, in this case <code>()</code>, is the type of the return value of the action; that is, the type of what it gives back to the program (as opposed to what it does outside the program). <code>()</code> (pronounced as "unit") is a type that only contains one value also called <code>()</code> (effectively a tuple with zero elements). Since <code>putStrLn</code> sends output to the world but doesn't return anything to the program, <code>()</code> is used as a placeholder. We might read <code>IO ()</code> as "action which returns <code>()</code>".
A few more examples of when we use IO:
* print a string to the screen
* read a string from a keyboard
* write data to a file
* read data from a file
What makes IO actually work? Lots of things happen behind the scenes to take us from <code>putStrLn</code> to pixels in the screen, but we don't need to understand any of the details to write our programs. A complete Haskell program is actually a big IO action. In a compiled program, this action is called <code>main</code> and has type <code>IO ()</code>. From this point of view, to write a Haskell program is to combine actions and functions to form the overall action <code>main</code> that will be executed when the program is run. The compiler takes care of instructing the computer on how to do this.
{{Exercises|1=
Back in the Type Basics chapter, we mentioned that the type of the [[Haskell/Type_basics#Real world example: openWindow|<code>openWindow</code> function]] had been simplified. What do you think its type should actually be?
}}
== Sequencing actions with ''do'' ==
'''do''' notation provides a convenient means of putting actions together (which is essential in doing useful things with Haskell). Consider the following program:
{{Haskell/Example|1=What is your name?|2=<syntaxhighlight lang="haskell">
main = do
putStrLn "Please enter your name:"
name <- getLine
putStrLn ("Hello, " ++ name ++ ", how are you?")
</syntaxhighlight>}}
{{body note|1=
Even though <code>do</code> notation looks very different from the Haskell code we have seen so far, it is just syntactic sugar for a handful of functions, the most important of them being the <code>(>>=)</code> operator. We could explain how those functions work and ''then'' introduce <code>do</code> notation. However, there are several topics we would need to cover before we can give a convincing explanation. Jumping in with <code>do</code> right now is a pragmatic shortcut that will allow you to start writing complete programs with IO right away. We will see how <code>do</code> works later in the book, beginning with the [[../Understanding monads/]] chapter.
}}
Before we get into how ''do'' works, take a look at <code>getLine</code>. It goes to the outside world (to the terminal in this case) and brings back a <code>String</code>. What is its type?
<syntaxhighlight lang="haskell">
Prelude> :t getLine
getLine :: IO String
</syntaxhighlight>
That means <code>getLine</code> is an IO action that, when run, will return a <code>String</code>. But what about the input? While functions have types like <code>a -> b</code> which reflect that they take arguments and give back results, <code>getLine</code> doesn't actually take an argument. It takes as input whatever is in the line in the terminal. However, that line in the outside world isn't a defined value with a type until we bring it into the Haskell program.
The program doesn't know the state of the outside world until runtime, so it cannot predict the exact results of IO actions. To manage the relationship of these IO actions to other aspects of a program, the actions must be executed in a predictable sequence defined in advance in the code. With regular functions that do not perform IO, the exact sequencing of execution is less of an issue — as long as the results eventually go to the right places.
In our name program, we're sequencing three actions: a <code>putStrLn</code> with a greeting, a <code>getLine</code>, and another <code>putStrLn</code>. With the <code>getLine</code>, we use <code><-</code> notation which assigns a variable name to stand for the returned value. We cannot know what the value will be in advance, but we know it will use the specified variable name, so we can then use the variable elsewhere (in this case, to prepare the final message being printed). The final action defines the type of the whole <code>do</code> block. Here, the final action is the result of a <code>putStrLn</code>, and so our whole program has type <code>IO ()</code>.
{{Exercises|1=
Write a program which asks the user for the base and height of a right angled triangle, calculates its area, and prints it to the screen.
The interaction should look something like:
<pre>
The base?
3.3
The height?
5.4
The area of that triangle is 8.91
</pre>
You will need to use the function <code>read</code> to convert user strings like "3.3" into numbers like 3.3 and the function <code>show</code> to convert a number into string.
}}
=== Left arrow clarifications ===
While actions like <code>getLine</code> are almost always used to get values, we are not obliged to actually get them. For example, we could write something like this:
{{Haskell/Example|1=executing <code>getLine</code> directly|2=<syntaxhighlight lang="haskell">
main = do
putStrLn "Please enter your name:"
getLine
putStrLn "Hello, how are you?"
</syntaxhighlight>}}
In this case, we don't use the input at all, but we still give the user the experience of entering their name. By omitting the <code><-</code>, the action will happen, but the data won't be stored or accessible to the program.
==== <code><-</code> can be used with any action except the last ====
There are very few restrictions on which actions can have values
obtained from them. Consider the following example where we put the
results of each action into a variable (except the last... more on that
later):
{{Haskell/Example|1=putting all results into a variable|2=<syntaxhighlight lang="haskell">
main = do
x <- putStrLn "Please enter your name:"
name <- getLine
putStrLn ("Hello, " ++ name ++ ", how are you?")
</syntaxhighlight>}}
The variable <code>x</code> gets the value out
of its action, but that isn't useful in this case because
the action returns the unit value <code>()</code>. So while we could technically get the value out
of any action, it isn't always worth it.
So, what about the final action? Why can't we get a value out of that? Let's see what happens
when we try:
{{Haskell/Example|1=getting the value out of the last action|2=
<syntaxhighlight lang="haskell">
main = do
x <- putStrLn "Please enter your name:"
name <- getLine
y <- putStrLn ("Hello, " ++ name ++ ", how are you?")
</syntaxhighlight>
Whoops! Error!
{{Haskell/GHCi|1=
HaskellWikibook.hs:5:2:
The last statement in a 'do' construct must be an expression
}}
}}
Making sense of this requires a somewhat deeper understanding of Haskell than we currently have. Suffice it to
say, after any line where you use <code><-</code> to get the value of an action, Haskell expects another action, so the final action cannot have any <code><-</code>s.
=== Controlling actions ===
Normal Haskell constructions like <code>'''if/then/else'''</code>
can be used within the <code>'''do'''</code> notation, but you need to take some
care here. For instance, in a simple "guess the number" program, we have:
<syntaxhighlight lang="haskell">
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
if (read guess) < num
then do putStrLn "Too low!"
doGuessing num
else if (read guess) > num
then do putStrLn "Too high!"
doGuessing num
else putStrLn "You Win!"
</syntaxhighlight>
Remember that the <code>'''if/then/else'''</code> construction takes three arguments:
the condition, the "then" branch, and the "else" branch. The condition needs to have type <code>Bool</code>,
and the two branches can have any type, provided that they have the ''same'' type. The type of the entire <code>'''if/then/else'''</code>
construction is then the type of the two branches.
In the outermost comparison, we have <code>(read guess) < num</code> as the condition.
That has the correct type. Let's now consider the "then" branch. The code here is:
<syntaxhighlight lang="haskell">
do putStrLn "Too low!"
doGuessing num
</syntaxhighlight>
Here, we are sequencing two actions: <code>putStrLn</code> and
<code>doGuessing</code>. The first has type <code>IO ()</code>, which is fine. The
second also has type <code>IO ()</code>, which is fine. The type result of the
entire computation is precisely the type of the final computation.
Thus, the type of the "then" branch is also <code>IO ()</code>. A similar
argument shows that the type of the "else" branch is also <code>IO ()</code>.
This means the type of the entire <code>'''if/then/else'''</code>
construction is <code>IO ()</code>, which is what we want.
Note: be careful if you find yourself thinking, "Well, I already started
a <code>'''do'''</code> block; I don't need another one." We can't have code like:
<syntaxhighlight lang="haskell">
do if (read guess) < num
then putStrLn "Too low!"
doGuessing num
else ...
</syntaxhighlight>
Here, since we didn't repeat the <code>'''do'''</code>, the compiler doesn't know
that the <code>putStrLn</code> and <code>doGuessing</code> calls are supposed to be
sequenced, and the compiler will think you're trying to call
<code>putStrLn</code> with three arguments: the string, the function
<code>doGuessing</code> and the integer <code>num</code>, and thus reject the program.
{{Exercises|1=
Write a program that asks the user for his or her name. If the name is
one of Simon, John or Phil, tell the user that you think Haskell is a
great programming language. If the name is Koen, tell them that you
think debugging Haskell is fun (Koen Classen is one of the people who
works on Haskell debugging); otherwise, tell the user that you don't know who he or she is.
(As far as syntax goes there are a few different ways to do it; write at least a version using <code>if</code> / <code>then</code> / <code>else</code>.)
}}
== Actions under the microscope ==
Actions may look easy up to now, but they are a common stumbling block for new Haskellers. If you have run into trouble working with actions, see if any of your problems or questions match any of the cases below. We suggest skimming this section now, then come back here when you actually experience trouble.
=== Mind your action types ===
One temptation might be to simplify our program for getting a name and printing it back out. Here is one unsuccessful attempt:
{{Haskell/Example|Why doesn't this work?|
<syntaxhighlight lang="haskell">
main =
do putStrLn "What is your name? "
putStrLn ("Hello " ++ getLine)
</syntaxhighlight>
Ouch! Error!
{{Haskell/GHCi|1=
HaskellWikiBook.hs:3:26:
Couldn't match expected type `[Char]'
against inferred type `IO String'
}}
}}
Let us boil the example above down to its simplest form. Would you expect this program to compile?
{{Haskell/Example|1=This still does not work|2=<syntaxhighlight lang="haskell">
main =
do putStrLn getLine
</syntaxhighlight>}}
For the most part, this is the same (attempted) program, except that we've stripped off the superfluous "What is your name" prompt as well as the polite "Hello". One trick to understanding this is to reason about it in terms of types. Let us compare:
<syntaxhighlight lang="haskell">
putStrLn :: String -> IO ()
getLine :: IO String
</syntaxhighlight>
We can use the same mental machinery we learned in [[../Type basics/]] to figure how this went wrong. <code>putStrLn</code> is expecting a <code>String</code> as input. We do not have a <code>String</code>; we have something tantalisingly close: an <code>IO String</code>. This represents an action that will ''give'' us a <code>String</code> when it's run. To obtain the <code>String</code> that <code>putStrLn</code> wants, we need to run the action, and we do that with the ever-handy left arrow, <code><-</code>.
{{Haskell/Example|1=This time it works|2=
<syntaxhighlight lang="haskell">
main =
do name <- getLine
putStrLn name
</syntaxhighlight>
Working our way back up to the fancy example:
<syntaxhighlight lang="haskell">
main =
do putStrLn "What is your name? "
name <- getLine
putStrLn ("Hello " ++ name)
</syntaxhighlight>
}}
Now the name is the String we are looking for and everything is rolling again.
=== Mind your expression types too ===
So, we've made a big deal out of the idea that you can't use actions in situations that don't call for them. The converse of this is that you can't use non-actions in situations that expect actions. Say we want to greet the user, but this time we're so excited to meet them, we just have to SHOUT their name out:
{{Haskell/Example|1=Exciting but incorrect. Why?|2=
<syntaxhighlight lang="haskell">
import Data.Char (toUpper)
main =
do name <- getLine
loudName <- makeLoud name
putStrLn ("Hello " ++ loudName ++ "!")
putStrLn ("Oh boy! Am I excited to meet you, " ++ loudName)
-- Don't worry too much about this function; it just converts a String to uppercase
makeLoud :: String -> String
makeLoud s = map toUpper s
</syntaxhighlight>
This goes wrong...
{{Haskell/GHCi|1=
Couldn't match expected type `IO' against inferred type `[]'
Expected type: IO t
Inferred type: String
In a 'do' expression: loudName <- makeLoud name
}}
}}
This is similar to the problem we ran into above: we've got a mismatch between something expecting an IO type and something which does not produce IO. This time, the trouble is the left arrow <code><-</code>; we're trying to left-arrow a value of <code>makeLoud name</code>, which really isn't left arrow material. It's basically the same mismatch we saw in the previous section, except now we're trying to use regular old String (the loud name) as an IO String. The latter is an action, something to be run, whereas the former is just an expression minding its own business. We cannot simply use <code>loudName = makeLoud name</code> because a <code>do</code> sequences ''actions'', and <code>loudName = makeLoud name</code> is not an action.
So how do we extricate ourselves from this mess? We have a number of options:
* We could find a way to turn <code>makeLoud</code> into an action, to make it return <code>IO String</code>. However, we don't want to make actions go out into the world for no reason. Within our program, we can reliably verify how everything is working. When actions engage the outside world, our results are much less predictable. An IO <code>makeLoud</code> would be misguided. Consider another issue too: what if we wanted to use makeLoud from some other, non-IO, function? We really don't want to engage IO actions except when absolutely necessary.
* We could use a special code called <code>return</code> to promote the loud name into an action, writing something like <code>loudName <- return (makeLoud name)</code>. This is slightly better. We at least leave the <code>makeLoud</code> function itself nice and IO-free whilst using it in an IO-compatible fashion. That's still moderately clunky because, by virtue of left arrow, we're implying that there's action to be had -- how exciting! -- only to let our reader down with a somewhat anticlimactic <code>return</code> (note: we will learn more about appropriate uses for <code>return</code> in later chapters).
* Or we could use a let binding...
It turns out that Haskell has a special extra-convenient syntax for let bindings in actions. It looks a little like this:
{{Haskell/Example|1=<code>let</code> bindings in <code>do</code> blocks.|2=<syntaxhighlight lang="haskell">
main =
do name <- getLine
let loudName = makeLoud name
putStrLn ("Hello " ++ loudName ++ "!")
putStrLn ("Oh boy! Am I excited to meet you, " ++ loudName)
</syntaxhighlight>}}
If you're paying attention, you might notice that the let binding above is missing an <code>in</code>. This is because <code>let</code> bindings inside <code>do</code> blocks do not require the <code>in</code> keyword. You could very well use it, but then you'd have messy extra do blocks. For what it's worth, the following two blocks of code are equivalent.
{|class="wikitable"
!|sweet
!|unsweet
|-
||
<syntaxhighlight lang="haskell">
do name <- getLine
let loudName = makeLoud name
putStrLn ("Hello " ++ loudName ++ "!")
putStrLn (
"Oh boy! Am I excited to meet you, "
++ loudName)
</syntaxhighlight>
||
<syntaxhighlight lang="haskell">
do name <- getLine
let loudName = makeLoud name
in do putStrLn ("Hello " ++ loudName ++ "!")
putStrLn (
"Oh boy! Am I excited to meet you, "
++ loudName)
</syntaxhighlight>
|}
{{Exercises|
# Why does the unsweet version of the let binding require an extra <code>do</code> keyword?
# Do you always need the extra <code>do</code>?
# (extra credit) Curiously, <code>let</code> without <code>in</code> is exactly how we wrote things when we were playing with the interpreter in the beginning of this book. Why is it ok to omit the <code>in</code> keyword in the interpreter but needed (outside of ''do'' blocks) in a source file?
}}
== Learn more ==
At this point, you have the fundamentals needed to do some fancier input/output. Here are some IO-related topics you may want to check in parallel with the main track of this course.
* You could continue the sequential track, learning more about [[../Type Declarations/|types]] and eventually [[../Understanding monads/|monads]].
* Alternately: you could start learning about building graphical user interfaces in the [[../GUI/]] chapter
* For more IO-related functionality, you could also consider learning more about the [[../Hierarchical libraries/IO|System.IO library]]
{{Haskell/Navigation|chapter=Haskell Basics}}
{{BookCat}}
om62kg4s9abghknab9zxfymaml6z4c7
Haskell/Lists III
0
27121
4675926
4485942
2026-10-13T23:03:51Z
Luciérnaga de conocimiento
3401314
4675926
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Elementary Haskell}}
== Folds ==
Like <code>map</code>, a ''fold'' is a higher order function that takes a function and a list. However, instead of applying the function element by element, the fold uses it to combine the list elements into a result value.
Let's look at a few concrete examples. <code>sum</code> could be implemented as:
{{Haskell/Example|sum|<syntaxhighlight lang="haskell">
sum :: [Integer] -> Integer
sum [] = 0
sum (x:xs) = x + sum xs</syntaxhighlight>}}
and <code>product</code> as:
{{Haskell/Example|product|<syntaxhighlight lang="haskell">
product :: [Integer] -> Integer
product [] = 1
product (x:xs) = x * product xs</syntaxhighlight>}}
<code>concat</code>, which takes a list of lists and joins (concatenates) them into one:
{{Haskell/Example|concat|<syntaxhighlight lang="haskell">
concat :: [[a]] -> [a]
concat [] = []
concat (x:xs) = x ++ concat xs</syntaxhighlight>}}
All these examples show a pattern of recursion known as a fold. Think of the name referring to a list getting "folded up" into a single value or to a function being "folded between" the elements of the list.
Prelude defines four <code>fold</code> functions: <code>foldr</code>, <code>foldl</code>, <code>foldr1</code> and <code>foldl1</code>.
=== foldr ===
The ''right-associative'' <code>foldr</code> folds up a list from the right to left. As it proceeds, foldr uses the given function to combine each of the elements with the running value called the ''accumulator''. When calling foldr, the initial value of the accumulator is set as an argument.
<syntaxhighlight lang="haskell">
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f acc [] = acc
foldr f acc (x:xs) = f x (foldr f acc xs)
</syntaxhighlight>
The first argument to <code>foldr</code> is a function with two arguments. The second argument is the value for the accumulator (which often starts at a neutral "zero" value). The third argument is the list to be folded.
In <code>sum</code>, <code>f</code> is <code>(+)</code>, and <code>acc</code> is <code>0</code>. In <code>concat</code>, <code>f</code> is <code>(++)</code> and <code>acc</code> is <code>[]</code>. In many cases (like all of our examples so far), the function passed to a fold will be one that takes two arguments of the same type, but this is not necessarily the case (as we can see from the <code>(a -> b -> b)</code> part of the type signature — if the types ''had'' to be the same, the first two letters in the type signature would have matched).
Remember, a list in Haskell written as <code>[a, b, c]</code> is an alternative (syntactic sugar) style for <code>a : b : c : []</code>.
Now, <code>foldr f acc xs</code> in the <code>foldr</code> definition simply replaces each cons (:) in the <code>xs</code> list with the function <code>f</code> while replacing the empty list at the end with <code>acc</code>:
<syntaxhighlight lang="haskell">
foldr f acc (a:b:c:[]) = f a (f b (f c acc))
</syntaxhighlight>
Note how the parentheses nest around the right end of the list.
An elegant visualisation is given by picturing the list data structure as a tree:
: f
/ \ / \
a : foldr f acc a f
/ \ -------------> / \
b : b f
/ \ / \
c [] c acc
We can see here that <code>foldr (:) []</code> will return the list completely unchanged. That sort of function that has no effect is called an ''identity function''. You should start building a habit of looking for identity functions in different cases, and we'll discuss them more later when we learn about ''monoids''.
=== foldl ===
The ''left-associative'' <code>foldl</code> processes the list in the opposite direction, starting at the left side with the first element.
<syntaxhighlight lang="haskell">
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f acc [] = acc
foldl f acc (x:xs) = foldl f (f acc x) xs
</syntaxhighlight>
So, parentheses in the resulting expression accumulate around the left end of the list:
<syntaxhighlight lang="haskell">
foldl f acc (a:b:c:[]) = f (f (f acc a) b) c
</syntaxhighlight>
The corresponding trees look like:
: f
/ \ / \
a : foldl f acc f c
/ \ -------------> / \
b : f b
/ \ / \
c [] acc a
Because all folds include both left and right elements, beginners can get confused by the names. You could think of foldr as short for fold-right-to-left and foldl as fold-left-to-right. The names refer to where the fold starts.
{{body note|1=
''Technical Note'': foldl is ''tail-recursive'', that is, it recurses
immediately, calling itself. For this reason the compiler will optimise it to a
simple loop for efficiency. However, Haskell is a lazy language, so the calls to
''f'' will be left unevaluated by default, thus building up an unevaluated
expression in memory that includes the entire length of the list. To avoid
running out of memory, we have a version of foldl called <code>foldl'</code>
that is ''strict'' — it forces the evaluation of ''f'' immediately at each step.
An apostrophe at the end of a function name is pronounced "tick" as in
"fold-L-tick" or "prime" as in "fold-L-prime". A tick is a valid character in Haskell identifiers.
<code>foldl'</code> can be found in the <code>Data.List</code> library module
(imported by adding <code>import Data.List</code> to the beginning of a source
file). As a rule of thumb, you should use <code>foldr</code> on lists that might
be infinite or where the fold is building up a data structure and use
<code>foldl'</code> if the list is known to be finite and comes down to a single
value. There is almost never a good reason to use <code>foldl</code> (without
the tick), though it might just work if the lists fed to it are not too long.
}}
=== Are foldl and foldr opposites? ===
You may notice that in some cases <code>foldl</code> and <code>foldr</code> do ''not'' appear to be opposites. Let's examine one such case, involving subtraction as the combining operation. Will we get <code>True</code> or <code>False</code> for each of the equalities below?
<syntaxhighlight lang="haskell">
foldl (-) 6 [3, 2, 1] == 6 - 3 - 2 - 1
foldr (-) 6 [1, 2, 3] == 6 - 3 - 2 - 1
</syntaxhighlight>
Thinking of <code>foldr</code> as going from right to left might lead us to suppose that the second equality would be true, as the rightmost elements show up before the leftmost ones. That, however, is not what we actually see:
<syntaxhighlight lang="haskell">
GHCi> foldl (-) 6 [3, 2, 1] == 6 - 3 - 2 - 1
True
GHCi> foldr (-) 6 [1, 2, 3] == 6 - 3 - 2 - 1
False
</syntaxhighlight>
This happens because the difference between <code>foldr</code> and <code>foldl</code> lies in the way the resulting expression is associated, and not in the left-to-right order of the elements of the list. Here is the expansion of the expressions above, with explicit parentheses:
<syntaxhighlight lang="haskell">
foldl (-) 6 [3, 2, 1] == ((6 - 3) - 2) - 1 -- True
foldr (-) 6 [1, 2, 3] == 1 - (2 - (3 - 6)) -- True
</syntaxhighlight>
Also note how the initial accumulator (<code>6</code> in this example) is always found in the innermost parentheses.
For the sake of contrast, here is a simulated imperative style that does change the order of the elements in the list:
<ref>The <code>reduce</code> and <code>reduceRight</code> functions are taken from JavaScript, and they behave in this manner.</ref>
<syntaxhighlight lang="haskell">
GHCi> import Data.List -- So that we can give foldl' a try
GHCi> reduce f acc list = foldl' f acc list -- This is the same as plain old foldl'
GHCi> reduceRight f acc list = foldl' f acc (reverse list) -- keep foldl', but reverse list
</syntaxhighlight>
Now we get <code>True</code> in both cases from our initial example, because both are folding from the left:
<syntaxhighlight lang="haskell">
GHCi> reduce (-) 6 [3, 2, 1] == 6 - 3 - 2 - 1
True
GHCi> reduceRight (-) 6 [1, 2, 3] == 6 - 3 - 2 - 1
True
</syntaxhighlight>
=== foldr1 and foldl1 ===
As previously noted, the type declaration for <code>foldr</code> makes it quite possible for the list elements and result to be of different types. For example, "read" is a function that takes a string and converts it into some type (the type system is smart enough to figure out which one). In this case we convert it into a float.
{{Haskell/Example|The list elements and results can have different types|
<syntaxhighlight lang="haskell">
addStr :: String -> Float -> Float
addStr str x = read str + x
sumStr :: [String] -> Float
sumStr = foldr addStr 0.0</syntaxhighlight>
}}
There is also a variant called <code>foldr1</code> ("fold - R - one") which dispenses with an explicit "zero" for an accumulator by taking the last element of the list instead:
<syntaxhighlight lang="haskell">
foldr1 :: (a -> a -> a) -> [a] -> a
foldr1 f [x] = x
foldr1 f (x:xs) = f x (foldr1 f xs)
foldr1 _ [] = error "Prelude.foldr1: empty list"
</syntaxhighlight>
And <code>foldl1</code> as well:
<syntaxhighlight lang="haskell">
foldl1 :: (a -> a -> a) -> [a] -> a
foldl1 f [x] = x
foldl1 f (x:xs) = foldl f x xs
foldl1 _ [] = error "Prelude.foldl1: empty list"
</syntaxhighlight>
''Note: Just like for foldl, the Data.List library includes foldl1' as a strict version of foldl1.''
With foldl1 and foldr1, all the types have to be the same, and an empty list is an error. These variants are useful when there is no obvious candidate for the initial accumulator value and we are sure that the list is not going to be empty. When in doubt, stick with foldr or foldl'.
=== folds and laziness ===
One reason that right-associative folds are more natural in Haskell than left-associative ones is that right folds can operate on infinite lists. A fold that returns an infinite list is perfectly usable in a larger context that doesn't need to access the entire infinite result. In that case, foldr can move along as much as needed and the compiler will know when to stop. However, a left fold necessarily calls itself recursively until it reaches the end of the input list (because the recursive call is not made in an argument to f). Needless to say, no end will be reached if an input list to foldl is infinite.
As a toy example, consider a function <code>echoes</code> that takes a list of integers and produces a list such that wherever the number n occurs in the input list, it is replicated n times in the output list. To create our echoes function, we will use the prelude function <code>replicate</code> in which <code>replicate n x</code> is a list of length n with x the value of every element.
We can write echoes as a foldr quite handily:
<syntaxhighlight lang="haskell">
echoes :: [Int] -> [Int]
echoes = foldr (\ x xs -> (replicate x x) ++ xs) []
</syntaxhighlight>
<syntaxhighlight lang="haskell">
GHCi> take 10 (echoes [1..])
[1,2,2,3,3,3,4,4,4,4]
</syntaxhighlight>
(''Note:'' This definition is compact thanks to the <code>\ x xs -></code>
syntax. The <code>\</code>, meant to look like a lambda (λ), works as an
''unnamed'' function for cases where we won't use the function again anywhere
else. Thus, we provide the definition of our one-time function ''in situ''. In
this case, <code>x</code> and <code>xs</code> are the arguments, and the
right-hand side of the definition is what comes after the <code>-></code>.)
We could have instead used a foldl:
<syntaxhighlight lang="haskell">
echoes :: [Int] -> [Int]
echoes = foldl (\ xs x -> xs ++ (replicate x x)) []
</syntaxhighlight>
<syntaxhighlight lang="haskell">
GHCi> take 10 (echoes [1..]) -- not terminating
</syntaxhighlight>
but only the foldr version works on infinite lists. What would happen if you just evaluate
<code>echoes [1..]</code>? Try it! (If you try this in GHCi or a terminal, remember you can stop an evaluation with Ctrl-c, but you have to be quick and keep an eye on the system monitor or your memory will be consumed in no time and your system will hang.)
As a final example, <code>map</code> itself can be implemented as a fold:
<syntaxhighlight lang="haskell">
map :: (a -> b) -> [a] -> [b]
map f = foldr (\ x xs -> f x : xs) []
</syntaxhighlight>
Folding takes some time to get used to, but it is a fundamental pattern in functional programming and eventually becomes very natural. Any time you want to traverse a list and build up a result from its members, you likely want a fold.
{{Exercises|1=
#Define the following functions recursively (like the definitions for <code>sum</code>, <code>product</code> and <code>concat</code> above), then turn them into a fold:
#* <code>and :: [Bool] -> Bool</code>, which returns True if a list of Bools are all True, and False otherwise.
#* <code>or :: [Bool] -> Bool</code>, which returns True if any of a list of Bools are True, and False otherwise.
#Define the following functions using <code>foldl1</code> or <code>foldr1</code>:
#* <code>maximum :: Ord a => [a] -> a</code>, which returns the maximum element of a list (hint: <code>max :: Ord a => a -> a -> a</code> returns the maximum of two values).
#* <code>minimum :: Ord a => [a] -> a</code>, which returns the minimum element of a list (hint: <code>min :: Ord a => a -> a -> a</code> returns the minimum of two values).
#Use a fold (''which one?'') to define <code>reverse :: [a] -> [a]</code>, which returns a list with the elements in reverse order.
:Note that all of these are Prelude functions, so they will be always close at hand when you need them. (Also, that means you must use slightly different names in order to test your answers in GHCi.)
}}
== Scans ==
A "scan" is like a cross between a <code>map</code> and a fold. Folding a list accumulates a single return value, whereas mapping puts each item through a function returning a separate result for each item. A scan does both: it accumulates a value like a fold, but instead of returning only a final value it returns a list of all the intermediate values.
Prelude contains four scan functions:
<syntaxhighlight lang="haskell">
scanl :: (a -> b -> a) -> a -> [b] -> [a]
</syntaxhighlight>
<code>scanl</code> accumulates the list from the left, and the second argument becomes the first item in the resulting list. So, {{nowrap|1=<code>scanl (+) 0 [1,2,3] = [0,1,3,6]</code>}}.
<syntaxhighlight lang="haskell">
scanl1 :: (a -> a -> a) -> [a] -> [a]
</syntaxhighlight>
<code>scanl1</code> uses the first item of the list as a zero parameter. It is what you would typically use if the input and output items are the same type. Notice the difference in the type signatures between <code>scanl</code> and <code>scanl1</code>. {{nowrap|1=<code>scanl1 (+) [1,2,3] = [1,3,6]</code>}}.
<syntaxhighlight lang="haskell">
scanr :: (a -> b -> b) -> b -> [a] -> [b]
scanr (+) 0 [1,2,3] = [6,5,3,0]
scanr1 :: (a -> a -> a) -> [a] -> [a]
scanr1 (+) [1,2,3] = [6,5,3]
</syntaxhighlight>
These two functions are the counterparts of <code>scanl</code> and <code>scanl1</code> that accumulate the totals from the right.
{{Exercises|1=
# Write your own definition of <code>scanr</code>, first using recursion, and then using <code>foldr</code>. Do the same for <code>scanl</code> first using recursion then <code>foldl</code>.
# Define the following functions:
#*<code>factList :: Integer -> [Integer]</code>, which returns a list of factorials from 1 up to its argument. For example, <code>factList 4 = [1,2,6,24]</code>.
''More to be added''}}
==filter==
A common operation performed on lists is [[Wikipedia:Filter (mathematics)|filtering]] — generating a new list composed only of elements of the first list that meet a certain condition. A simple example: making a list of only even numbers from a list of integers.
<syntaxhighlight lang="haskell">
retainEven :: [Int] -> [Int]
retainEven [] = []
retainEven (n:ns) =
-- mod n 2 computes the remainder for the integer division of n by 2.
if (mod n 2) == 0
then n : (retainEven ns)
else retainEven ns
</syntaxhighlight>
This definition is somewhat verbose and specific. Prelude provides a concise and general <code>filter</code> function with type signature:
<syntaxhighlight lang="haskell">filter :: (a -> Bool) -> [a] -> [a]</syntaxhighlight>
So, a <code>(a -> Bool)</code> function tests an elements for some condition, we then feed in a list to be filtered, and we get back the filtered list.
To write <code>retainEven</code> using <code>filter</code>, we need to state the
condition as an auxiliary <code>(a -> Bool)</code> function, like this one:
<syntaxhighlight lang="haskell">
isEven :: Int -> Bool
isEven n = (mod n 2) == 0
</syntaxhighlight>
And then retainEven becomes simply:
<syntaxhighlight lang="haskell">
retainEven ns = filter isEven ns
</syntaxhighlight>
We used ns instead of xs to indicate that we know these are numbers and not just anything, but we can ignore that and use a more terse point-free definition:
<syntaxhighlight lang="haskell">
retainEven = filter isEven
</syntaxhighlight>
This is like what we demonstrated before for <code>map</code> and the folds. Like <code>filter</code>, those take another function as argument; and using them point-free emphasizes this "functions-of-functions" aspect.
==List comprehensions==
List comprehensions are syntactic sugar for some common list operations, such as filtering. For instance, instead of using the Prelude <code>filter</code>, we could write <code>retainEven</code> like this:
<syntaxhighlight lang="haskell">
retainEven es = [n | n <- es, isEven n]
</syntaxhighlight>
The compact syntax is actually very simple. It creates a new list based on the elements that pass a test - in this case is isEven. Broken down:
* The "n <- es" just means that we call the element of es being examined “n”. It’s an arbitrary variable name, we could have picked q or foo instead. The important thing to understand is that every element of the list is examined in turn.
* This is followed, after the comma, by a test - in this case <code>isEven n</code>.
* The part before | is the result that gets added to the new list if the test returns true. In this case it is n, but it doesn’t have to be - we could use eg n * n to get a list of the squares of the even numbers in es. If the test fails, nothing is added to the list.
Thus, if <code>es</code> is [1,2,3,4], then we would get back the list [2,4]. 1 and 3 were not drawn because <code>(isEven n) == False </code>.
If we want to use more tests, we just have to separate them with a comma. So to get that only even numbers larger than 100:
<syntaxhighlight lang="haskell">
retainLargeEvens :: [Int] -> [Int]
retainLargeEvens es = [n | n <- es, isEven n, n > 100]
</syntaxhighlight>
And again, <code>n</code> doesn’t have to be the result. We can use any expression at all before the vertical bar (if it is compatible with the type of the list, of course). For instance, if we wanted to subtract one from every even number, all it would take is:
<syntaxhighlight lang="haskell">
evensMinusOne es = [n - 1 | n <- es, isEven n]
</syntaxhighlight>
So the list comprehension syntax incorporates the
functionalities of <code>map</code> and <code>filter</code>.
To further sweeten things, the left arrow notation in list comprehensions can be combined with pattern matching. For example, suppose we had a list of <code>(Int, Int)</code> tuples, and we would like to construct a list with the first element of every tuple whose second element is even. Without pattern matching we might write
<syntaxhighlight lang="haskell">
firstForEvenSeconds :: [(Int, Int)] -> [Int]
firstForEvenSeconds ps = [fst p | p <- ps, isEven (snd p)] -- here, p is for pairs.
</syntaxhighlight>
But patterns make it much more readable:
<syntaxhighlight lang="haskell">
firstForEvenSeconds ps = [x | (x, y) <- ps, isEven y]
</syntaxhighlight>
Again, we’re free to write what we want before the <code>|</code>. If we wanted a list with the double of those first elements:
<syntaxhighlight lang="haskell">
doubleOfFirstForEvenSeconds :: [(Int, Int)] -> [Int]
doubleOfFirstForEvenSeconds ps = [2 * x | (x, y) <- ps, isEven y]
</syntaxhighlight>
Not counting spaces, that function code is shorter than its descriptive name!
We can also write a comprehension that works on more than one list - and put the lists inside the comprehension instead of making them parameters. Again we just have too separate them with commas - as long as the <- appears, Haskell will know they are not tests:
<syntaxhighlight lang="haskell">
allPairs :: [(Int, Int)]
allPairs = [(x, y) | x <- [1..4], y <- [5..8]]
</syntaxhighlight>
This comprehension draws from ''two'' lists, and generates all possible <code>(x, y)</code> pairs with the first element drawn from <code>[1..4]</code> and the second from <code>[5..8]</code>. In the final list of pairs, the first elements will be those generated with the first element of the first list (here, <code>1</code>), then those with the second element of the first list, and so on. In this example, the full list is (linebreaks added for clarity):
<pre>
Prelude> [(x, y) | x <- [1..4], y <- [5..8]]
[(1,5),(1,6),(1,7),(1,8),
(2,5),(2,6),(2,7),(2,8),
(3,5),(3,6),(3,7),(3,8),
(4,5),(4,6),(4,7),(4,8)]
</pre>
We could easily add a condition to restrict the combinations that go into the final list:
<syntaxhighlight lang="haskell">
somePairs = [(x, y) | x <- [1..4], y <- [5..8], x + y > 8]
</syntaxhighlight>
This list only has the pairs with the sum of elements larger than 8; starting with <code>(1,8)</code>, then <code>(2,7)</code> and so forth.
{{Exercises|1=
# Write a <code>returnDivisible :: Int -> [Int] -> [Int]</code> function which filters a list of integers retaining only the numbers divisible by the integer passed as first argument. For integers x and n, x is divisible by n if <code>(mod x n) == 0</code> (note that the test for evenness is a specific case of that).
#
# Write a function <code><nowiki>choosingTails :: [[Int]] -> [[Int]]</nowiki></code> using list comprehension syntax with appropriate "guards (filters)" for empty lists returning a list of tails following a head bigger than 5: <syntaxhighlight lang="haskell">
choosingTails [[7,6,3],[],[6,4,2],[9,4,3],[5,5,5]]
-- [[6,3],[4,2],[4,3]]
</syntaxhighlight>
#
# Does the order of guards matter? You may find it out by playing with the function of the preceding exercise.
#
# Over this section we've seen how list comprehensions are essentially syntactic sugar for <code>filter</code> and <code>map</code>. Now work in the opposite direction and define alternative versions of the <code>filter</code> and <code>map</code> using the list comprehension syntax.
#
# Rewrite <code>doubleOfFirstForEvenSeconds</code> using <code>filter</code> and <code>map</code> instead of list comprehension.
}}
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Elementary Haskell}}
{{BookCat}}
4i1gaml79cs56n6lh3fvdx9aq08sw3g
Haskell/More on functions
0
27127
4675950
4666184
2026-10-14T00:33:21Z
~2026-54868-50
3628373
4675950
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Elementary Haskell}}
Here are several nice features that make using functions easier.
== let and where revisited ==
As discussed in earlier chapters, <code>let</code> and <code>where</code> are useful in local function definitions. Here, <code>sumStr</code> calls <code>addStr</code> function:
<syntaxhighlight lang="haskell">
addStr :: Float -> String -> Float
addStr x str = x + read str
sumStr :: [String] -> Float
sumStr = foldl addStr 0.0
</syntaxhighlight>
But what if we never need <code>addStr</code> anywhere else? Then we could rewrite <code>sumStr</code> using local bindings. We can do that either with a <code>let</code> binding...
<syntaxhighlight lang="haskell">
sumStr =
let addStr x str = x + read str
in foldl addStr 0.0
</syntaxhighlight>
... or with a <code>where</code> clause...
<syntaxhighlight lang="haskell">
sumStr = foldl addStr 0.0
where addStr x str = x + read str
</syntaxhighlight>
... and the difference appears to be just a question of style: Do we prefer the bindings to come before or after the rest of the definition?
However, there is another important difference between <code>let</code> and <code>where</code>. The <code>let...in</code> construct is an expression just like if/then/else. In contrast, <code>where</code> clauses are like guards and so are not expressions. Thus, <code>let</code> bindings can be used within complex expressions:
<syntaxhighlight lang="haskell">
f x =
if x > 0
then (let lsq = (log x) ^ 2 in tan lsq) * sin x
else 0
</syntaxhighlight>
The expression within the outer parentheses is self-contained, and evaluates to the tangent of the square of the logarithm of <code>x</code>. Note that the scope of <code>lsq</code> does not extend beyond the parentheses, so changing the then-branch to
<syntaxhighlight lang="haskell">
then (let lsq = (log x) ^ 2 in tan lsq) * (sin x + lsq)
</syntaxhighlight>
does not work without dropping the parentheses around the <code>let</code>.
Despite not being full expressions, <code>where</code> clauses ''can'' be incorporated into <code>case</code> expressions:
<syntaxhighlight lang="haskell">
describeColour c =
"This colour "
++ case c of
Black -> "is black"
White -> "is white"
RGB red green blue -> " has an average of the components of " ++ show av
where av = (red + green + blue) `div` 3
++ ", yeah?"
</syntaxhighlight>
In this example, the indentation of the <code>where</code> clause sets the scope of the <code>av</code> variable so that it only exists as far as the <code>RGB red green blue</code> case is concerned. Placing it at the same indentation of the cases would make it available for all cases. Here is an example with guards:
<syntaxhighlight lang="haskell">
doStuff :: Int -> String
doStuff x
| x < 3 = report "less than three"
| otherwise = report "normal"
where
report y = "the input is " ++ y
</syntaxhighlight>
Note that since there is one equals sign for each guard there is no place we could put a <code>let</code> expression which would be in scope of all guards in the manner of the <code>where</code> clause. So this is a situation in which <code>where</code> is particularly convenient.
== Anonymous Functions - lambdas ==
Why create a formal name for a function like <code>addStr</code> when it only exists within another function's definition, never to be used again? Instead, we can make it an anonymous function also known as a "lambda function". Then, <code>sumStr</code> could be defined like this:
<syntaxhighlight lang="haskell">
sumStr = foldl (\ x str -> x + read str) 0.0
</syntaxhighlight>
The expression in the parentheses is a lambda function. The backslash is used as the nearest ASCII equivalent to the Greek letter lambda (λ). This lambda function takes two arguments, <code>x</code> and <code>str</code>, and it evaluates to "x + read str". So, the <code>sumStr</code> presented just above is precisely the same as the one that used <code>addStr</code> in a let binding.
Lambdas are handy for writing one-off functions to be used with maps, folds and their siblings, especially where the function in question is simple (beware of cramming complicated expressions in a lambda — it can hurt readability).
Since variables are being bound in a lambda expression (to the arguments, just like in a regular function definition), pattern matching can be used in them as well. A trivial example would be redefining <code>tail</code> with a lambda:
<syntaxhighlight lang="haskell">
tail' = (\ (_:xs) -> xs)
</syntaxhighlight>
Note: Since lambdas are a special character in Haskell, the <code>\</code> on its own will be treated as the function and whatever non-space character is next will be the variable for the first argument. It is still good form to put a space between the lambda and the argument as in normal function syntax (especially to make things clearer when a lambda takes more than one argument).
== Operators ==
In Haskell, any function that takes two arguments and has a name consisting entirely of non-alphanumeric characters is considered an ''operator''. The most common examples are the arithmetical ones like addition (+) and subtraction (-). Unlike other functions, operators are normally used infix (written between the two arguments). All operators can also be surrounded with parentheses and then used prefix like other functions:
<syntaxhighlight lang="haskell">
-- these are the same:
2 + 4
(+) 2 4
</syntaxhighlight>
We can define new operators in the usual way as other functions — just don't use any alphanumeric characters in their names. For example, here's the set-difference definition from <code>Data.List</code>:
<syntaxhighlight lang="haskell">
(\\) :: (Eq a) => [a] -> [a] -> [a]
xs \\ ys = foldl (\zs y -> delete y zs) xs ys
</syntaxhighlight>
As the example above shows, operators can be defined infix as well. The same definition written as prefix also works:
<syntaxhighlight lang="haskell">
(\\) xs ys = foldl (\zs y -> delete y zs) xs ys
</syntaxhighlight>
Note that the type declarations for operators have no infix version and must be written with the parentheses.
=== Sections ===
''Sections'' are a nifty piece of syntactical sugar that can be used with operators. An operator within parentheses and flanked by one of its arguments...
<syntaxhighlight lang="haskell">
(2+) 4
(+4) 2
</syntaxhighlight>
... is a new function in its own right. <code>(2+)</code>, for instance, has the type <code>(Num a) => a -> a</code>. We can pass sections to other functions, e.g. <code>map (+2) [1..4] == [3..6]</code>. For another example, we can add an extra flourish to the <code>multiplyList</code> function we wrote back in [[../Lists II|Lists II]]:
<syntaxhighlight lang="haskell">
multiplyList :: Integer -> [Integer] -> [Integer]
multiplyList m = map (m*)
</syntaxhighlight>
If you have a "normal" prefix function and want to use it as an operator, simply surround it with backticks:
<syntaxhighlight lang="haskell">
1 `elem` [1..4]
</syntaxhighlight>
This is called making the function ''infix''. It's normally done for readability purposes: <code>1 `elem` [1..4]</code> reads better than <code>elem 1 [1..4]</code>. You can also define functions infix:
<syntaxhighlight lang="haskell">
elem :: (Eq a) => a -> [a] -> Bool
x `elem` xs = any (==x) xs
</syntaxhighlight>
But once again notice that the type signature stays with the prefix style.
Sections even work with infix functions:
<syntaxhighlight lang="haskell">
(1 `elem`) [1..4]
(`elem` [1..4]) 1
</syntaxhighlight>
Of course, remember that you can only make binary functions (that is, those that take two arguments) infix.
{{Exercises|1=
* Lambdas are a nice way to avoid defining unnecessary separate functions. Convert the following let- or where-bindings to lambdas:
** <code>map f xs where f x = x * 2 + 3</code>
** <code>let f x y = read x + y in foldr f 1 xs</code>
* Sections are just syntactic sugar for lambda operations. I.e. <code>(+2)</code> is equivalent to <code>\x -> x + 2</code>. What would the following sections 'desugar' to? What would be their types?
** <code>(4+)</code>
** <code>(1 `elem`)</code>
** <code>(`notElem` "abc")</code>
}}
{{Haskell/Navigation|chapter=Elementary Haskell}}
{{BookCat}}
f32r0afh1fid2wvosq78k2rgc3igx9m
Radiation Oncology/Rectum/NSABP trials
0
35665
4675996
4092897
2026-10-14T09:30:09Z
Jcb
90773
4675996
wikitext
text/x-wiki
{{Radiation Oncology:TOC}}
[[Radiation Oncology/Rectum]]
The '''National Surgical Adjuvant Breast and Bowel Project''' ('''NSABP'''):
See other [[Radiation Oncology/NSABP|NSABP trials]] and NSABP [[Radiation Oncology/Colon/NSABP trials|Colon trials]]
<br>See the [http://www.nsabp.pitt.edu/ NSABP web page].
*'''R-01''' (1977-86) - Dukes' B and C. After resection, randomized to observation, MOF chemotherapy, or RT.
**'''Results 1988''': {{PMID|3276900}}
**{{PMID|3532972}} (1986 - "An analysis of survival and treatment failure following abdominoperineal and sphincter-saving resection in Dukes' B and C rectal carcinoma.")
**{{PMID|3516601}} (1986 - "A comparison of stapled and handsewn anastomoses in patients undergoing resection for Dukes' B and C colorectal cancer.")
**{{PMID|3511864}} [Full text at PMC] - NSABP C-01 and R-01 - (1986 - "The prognostic value of the modifications of the Dukes' C class of colorectal cancer.")
**{{PMID|6722730}} (1984 - "The relationship of depth of penetration and tumor size to the number of positive nodes in Dukes C colorectal cancer.")
**{{PMID|6337699}} (1983 - "Tumor size and regional lymph node metastasis in colorectal cancer. A preliminary analysis from the NSABP clinical trials.")
*'''R-02''' (1987-92) - Dukes' B and C. Randomized to post-op chemo/RT or post-op chemotherapy alone.
**2000: {{PMID|10699069}} - Post op chemo/RT did not improve DFS or OS. 5-FU/LV chemo was superior to MOF (a second randomization).
*'''R-03''' (1993-99) - {{PMID|19770376}} [http://jco.ascopubs.org/cgi/reprint/27/31/5124 Full text] — "Preoperative multimodality therapy improves disease-free survival in patients with carcinoma of the rectum: NSABP R-03." Roh M et al. J Clin Oncol. 2009 Nov 1;27(31):5124-30. Epub 2009 Sep 21.
**Trial closed due to poor accrual - intended sample size was 900 patients. Results analyzed as below.
**267 pts. with T3-T4 or N+ rectal cancer. Randomized to preoperative or postoperative chemoradiotherapy (45 Gy in 25 fx with 5.4 Gy boost, chemo consisting of 5-FU and leucovorin).
**5-year DFS was improved for pre-op over post-op (64.7% v 53.4%, p=0.011). Nonsignificant trend in 5-year OS (74.5% v 65.6%, p=0.065). No difference in locoregional recurrence, 10.7% in each group.
**Conclusion: Pre-op chemoradiotherapy, compared with post-op chemoradiotherapy, significantly improved DFS and showed a trend toward improved OS.
*'''R-04''' (2004- 2010) - pre-operative chemo/RT with continuous infusion 5-FU vs Capecitabine (Xeloda) vs Capecitabine +Oxaliplatin vs 5-FU + Oxaliplatin
** Abstract ASCO 2011 [http://www.asco.org/ascov2/Meetings/Abstracts?&vmview=abst_detail_view&confID=102&abstractID=76910]
** 1608 pts. with clinical stage II or III rectal cancer, pre-operative chemo/RT (45 Gy in 25 fx with 5.4 -10.8 Gy boost), 4 arm randomization to chemo with arm A) 5-FU (CVI 225mg/m2 5 days/wk) arm B) 5-FU + Oxaliplatin (50mg/m2/wk x 5) arm C) Capecitabine (825 mg/m2 BID 5 days/wk) arm D) Capecitabine + Oxaliplatin
** Endpoints: complete pathologic response (pCR), sphincter-saving surgery (SSS), surgical downstaging (SD, conversion to SSS).
** pCR 5-FU +/-OX 18.8 % vs. CAPE +/-OX 22.2 % (NS), SSS 61.2 % vs. 62.7 % (NS), SD 20.7 % vs. 23.0 % (NS), grade 3/4 diarrhoe{{typo help inline|reason=similar to diarrhoea|date=August 2022}} 11.2 % vs. 10.8 % (NS)
** pCR (5-FU or CAPE) No OX 19.1 % vs. (5-FU or CAPE) + OX 20.9 % (NS), SSS 63.6 % vs. 60.4 % (NS), SD 23.0 % vs. 19.2 % (NS), grade 3/4 diarrhoe{{typo help inline|reason=similar to diarrhoea|date=August 2022}} 6.6 % vs. 15.4 % (SS)
** Conclusion: no significant differences in pCR, SSS, SD between groups with 5-FU and Capecitabine or between groups with or without Oxaliplatin, but increased grade 3/4 gastrointestinal toxicity with addition of Oxaliplatin
** 2014 GI symposium presentation [http://meetinglibrary.asco.org/content/123227-143]: Standard of care should be Capecitabine + 50-55.8 Gy Radiation preoperatively. No benefit seen with addition of Oxaliplatin.
ozl80vmuayk6hgqg94zd58g7sls5jqi
LaTeX/Tables
0
42436
4675965
4675624
2026-10-14T03:22:11Z
SneaselxLv94
3189883
LaTeX Example added
4675965
wikitext
text/x-wiki
<noinclude>{{LaTeX/Top}}
</noinclude>
Tables are a common feature in academic writing, often used to summarize research results. Mastering the art of table construction in LaTeX is therefore necessary to produce quality papers and with sufficient practice one can print beautiful tables of any kind.
Keeping in mind that LaTeX is not a spreadsheet; it makes sense to use a dedicated tool to build tables and then to export these tables into the document. Basic tables are not too taxing, but anything more advanced can take a fair bit of construction; in these cases, more advanced packages can be very useful. However, first it is important to know the basics. Once you are comfortable with basic LaTeX tables, you might have a look at more advanced packages or the [[#Using spreadsheets and data analysis tools|export options of your favorite spreadsheet]]. Thanks to the modular nature of LaTeX, the whole process can be automated in a fairly comfortable way.
== Introduction ==
LaTeX has built-in support to typeset tables and provides two environments: {{LaTeX/Environment|tabular}} and {{LaTeX/Environment|table}}. To typeset material in rows and columns, the {{LaTeX/Environment|tabular}} environment is needed; the optional {{LaTeX/Environment|table}} environment is a container for floating material similar to {{LaTeX/Environment|figure}}, into which a {{LaTeX/Environment|tabular}} environment may be included.
The {{LaTeX/Environment|table}} environment contains the caption and defines the float for the table, i.e., where in the document the table should be positioned and whether we want it to be displayed centered. The {{LaTeX/Inline|code=\caption}} and {{LaTeX/Inline|code=\label}} commands can be used in the same way as for pictures. For more information about the {{LaTeX/Environment|table}} environment, see the [[#Floating with table|Floating with ''table'']] section.
In any case, the actual content of the table is contained within the {{LaTeX/Environment|tabular}} environment.
== The ''tabular'' environment ==
The {{LaTeX/Environment|tabular}} environment can be used to typeset tables with optional horizontal and vertical lines. LaTeX determines the width of the columns automatically.
The first line of the environment has the form:
{{LaTeX/Usage|code=
\begin{tabular}[pos]{table spec}
}}
The {{LaTeX/Parameter|table spec}} argument tells LaTeX the alignment to be used in each column and the vertical lines to insert.
The number of columns does not need to be specified as it is inferred by looking at the number of arguments provided. It is also possible to add vertical lines between the columns here. The following symbols are available to describe the table columns (some of them require that the package {{LaTeX/Package|array}} has been loaded):
{| class="wikitable"
| {{LaTeX/Parameter|l}}
| left-justified column
|-
| {{LaTeX/Parameter|c}}
| centered column
|-
| {{LaTeX/Parameter|r}}
| right-justified column
|-
| {{LaTeX/Parameter|p{'width'}<!---->}}
| paragraph column with text vertically aligned at the top
|-
| {{LaTeX/Parameter|m{'width'}<!---->}}
| paragraph column with text vertically aligned in the middle (requires array package)
|-
| {{LaTeX/Parameter|b{'width'}<!---->}}
| paragraph column with text vertically aligned at the bottom (requires array package)
|-
| <code><nowiki>|</nowiki></code>
| vertical line
|-
| <code><nowiki>||</nowiki></code>
| double vertical line
|}
By default, if the text in a column is too wide for the page, LaTeX won’t automatically wrap it. Using {{LaTeX/Parameter|p{'width'}<!---->}} you can define a special type of column which will wrap-around the text as in a normal paragraph. You can pass the width using any unit supported by LaTeX, such as 'pt' and 'cm', or ''command lengths'', such as {{LaTeX/LaTeX|code=\textwidth<!---->}}. You can find a list in chapter [[LaTeX/Lengths|Lengths]].
The optional parameter {{LaTeX/Parameter|pos}} can be used to specify the vertical position of the table relative to the baseline of the surrounding text. In most cases, you will not need this option. It becomes relevant only if your table is not in a paragraph of its own. You can use the following letters:
{| class="wikitable"
|-
| {{LaTeX/Parameter|b}}
| bottom
|-
| {{LaTeX/Parameter|c}}
| center (default)
|-
| {{LaTeX/Parameter|t}}
| top
|-
|}
To specify a font format (such as bold, italic, etc.) for an entire column, you can add {{LaTeX/LaTeX|code=>{\format}<!---->}} before you declare the alignment. For example {{LaTeX/LaTeX|code=\begin{tabular}{ >{\bfseries}l c >{\itshape}r }<!---->}} will indicate a three column table with the first one aligned to the left and in bold font, the second one aligned in the center and with normal font, and the third aligned to the right and in italic. The "array" package needs to be activated in the preamble for this to work.
In the first line you have pointed out how many columns you want, their alignment and the vertical lines to separate them. Once in the environment, you have to introduce the text you want, separating between cells and introducing new lines. The commands you have to use are the following:
{| class="wikitable"
| {{LaTeX/LaTeX|code=&<!---->}}
| column separator
|-
| {{LaTeX/LaTeX|code=\\<!---->}}
| start new row (additional space may be specified after {{LaTeX/LaTeX|code=\\<!---->}} using square brackets, such as {{LaTeX/Parameter|\\[6pt]}})
|-
| {{LaTeX/LaTeX|code=\hline<!---->}}
| horizontal line
|-
| {{LaTeX/LaTeX|code=\newline<!---->}}
| start a new line within a cell (in a paragraph column)
|-
| {{LaTeX/LaTeX|code=\cline{i-j}<!---->}}
| partial horizontal line beginning in column ''i'' and ending in column ''j''
|}
Note, any white space inserted between these commands is purely down to one's preferences. I personally add spaces between to make it easier to read.
=== Basic examples ===
This example shows how to create a simple table in LaTeX. It is a three-by-three table, but without any lines.
{{LaTeX/Example|code=
\begin{tabular}{ l c r }
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{tabular}
|render=
<math>\begin{array}{lcr} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{array}</math>
}}
Expanding upon that by including some vertical lines:
{{LaTeX/Example|code=
\begin{tabular}{ l {{!}} c {{!}} r }
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\end{tabular}
|render=
<math>\begin{array}{l|c||r} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{array}</math>
}}
To add horizontal lines to the very top and bottom edges of the table:
{{LaTeX/Example|code=
\begin{tabular}{ l {{!}} c {{!}} r }
\hline
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 \\
\hline
\end{tabular}
|render=
<math>\begin{array}{l|c||r}\hline 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \hline \end{array}</math>
}}
And finally, to add lines between all rows, as well as centering (notice the use of the center environment - of course, the result of this is not obvious from the preview on this web page):
{{LaTeX/Example|code=
\begin{center}
\begin{tabular}{ l {{!}} c {{!}} r }
\hline
1 & 2 & 3 \\ \hline
4 & 5 & 6 \\ \hline
7 & 8 & 9 \\
\hline
\end{tabular}
\end{center}
|render=
<math>\begin{array}{l|c|r}\hline 1 & 2 & 3 \\ \hline 4 & 5 & 6 \\ \hline 7 & 8 & 9 \\ \hline \end{array}</math>
}}
{{LaTeX/Example|code=
\begin{center}
\begin{tabular}{ {{!}} l {{!}} c {{!}} r {{!}} }
\hline
1 & 2 & 3 \\ \hline
4 & 5 & 6 \\ \hline
7 & 8 & 9 \\
\hline
\end{tabular}
\end{center}
|render=
<math>\begin{array}{|l|c|r|}\hline 1 & 2 & 3 \\ \hline 4 & 5 & 6 \\ \hline 7 & 8 & 9 \\ \hline \end{array}</math>
}}
{{LaTeX/Example|code=
\begin{tabular}{{{!}}r{{!}}l{{!}}}
\hline
7C0 & hexadecimal \\
3700 & octal \\ \cline{2-2}
11111000000 & binary \\
\hline \hline
1984 & decimal \\
\hline
\end{tabular}
|render=
{{Dark mode invert|[[Image:Latex example tabular cline.svg|250px]]}}
}}
=== Text wrapping in tables ===
LaTeX's algorithms for formatting tables have a few shortcomings. One is that it will not automatically wrap text in cells, even if it overruns the width of the page. For columns that will contain text whose length exceeds the column's desired width, it is recommended that you use the {{LaTeX/Parameter|p}} attribute and specify the desired width of the column (although it may take some trial-and-error to get the result you want). For a more convenient method, have a look at [[#The tabularx package|The tabularx package]], or [[#The tabulary package|The tabulary package]].
Instead of {{LaTeX/Parameter|p}}, use the {{LaTeX/Parameter|m}} attribute to have the lines aligned toward the middle of the box or the {{LaTeX/Parameter|b}} attribute to align along the bottom of the box.
Here is a simple example. The following code creates two tables with the same code; the only difference is that the last column of the second one has a defined width of 5 centimeters, while in the first one we didn't specify any width. Compiling this code:
{{LaTeX/Usage|code=
\documentclass{article}
\usepackage[english]{babel}
\begin{document}
Without specifying width for last column:
\begin{center}
\begin{tabular}{{{!}} l {{!}} l {{!}} l {{!}} l {{!}}}
\hline
Day & Min Temp & Max Temp & Summary \\ \hline
Monday & 11C & 22C & A clear day with lots of sunshine.
However, the strong breeze will bring down the temperatures. \\ \hline
Tuesday & 9C & 19C & Cloudy with rain, across many northern regions. Clear spells
across most of Scotland and Northern Ireland,
but rain reaching the far northwest. \\ \hline
Wednesday & 10C & 21C & Rain will still linger for the morning.
Conditions will improve by early afternoon and continue
throughout the evening. \\
\hline
\end{tabular}
\end{center}
With width specified:
\begin{center}
\begin{tabular}{ {{!}} l {{!}} l {{!}} l {{!}} p{5cm} {{!}}}
\hline
Day & Min Temp & Max Temp & Summary \\ \hline
Monday & 11C & 22C & A clear day with lots of sunshine.
However, the strong breeze will bring down the temperatures. \\ \hline
Tuesday & 9C & 19C & Cloudy with rain, across many northern regions. Clear spells
across most of Scotland and Northern Ireland,
but rain reaching the far northwest. \\ \hline
Wednesday & 10C & 21C & Rain will still linger for the morning.
Conditions will improve by early afternoon and continue
throughout the evening. \\
\hline
\end{tabular}
\end{center}
\end{document}
}}
You get the following output:
{{Dark mode invert|[[Image:Latex example wrapped table.svg|800px|center]]}}
Note that the first table has been cropped, since the output is wider than the page width.
=== Manually broken paragraphs in table cells ===
Sometimes it is necessary to not rely on the breaking algorithm when using the {{LaTeX/Parameter|p}} specifier, but rather specify the line breaks by hand. In this case it is easiest to use a {{LaTeX/LaTeX|code=\parbox<!---->}}:
{{LaTeX/Usage|code=
\begin{tabular}{cc}
boring cell content & \parbox[t]{5cm}{rather long par\\new par}
\end{tabular}
}}
Here the {{LaTeX/Parameter|t}} argument controls the placement of the text inside the box. Other allowed values are {{LaTeX/Parameter|c}} for center and {{LaTeX/Parameter|b}} for bottom.
=== Space between columns ===
To tweak the space between columns (LaTeX will by default choose very tight columns), one can alter the column separation: {{LaTeX/LaTeX|code=\setlength{\tabcolsep}{5pt}<!---->}}.
The default value is 6pt.
One can also introduce a horizontal space with hspace like this: {{LaTeX/LaTeX|code=\begin{tabular}{r@{\hspace{1in}<!---->}<!---->rr}<!---->}} There are different options for the hspace [[LaTeX/Lengths|length]].
=== Space between rows ===
Re-define the {{LaTeX/LaTeX|code=\arraystretch<!---->}} command to set the space between rows:
{{LaTeX/Usage|code=
\renewcommand{\arraystretch}{1.5}
}}
Default value is 1.0.
An alternative way to adjust the rule spacing is to add {{LaTeX/LaTeX|code=\noalign{\smallskip}<!---->}} before or after the {{LaTeX/LaTeX|code=\hline<!---->}} and {{LaTeX/LaTeX|code=\cline{i-j}<!---->}} commands:
{{LaTeX/Usage|code=
\begin{tabular}{ {{!}} l {{!}} l {{!}} r {{!}} }
\hline\noalign{\smallskip}
\multicolumn{2}{c}{Item} \\
\cline{1-2}\noalign{\smallskip}
Animal & Description & Price (\$) \\
\noalign{\smallskip}\hline\noalign{\smallskip}
Gnat & per gram & 13.65 \\
& each & 0.01 \\
Gnu & stuffed & 92.50 \\
Emu & stuffed & 33.33 \\
Armadillo & frozen & 8.99 \\
\noalign{\smallskip}\hline
}}
You may also specify the skip after a line explicitly using glue after the line terminator
{{LaTeX/Example|code=
\begin{tabular}{{{!}} l {{!}} l {{!}}}
\hline
Mineral & Color \\[1cm]
Ruby & Red \\
Sapphire & Blue \\
\hline
\end{tabular}
|render=
<math>\begin{array}{|l|l|}\hline Mineral & Color \\[1cm] Ruby & Red \\ Saphhire & Blue \\ \hline \end{array}</math>
}}
=== Other environments inside tables ===
If you use some LaTeX environments inside table cells, like {{LaTeX/Environment|verbatim}} or {{LaTeX/Environment|enumerate}}:
{{LaTeX/Usage|code=
\begin{tabular}{c c}
\hline
\begin{verbatim}
code
\end{verbatim}
& description
\\ \hline
\end{tabular}
}}
you might encounter errors similar to
<syntaxhighlight lang="output">
! LaTeX Error: Something's wrong--perhaps a missing \item.
</syntaxhighlight>
To solve this problem, change [[#The tabular environment|column specifier]] to "paragraph" ({{LaTeX/Parameter|p}}, {{LaTeX/Parameter|m}} or {{LaTeX/Parameter|b}}).
{{LaTeX/Usage|code=
\begin{tabular}{m{5cm} c}
}}
=== Defining multiple columns ===
It is possible to define many identically aligned columns at once using the {{LaTeX/LaTeX|code=*{num}{str}<!---->}} syntax. This is particularly useful when your table has many columns.
Here is a table with six centered columns flanked by a single column on each side:
{{LaTeX/Example|code=
\begin{tabular}{l*{6}{c}r}
Team & P & W & D & L & F & A & Pts \\
\hline
Manchester United & 6 & 4 & 0 & 2 & 10 & 5 & 12 \\
Celtic & 6 & 3 & 0 & 3 & 8 & 9 & 9 \\
Benfica & 6 & 2 & 1 & 3 & 7 & 8 & 7 \\
FC Copenhagen & 6 & 2 & 1 & 3 & 5 & 8 & 7 \\
\end{tabular}
|render=
{{Dark mode invert|[[Image:Latex example defining multiple columns.svg|450px]]}}
}}
=== Column specification using <code>>{\cmd}</code> and <code><{\cmd}</code> ===
The column specification can be altered using the {{LaTeX/Package|array}} package. This is done in the
argument of the tabular environment using {{LaTeX/LaTeX|code=>{\command}}} for commands executed right
''before'' each column element and {{LaTeX/LaTeX|code=<{\command}}} for commands to be executed right
''after'' each column element.
As an example: to get a column in math mode enter: <syntaxhighlight lang="tex" inline>\begin{tabular}{>{$}c<{$}}</syntaxhighlight>.
Another example is changing the font: {{LaTeX/LaTeX|code=\begin{tabular}{>{\small}c}|}} to print the column in a small font.
The argument of the {{LaTeX/LaTeX|code=>|}} and {{LaTeX/LaTeX|code=<|}} specifications must be correctly balanced when it comes to {{LaTeX/LaTeX|code={|}} and {{LaTeX/LaTeX|code=}|}} characters. This means that {{LaTeX/LaTeX|code=>{\bfseries}|}} is valid, while {{LaTeX/LaTeX|code=>{\textbf}|}} will not work and <code>{\textbf{}}</code> is not valid. If there is the need to use the text of the table as an argument (for instance, using the {{LaTeX/LaTeX|code=\textbf|}} to produce bold text), one should use the {{LaTeX/LaTeX|code=\bgroup|}} and {{LaTeX/LaTeX|code=\egroup|}} commands: {{LaTeX/LaTeX|code=>{\textbf\bgroup}c<{\egroup}|}} produces the intended effect. This works only for some basic LaTeX commands. For other commands, such as {{LaTeX/LaTeX|code=\underline|}} to underline text, it is necessary to temporarily store the column text in a box using {{LaTeX/LaTeX|code=lrbox|}}. First, you must define such a box with {{LaTeX/LaTeX|code=\newsavebox{\boxname}|}} and then you can define:
{{LaTeX/Usage|code=
>{\begin{lrbox}{\boxname} }%
l%
<{\end{lrbox}%
\underline{\unhbox\boxname} }%
}
}}
This stores the text in a box and afterwards, takes the text out of the box with {{LaTeX/LaTeX|code=\unhbox|}} (this destroys the box, if the box is needed again one should use {{LaTeX/LaTeX|code=\unhcopy|}} instead) and passing it to {{LaTeX/LaTeX|code=\underline|}}. (For LaTeX2e, you may want to use {{LaTeX/LaTeX|code=\usebox{\boxname}|}} instead of {{LaTeX/LaTeX|code=\unhbox\boxname|}}.)
This same trick done with {{LaTeX/LaTeX|code=\raisebox|}} instead of {{LaTeX/LaTeX|code=\underline|}} can force all lines in a table to have equal height, instead of the natural varying height that can occur when e.g. math terms or superscripts occur in the text.
Here is an example showing the use of both {{LaTeX/LaTeX|code=p{...}|}} and {{LaTeX/LaTeX|code=>{\centering}|}} :
<syntaxhighlight lang="tex">
\begin{tabular}{>{\centering}p{3.5cm}>{\centering}p{3.5cm} }
Geometry & Algebra
\tabularnewline
\hline
Points & Addition
\tabularnewline
Spheres & Multiplication
\end{tabular}
</syntaxhighlight>
Note the use of {{LaTeX/LaTeX|code=\tabularnewline|}} instead of {{LaTeX/LaTeX|code=\\|}} to avoid a <samp>Misplaced \noalign</samp> error.
=== @ and ! expressions ===
The column separator can be specified with the {{LaTeX/LaTeX|code=@{...}<!---->}} or {{LaTeX/LaTeX|code=!{...}<!---->}} constructs.
It typically takes some text as its argument, and when appended to a column, it will automatically insert that text into each cell in that column before the actual data for that cell. The {{LaTeX/LaTeX|code=@{...}<!---->}} command kills the inter-column space and replaces it with whatever is between the curly braces. To keep the initial space, use {{LaTeX/LaTeX|code=!{...}<!---->}}. To add space, use {{LaTeX/LaTeX|code=@{\hspace{''width''}<!---->}<!---->}}.
Admittedly, this is not that clear, and so will require a few examples to clarify. Sometimes, it is desirable in scientific tables to have the numbers aligned on the decimal point. This can be achieved by doing the following:
{{LaTeX/Example|code=
\begin{tabular}{r@{.}l}
3 & 14159 \\
16 & 2 \\
123 & 456 \\
\end{tabular}
|render=
<math>\begin{align}3&.14159\\16&.2\\123&.456\end{align}</math>
}}
The space-suppressing qualities of the @-expression actually make it quite useful for manipulating the horizontal spacing between columns. Given a basic table, and varying the column descriptions:
{{LaTeX/Usage|code=
\begin{tabular}{ {{!}}l{{!}}l{{!}} }
\hline
stuff & stuff \\ \hline
stuff & stuff \\
\hline
\end{tabular}
}}
{|
| style="vertical-align: middle;" | <code><nowiki>{|l|l|}</nowiki></code>
| style="vertical-align: middle;" |
{{Dark mode invert|[[Image:specifier1.svg]]}}
|-
| style="vertical-align: middle;" | <code><nowiki>{|@{}l|l@{}|}</nowiki></code>
| style="vertical-align: middle;" |
{{Dark mode invert|[[Image:specifier2.svg]]}}
|-
| style="vertical-align: middle;" | <code><nowiki>{|@{}l@{}|l@{}|}</nowiki></code>
| style="vertical-align: middle;" |
{{Dark mode invert|[[Image:specifier3.svg]]}}
|-
| style="vertical-align: middle;" | <code><nowiki>{|@{}l@{}|@{}l@{}|}</nowiki></code>
| style="vertical-align: middle;" |
{{Dark mode invert|[[Image:specifier4.svg]]}}
|}
=== Aligning columns at decimal points using dcolumn ===
Instead of using @-expressions to build columns of decimals aligned to the decimal point (or equivalent symbol), it is possible to center a column on the decimal separator using the {{LaTeX/Package|dcolumn}} package, which provides a new column specifier for floating point data. See the [http://anorien.csc.warwick.ac.uk/mirrors/CTAN/macros/latex/required/tools/dcolumn.pdf dcolumn package documentation] for more information, but a simple way to use {{LaTeX/Package|dcolumn}} is as follows.
{{LaTeX/Example|code=
\usepackage{dcolumn}
\ldots
\newcolumntype{d}[1]{D{.}{\cdot}{#1} }
%the argument for d specifies the maximum number of decimal places
\begin{tabular}{l r c d{1} }
Left&Right&Center&\mathrm{Decimal}\\
1&2&3&4\\
11&22&33&44\\
1.1&2.2&3.3&4.4\\
\end{tabular}
|render={{Dark mode invert|[[File:LaTeX_example_dcolumn.png|200px]]}}
}}
A negative argument provided for the number of decimal places in the new column type allows unlimited decimal places, but may result in rather wide columns. Rounding is not applied, so the data to be tabulated should be adjusted to the number of decimal places specified. Note that a decimal aligned column is typeset in math mode, hence the use of \mathrm for the column heading in the example above. Also, text in a decimal aligned column (for example the header) will be right-aligned before the decimal separator (assuming there's no decimal separator in the text). While this may be fine for very short text, or numeric column headings, it looks cumbersome in the example above. A solution to this is to use the {{LaTeX/LaTeX|code=\multicolumn}} command described below, specifying a single column and its alignment. For example to center the header ''Decimal'' over its column in the above example, the first line of the table itself would be {{LaTeX/LaTeX|code=Left&Right&Center&\multicolumn{1}{c}{Decimal}\\}}
====Bold text and dcolumn====
To draw attention to particular entries in a table, it may be nice to use bold text. Ordinarily this is easy, but as dcolumn needs to ''see'' the decimal point it is rather harder to do. In addition, the usual bold characters are wider than their normal counterparts, meaning that although the decimals may align nicely, the figures (for more than 2--3 digits on one side of the decimal point) will be visibly misaligned. It is however possible to use normal width bold characters and define a new bold column type, as shown below.<ref>{{cite web|url=http://tex.stackexchange.com/questions/118458/decimals-in-table-dont-align-with-dcolumn-when-bolded|title=Decimals in table don't align with dcolumn when bolded|author=D Carlisle|publisher=Stackexchange}}</ref>
{{LaTeX/Example|code=
\usepackage{dcolumn}
%here we're setting up a version of the math fonts with normal x-width
\DeclareMathVersion{nxbold}
\SetSymbolFont{operators}{nxbold}{OT1}{cmr} {b}{n}
\SetSymbolFont{letters} {nxbold}{OML}{cmm} {b}{it}
\SetSymbolFont{symbols} {nxbold}{OMS}{cmsy}{b}{n}
\begin{document}
\makeatletter
\newcolumntype{d}{D{.}{.}{-1} } %decimal column as before
%wide bold decimal column
\newcolumntype{B}[3]{>{\boldmath\DC@{#1}{#2}{#3} }c<{\DC@end} }
%normal width bold decimal column
\newcolumntype{Z}[3]{>{\mathversion{nxbold}\DC@{#1}{#2}{#3} }c<{\DC@end} }
\makeatother
\begin{tabular}{l l d}
Type &M & \multicolumn{1}{c}{N} \\
Normal & 1 & 22222.222 \\
Bold (standard)&10 & \multicolumn{1}{B{.}{.}{-1} }{22222.222}\\
Bold (nxbold)&100 & \multicolumn{1}{Z{.}{.}{-1} }{22222.222}\\
\end{tabular}
\end{document}
|render={{Dark mode invert|[[file:LaTeX example dcolumn bold.png|200px]]}}
}}
== Row specification ==
It might be convenient to apply the same command over every cell of a row, just as for column. Unfortunately the {{LaTeX/Environment|tabular}} environment cannot do that by default.
We will need {{LaTeX/Package|tabu}} instead, which provides the {{LaTeX/LaTeX|code=\rowfont<!---->}} option.
{{LaTeX/Usage|code=
\begin{tabu}{XX}
\rowfont{\bfseries\itshape\large} Header1 & Header2 \\
\hline
Cell2 & Cell2
\end{tabu}
}}
== Spanning ==
To complete this tutorial, we take a quick look at how to generate slightly more complex tables. Unsurprisingly, the commands necessary have to be embedded within the table data itself.
=== Rows spanning multiple columns ===
The command for this looks like this: {{LaTeX/LaTeX|code=\multicolumn{num_cols}{alignment}{contents}<!---->}}. {{LaTeX/Parameter|num_cols}} is the number of subsequent columns to merge; {{LaTeX/Parameter|alignment}} is either {{LaTeX/Parameter|l}}, {{LaTeX/Parameter|c}}, {{LaTeX/Parameter|r}}, or to have text wrapping specify a width {{LaTeX/LaTeX|code=p{5.0cm}<!---->}} . And {{LaTeX/Parameter|contents}} is simply the actual data you want to be contained within that cell. You can also use {{LaTeX/LaTeX|code=\multicolumn{1}{alignment}{contents}<!---->}} for a single column. In this simple example, the name David Batty is an exception, shifted to the right:
{{LaTeX/Example|code=
\begin{tabular}{ {{!}}l{{!}}l{{!}} }
\hline
\multicolumn{2}{{{!}}c{{!}}}{Team sheet} \\
\hline
GK & Paul Robinson \\
LB & Lucas Radebe \\
DC & Michael Duberry \\
DC & Dominic Matteo \\
RB & Dider Domi \\
MC & \multicolumn{1}{r{{!}}}{David Batty} \\
MC & Eirik Bakke \\
MC & Jody Morris \\
FW & Jamie McMaster \\
ST & Alan Smith \\
ST & Mark Viduka \\
\hline
\end{tabular}
|render=
{{Dark mode invert|[[Image:multicolumn.svg]]}}
}}
=== Columns spanning multiple rows ===
The first thing you need to do is add {{LaTeX/LaTeX|code=\usepackage{multirow}|}} to the preamble<ref name="multirow">Package multirow [http://www.ctan.org/tex-archive/macros/latex/contrib/multirow/ on CTAN]</ref>. This then provides the command needed for spanning rows: <code>\multirow{''num_rows''}{''width''}{''contents''}</code>. The arguments are pretty simple to deduce ({{LaTeX/LaTeX|code=*<!---->}} for the ''width'' means the content's natural width).
{{LaTeX/Example|code=
...
\usepackage{multirow}
...
\begin{tabular}{ {{!}}l{{!}}l{{!}}l{{!}} }
\hline
\multicolumn{3}{ {{!}}c{{!}} }{Team sheet} \\
\hline
Goalkeeper & GK & Paul Robinson \\ \hline
\multirow{4}{*}{Defenders} & LB & Lucas Radebe \\
& DC & Michael Duburry \\
& DC & Dominic Matteo \\
& RB & Didier Domi \\ \hline
\multirow{3}{*}{Midfielders} & MC & David Batty \\
& MC & Eirik Bakke \\
& MC & Jody Morris \\ \hline
Forward & FW & Jamie McMaster \\ \hline
\multirow{2}{*}{Strikers} & ST & Alan Smith \\
& ST & Mark Viduka \\
\hline
\end{tabular}
|render=
{{Dark mode invert|[[Image:multirow.svg]]}}
}}
The main thing to note when using {{LaTeX/LaTeX|code=\multirow<!---->}} is that a blank entry must be inserted for each appropriate cell in each subsequent row to be spanned.
If there is no data for a cell, just don't type anything, but you still need the "&" separating it from the next column's data. The astute reader will already have deduced that for a table of <math>n</math> columns, there must always be <math>n-1</math> ampersands in each row (unless {{LaTeX/LaTeX|code=\multicolumn<!---->}} is also used).
=== Spanning in both directions simultaneously ===
Here is a nontrivial example of how to use spanning in both directions simultaneously and have the borders of the cells drawn correctly:
{{LaTeX/Example|code=
\usepackage{multirow}
\begin{tabular}{cc{{!}}c{{!}}c{{!}}c{{!}}c{{!}}l}
\cline{3-6}
& & \multicolumn{4}{ c{{!}} }{Primes} \\ \cline{3-6}
& & 2 & 3 & 5 & 7 \\ \cline{1-6}
\multicolumn{1}{ {{!}}c }{\multirow{2}{*}{Powers} } &
\multicolumn{1}{ {{!}}c{{!}} }{504} & 3 & 2 & 0 & 1 & \\ \cline{2-6}
\multicolumn{1}{ {{!}}c }{} &
\multicolumn{1}{ {{!}}c{{!}} }{540} & 2 & 3 & 1 & 0 & \\ \cline{1-6}
\multicolumn{1}{ {{!}}c }{\multirow{2}{*}{Powers} } &
\multicolumn{1}{ {{!}}c{{!}} }{gcd} & 2 & 2 & 0 & 0 & min \\ \cline{2-6}
\multicolumn{1}{ {{!}}c }{} &
\multicolumn{1}{ {{!}}c{{!}} }{lcm} & 3 & 3 & 1 & 1 & max \\ \cline{1-6}
\end{tabular}
|render=
{{Dark mode invert|[[Image:multirowandcolumnexample.svg|300px]]}}
}}
The command {{LaTeX/LaTeX|code=\multicolumn{1}{|c|}{...}<!---->}} is just used to draw vertical borders both on the left and on the right of the cell. Even when combined with {{LaTeX/LaTeX|code=\multirow{2}{*}{...}<!---->}}, it still draws vertical borders that only span the first row. To compensate for that, we add {{LaTeX/LaTeX|code=\multicolumn{1}{|c|}{...}<!---->}} in the following rows spanned by the multirow. Note that we cannot just use {{LaTeX/LaTeX|code=\hline<!---->}} to draw horizontal lines, since we do not want the line to be drawn over the text that spans several rows. Instead we use the command {{LaTeX/LaTeX|code=\cline{2-6}<!---->}} and opt out the first column that contains the text "Powers".
Here is another example exploiting the same ideas to make
the familiar and popular "2x2" or double dichotomy:
{{LaTeX/Example|code=
\begin{tabular}{ r{{!}}c{{!}}c{{!}} }
\multicolumn{1}{r}{}
& \multicolumn{1}{c}{noninteractive}
& \multicolumn{1}{c}{interactive} \\
\cline{2-3}
massively multiple & Library & University \\
\cline{2-3}
one-to-one & Book & Tutor \\
\cline{2-3}
\end{tabular}
|render=
{{Dark mode invert|[[Image:Latex-tables-double-dichotomy-example.svg|400px]]}}
}}
==Controlling table size==
=== Resize tables ===
The {{LaTeX/Package|graphicx}} packages features the command {{LaTeX/LaTeX|code=\resizebox{width}{height}{object}<!---->}} which can be used with {{LaTeX/Environment|tabular}} to specify the height and width of a table. The following example shows how to resize a table to 8cm width while maintaining the original width/height ratio.
{{LaTeX/Usage|code=
\usepackage{graphicx}
% ...
\resizebox{8cm}{!} {
\begin{tabular}...
\end{tabular}
}
}}
Resizing table including the caption
{{LaTeX/Usage|code=
\begin{table}[h]
\resizebox{1.4\textwidth}{!}{\begin{minipage}{\textwidth}
\begin{tabular}{r{{!}}c{{!}}c{{!}}}
& \multicolumn{1}{c}{noninteractive}
& \multicolumn{1}{c}{interactive} \\
\cline{2-3}
massively multiple & Library & University \\
\cline{2-3}
one-to-one & Book & Tutor \\
\cline{2-3}
\end{tabular}
\caption[Table caption text]{Table taken from \cite[p.10]{refid} }
\label{table:name}
\end{minipage} }
\end{table}
}}
Alternatively you can use {{LaTeX/LaTeX|code=\scalebox{ratio}{object}<!---->}} in the same way but with ratios rather than fixed sizes:
{{LaTeX/Usage|code=
\usepackage{graphicx}
% ...
\scalebox{0.7}{
\begin{tabular}...
\end{tabular}
}
}}
=== Changing font size ===
A table can be globally switched to a different font size by simply adding the desired size command (here: {{LaTeX/LaTeX|code=\footnotesize<!---->}}) in the table scope, which may be after the {{LaTeX/LaTeX|code=\begin{table}<!---->}} statement if you use floats, otherwise you need to add a group delimiter.
{{LaTeX/Usage|code=
{\footnotesize
\begin{tabular}{{{!}} r {{!}} r {{!}}{{!}} c {{!}} c {{!}} c {{!}}}
% ...
\end{tabular}
}
}}
{{LaTeX/Usage|code=
\begin{table}[h]\footnotesize
\caption{Performance at peak F-measure}
\begin{tabular}{{{!}} r {{!}} r {{!}}{{!}} c {{!}} c {{!}} c {{!}}}
% ...
\end{tabular}
\end{table}
}}
Alternatively, you can change the default font for all the tables in your document by placing the following code in the preamble:
{{LaTeX/Usage|code=
\let\oldtabular\tabular
\renewcommand{\tabular}{\footnotesize\oldtabular}
}}
See [[LaTeX/Fonts#Sizing_text|Fonts]] for named font sizes. The table caption font size is not affected. To control the caption font size, see [[LaTeX/Floats,_Figures_and_Captions#Caption_Styles|Caption Styles]].
It is also possible to change the vertical space between rows using {{LaTeX/LaTeX|code=\renewcommand{\arraystretch}{0.8}<!---->}} before {{LaTeX/LaTeX|code=\begin{tabular}<!---->}}.
== Colors ==
=== Alternate row colors in tables ===
The {{LaTeX/Package|xcolor}} package provides the necessary commands to produce tables with alternate row colors, when loaded with the {{LaTeX/Parameter|table}} option.
The command <code>\rowcolors{<''starting row''>}{<''odd color''>}{<''even color''>}</code> has to be specified right before the {{LaTeX/Environment|tabular}} environment starts.
{{LaTeX/Example|code=
\documentclass{article}
\usepackage[table]{xcolor}
\begin{document}
\begin{center}
\rowcolors{1}{green}{pink}
\begin{tabular}{lll}
odd & odd & odd \\
even & even & even\\
odd & odd & odd \\
even & even & even\\
\end{tabular}
\end{center}
\end{document}
|render=
[[File:LaTeXAlternateRowTable.svg|right]]
}}
The command {{LaTeX/LaTeX|code=\hiderowcolors<!---->}} is available to deactivate highlighting from a specified row until the end of the table.
Highlighting can be reactivated within the table via the {{LaTeX/LaTeX|code=\showrowcolors<!---->}} command. If while using these commands you experience <samp>misplaced \noalign errors</samp> then use the commands at the very beginning or end of a row in your tabular.
{{LaTeX/Usage|code=\hiderowcolors odd & odd & odd \\<!---->}}
or
{{LaTeX/Usage|code=odd & odd & odd \\ \showrowcolors<!---->}}
=== Colors of individual cells ===
As above this uses the {{LaTeX/Package|xcolor<!---->}} package.
{{LaTeX/Usage|code=
% Include this somewhere in your document
\usepackage[table]{xcolor}
% Enter this in the cell you wish to color a light grey.
% NB: the word 'gray' here denotes the grayscale color scheme, not the color grey. '0.9' denotes how dark the grey is.
\cellcolor[gray]{0.9}
% The following will color the cell red.
\cellcolor{red}
}}
== Width and stretching ==
We keep providing documentation for {{LaTeX/Environment|tabular*}} and {{LaTeX/Environment|tabularx}}.
=== The ''tabular*'' environment===
This is basically a slight extension on the original tabular version, although it requires an extra argument (before the column descriptions) to specify the preferred width of the table.
{{LaTeX/Example|code=
\begin{tabular*}{0.75\textwidth}{ {{!}} c {{!}} c {{!}} c {{!}} r {{!}} }
\hline
label 1 & label 2 & label 3 & label 4 \\
\hline
item 1 & item 2 & item 3 & item 4 \\
\hline
\end{tabular*}
|render=
{{Dark mode invert|[[Image:LaTeX TabWidth1.svg|right]]}}
}}
However, that may not look quite as intended. The columns are still at their natural width (just wide enough to fit their contents) while the rows are as wide as the table width specified. If you do not like this default, you must also explicitly insert extra column space. LaTeX has ''rubber lengths'', which, unlike others, are not fixed. LaTeX can dynamically decide how long the lengths should be. So, an example of this is the following.
{{LaTeX/Example|code=
\begin{tabular*}{0.75\textwidth}{@{\extracolsep{\fill} } {{!}} c {{!}} c {{!}} c {{!}} r {{!}} }
\hline
label 1 & label 2 & label 3 & label 4 \\
\hline
item 1 & item 2 & item 3 & item 4 \\
\hline
\end{tabular*}
|render=
{{Dark mode invert|[[Image:LaTeX TabWidth2.svg|right]]}}
}}
You will notice the {{LaTeX/LaTeX|code=@{...}<!---->}} construct added at the beginning of the column description. Within it is the {{LaTeX/LaTeX|code=\extracolsep<!---->}} command, which requires a width. A fixed width could have been used. However, by using a rubber length, such as {{LaTeX/LaTeX|code=\fill<!---->}}, the columns are automatically spaced evenly.
=== The ''tabularx'' package ===
This package provides a table environment called {{LaTeX/Environment|tabularx}}, which is similar to the {{LaTeX/Environment|tabular*}} environment except that it has a new column specifier {{LaTeX/Parameter|X}} (in uppercase). The column(s) specified with this specifier will be stretched to make the table as wide as specified, greatly simplifying the creation of tables.
{{LaTeX/Example|code=
\usepackage{tabularx}
% ...
\begin{tabularx}{\textwidth}{ {{!}}X{{!}}X{{!}}X{{!}}X{{!}} }
\hline
label 1 & label 2 & label 3 & label 4 \\
\hline
item 1 & item 2 & item 3 & item 4 \\
\hline
\end{tabularx}
|render=
{{Dark mode invert|[[Image:LaTeX TabXWidth1.svg|450px|right]]}}
}}
The content provided for the boxes is treated as for a {{LaTeX/Parameter|p}} column, except that the width is calculated automatically. If you use the package {{LaTeX/Package|array}}, you may also apply any {{LaTeX/LaTeX|code=>{\cmd}|}} or {{LaTeX/LaTeX|code=<{\cmd}|}} command to achieve specific behavior (like {{LaTeX/LaTeX|code=\centering<!---->}}, or {{LaTeX/LaTeX|code=\raggedright\arraybackslash<!---->}}) as described previously.
Another option is to use {{LaTeX/LaTeX|code=\newcolumntype<!---->}} to format selected columns in a different way. It defines a new column specifier, e.g. {{LaTeX/Parameter|R}} (in uppercase). In this example, the second and fourth column is adjusted in a different way ({{LaTeX/LaTeX|code=\raggedleft<!---->}}):
{{LaTeX/Example|code=
\usepackage{tabularx}
% ...
\newcolumntype{R}{>{\raggedleft\arraybackslash}X}%
\begin{tabularx}{\textwidth}{ {{!}}l{{!}}R{{!}}l{{!}}R{{!}} }
\hline
label 1 & label 2 & label 3 & label 4 \\
\hline
item 1 & item 2 & item 3 & item 4 \\
\hline
\end{tabularx}
|render=
{{Dark mode invert|[[Image:LaTeX TabXWidth2.svg|450px|right]]}}
}}
Tabularx with rows spanning multiple columns using {{LaTeX/LaTeX|code=\multicolumn<!---->}}. The two central columns are posing as one by using the {{LaTeX/Parameter|X@{}}} option. Note that the {{LaTeX/LaTeX|code=\multicolumn<!---->}} width (which in this example is 2) should equal the (in this example 1+1) width of the spanned columns:
{{LaTeX/Example|code=
\usepackage{tabularx}
% ...
\begin{tabularx}{1\textwidth}{ {{!}}>{\setlength\hsize{1\hsize}\centering}X{{!}}>{\setlength\hsize{1\hsize}\raggedleft}X@{} >{\setlength\hsize{1\hsize}\raggedright}X{{!}}>{\setlength\hsize{1\hsize}\centering}X{{!}} }
\hline
Label 1 & \multicolumn{2}{>{\centering\setlength\hsize{2\hsize} }X{{!}}}{Label 2} & Label 3\tabularnewline
\hline
123 & 123 & 456 & 123 \tabularnewline
\hline
123 & 123 & 456 & 123 \tabularnewline
\hline
\end{tabularx}
|render=
{{Dark mode invert|[[Image:LaTeX tabularx_multi.svg|450px|right]]}}
}}
In a way analogous to how new commands with arguments can be created with {{code|\newcommand}}, new column types with arguments can be created with {{code|\newcolumntype}} as follows:
{{LaTeX/Usage|code=
\usepackage{tabularx}
\usepackage[table]{xcolor} %Used to color the last column
% ...
\newcolumntype{L}[1]{>{\hsize=#1\hsize\raggedright\arraybackslash}X}%
\newcolumntype{R}[1]{>{\hsize=#1\hsize\raggedleft\arraybackslash}X}%
\newcolumntype{C}[2]{>{\hsize=#1\hsize\columncolor{#2}\centering\arraybackslash}X}%
\begin{tabularx}{\textwidth}{ {{!}} L{1} {{!}} R{0.5} {{!}} R{0.5} {{!}} C{2}{gray} {{!}} }
\hline
label 1 & label 2 & label 3 & label 4 \\
\hline
item 1 & item 2 & item 3 & item 4 \\
\hline
\end{tabularx}
}}
where since there are 4 columns, the sum of the {{code|\hsize}}'s (1 + 0.5 + 0.5 + 2) must be equal to 4. The default value used by tabularx for {{code|\hsize}} is 1.
=== The ''tabulary'' package ===
[http://www.ctan.org/pkg/tabulary <code>tabulary</code>] is a modified {{LaTeX/Package|tabular*}} allowing width of columns set for equal heights.
{{LaTeX/Package|tabulary}} allows easy and convenient writing of well balanced tables.
The problem with {{LaTeX/Package|tabularx}} is that it leaves much blank if your cells are almost empty. Besides, it is not easy to have different column sizes.
{{LaTeX/Package|tabulary}} tries to balance the column widths so that each column has at least its natural width, without exceeding the maximum length.
{{LaTeX/Usage|code=
\usepackage{tabulary}
...
\begin{center}
\begin{tabulary}{0.7\textwidth}{LCL}
Short sentences & \# & Long sentences \\
\hline
This is short. & 173 & This is much loooooooonger, because there are many more words. \\
This is not shorter. & 317 & This is still loooooooonger, because there are many more words. \\
\end{tabulary}
\end{center}
}}
The first parameter is the maximum width. {{LaTeX/Package|tabulary}} will try not to exceed it, but it will not stretch to it if there is not enough content, contrary to {{LaTeX/Package|tabularx}}.
The second parameter is the column disposition. Possible values are those from the {{LaTeX/Environment|tabular}} environment, plus
{| class="wikitable"
| {{LaTeX/Parameter|L}}
| left-justified balanced column
|-
| {{LaTeX/Parameter|C}}
| centered balanced column
|-
| {{LaTeX/Parameter|R}}
| right-justified balanced column
|-
| {{LaTeX/Parameter|J}}
| left-right-justified balanced column
|}
These are all capitals.
=== The ''tabu'' environment ===
It works pretty much like {{LaTeX/Environment|tabularx}}.
Note: ''tabu'' is currently [https://github.com/tabu-issues-for-future-maintainer/tabu/blob/master/README.md broken and unmaintained]
{{LaTeX/Usage|code=
\begin{tabu} to \linewidth {llX[2]lllXl}
% ...
\end{tabu}
}}
{{LaTeX/LaTeX|code=to \linewidth<!---->}} specifies the target width.
The {{LaTeX/Parameter|X}} parameter can have an optional span factor.
== Table across several pages ==
Long tables are natively supported by LaTeX thanks to the {{LaTeX/Environment|longtable}} environment, which replaces both the {{LaTeX/Environment|tabular}} and {{LaTeX/Environment|table}} environments or rather combines them into a single environment. Unfortunately, this environment does not support stretching (X columns).
The {{LaTeX/Package|tabu}} package (which is [https://github.com/tabu-issues-for-future-maintainer/tabu/blob/main/README.md no longer maintained]) provides the {{LaTeX/Environment|longtabu}} environment. It has most of the features of {{LaTeX/Environment|tabu}}, with the additional capability to span multiple pages.
LaTeX can do well with long tables: you can specify a header that will repeat on every page, a header for the first page only, and the same for the footer.
{{LaTeX/Usage|code=
\begin{longtabu} to \linewidth {lX[2]lXl}
\rowfont\bfseries H1 & H2 & H3 & H4 & H5 \\ \hline
\endhead
\\ \hline
\multicolumn{5}{r}{There is more to come} \\
\endfoot
\\ \hline
\endlastfoot
% Content ...
}}
It uses syntax similar to {{LaTeX/Environment|longtable}}, so you should have a look at its documentation if you want to know more.
Alternatively you can try one of the following packages [http://www.ctan.org/pkg/supertabular <code>supertabular</code>] or [http://www.ctan.org/pkg/xtab <code>xtab</code>], an extended and somewhat improved version of {{LaTeX/Package|supertabular}}.
== Partial vertical lines ==
Adding a partial vertical line to an individual cell:
{{LaTeX/Example|code=
\begin{tabular}{ l c r }
\hline
1 & 2 & 3 \\ \hline
4 & 5 & \multicolumn{1}{r{{!}}}{6} \\ \hline
7 & 8 & 9 \\ \hline
\end{tabular}
|render=
{{Dark mode invert|[[Image:Partial-vertical-line-add.svg]]}}
}}
Removing part of a vertical line in a particular cell:
{{LaTeX/Example|code=
\begin{tabular}{ {{!}} l {{!}} c {{!}} r {{!}} }
\hline
1 & 2 & 3 \\ \hline
4 & 5 & \multicolumn{1}{r}{6} \\ \hline
7 & 8 & 9 \\ \hline
\end{tabular}
|render=
{{Dark mode invert|[[Image:Partial-vertical-line-remove.svg]]}}
}}
== Vertically centered images ==
Inserting images into a table row will align it at the top of the cell.
By using the {{LaTeX/Package|array}} package this problem can be solved.
Defining a new columntype will keep the image vertically centered.
{{LaTeX/Usage|code=
\newcolumntype{V}{>{\centering\arraybackslash} m{.4\linewidth} }
}}
Or use a parbox to center the image.
{{LaTeX/Usage|code=
\parbox[c]{1em}{\includegraphics{image.png} }
}}
A raisebox works as well, also allowing to manually fine-tune the alignment with its first parameter.
{{LaTeX/Usage|code=
\raisebox{-.5\height}{\includegraphics{image.png} }
}}
== Footnotes in tables ==
The {{LaTeX/Environment|tabular}} environment does not handle footnotes properly. The {{LaTeX/Environment|longtable}} fixes that.
== Professional tables ==
Many professionally typeset books and journals feature simple tables, which have appropriate spacing above and below lines, and almost ''never'' use vertical rules. Many examples of LaTeX tables (including this Wikibook) showcase the use of vertical rules (using "|"), and double-rules (using {{LaTeX/LaTeX|code=\hline\hline<!---->}} or "||"), which are regarded as unnecessary and distracting in a professionally published form. The [http://www.ctan.org/tex-archive/macros/latex/contrib/booktabs/ booktabs] package is useful for easily providing this professionalism in LaTeX tables, and the [http://mirrors.ctan.org/macros/latex/contrib/booktabs/booktabs.pdf documentation] also provides guidelines on what constitutes a "good" table.
In brief, the package uses {{LaTeX/LaTeX|code=\toprule<!---->}} for the uppermost rule (or line), {{LaTeX/LaTeX|code=\midrule<!---->}} for the rules appearing in the middle of the table (such as under the header), and {{LaTeX/LaTeX|code=\bottomrule<!---->}} for the lowermost rule. This ensures that the rule weight and spacing are acceptable. In addition, {{LaTeX/LaTeX|code=\cmidrule<!---->}} can be used for mid-rules that span specified columns. The following example contrasts the use of booktabs and two equivalent normal LaTeX implementations (the second example requires {{LaTeX/LaTeX|code=\usepackage{array}<!---->}} or {{LaTeX/LaTeX|code=\usepackage{dcolumn}<!---->}}, and the third example requires {{LaTeX/LaTeX|code=\usepackage{booktabs}<!---->}} in the preamble).
=== Normal LaTeX ===
{{LaTeX/Example|code=
\begin{tabular}{llr}
\hline
\multicolumn{2}{c}{Item} \\
\cline{1-2}
Animal & Description & Price (\$) \\
\hline
Gnat & per gram & 13.65 \\
& each & 0.01 \\
Gnu & stuffed & 92.50 \\
Emu & stuffed & 33.33 \\
Armadillo & frozen & 8.99 \\
\hline
\end{tabular}
|render={{Dark mode invert|[[Image:LaTeX animal table.svg]]}}}}
=== Using {{LaTeX/Package|array}} ===
{{LaTeX/Example|code=
\usepackage{array}
%or \usepackage{dcolumn}
...
\begin{tabular}{llr}
\firsthline
\multicolumn{2}{c}{Item} \\
\cline{1-2}
Animal & Description & Price (\$) \\
\hline
Gnat & per gram & 13.65 \\
& each & 0.01 \\
Gnu & stuffed & 92.50 \\
Emu & stuffed & 33.33 \\
Armadillo & frozen & 8.99 \\
\lasthline
\end{tabular}
|render={{Dark mode invert|[[Image:LaTeX animal table with array.svg]]}}}}
=== Using {{LaTeX/Package|booktabs}} ===
{{LaTeX/Example|code=
\usepackage{booktabs}
\begin{tabular}{llr}
\toprule
\multicolumn{2}{c}{Item} \\
\cmidrule(r){1-2}
Animal & Description & Price (\$) \\
\midrule
Gnat & per gram & 13.65 \\
& each & 0.01 \\
Gnu & stuffed & 92.50 \\
Emu & stuffed & 33.33 \\
Armadillo & frozen & 8.99 \\
\bottomrule
\end{tabular}
|render={{Dark mode invert|[[Image:LaTeX animal table with booktabs.svg]]}}}}
Usually the need arises for footnotes under a table (and not at the bottom of the page), with a caption properly spaced above the table. These are addressed by the [http://www.ctan.org/tex-archive/macros/latex/contrib/ctable/ ctable] package. It provides the option of a short caption given to be inserted in the list of tables, instead of the actual caption (which may be quite long and inappropriate for the list of tables). The {{LaTeX/Package|ctable}} uses the {{LaTeX/Package|booktabs}} package.
== Sideways tables ==
Tables can also be put on their side within a document using the {{LaTeX/Package|rotating}} or the {{LaTeX/Package|rotfloat}} package. See the [[LaTeX/Rotations|Rotations]] chapter.
== Table with legend ==
To add a legend to a table the [http://www.ctan.org/tex-archive/macros/latex/contrib/caption/ caption] package can be used. With the caption package a {{LaTeX/LaTeX|code=\caption*{...}<!---->}} statement can be added besides the
normal {{LaTeX/LaTeX|code=\caption{...}<!---->}}. Example:
{{LaTeX/Usage|code=
\begin{table}
\begin{tabular}{{{!}} r {{!}} r {{!}}{{!}} c {{!}} c {{!}} c {{!}}}
...
\end{tabular}
\caption{A normal caption}
\caption*{
A legend, even a table can be used
\begin{tabular}{l l}
item 1 & explanation 1 \\
\end{tabular}
}
\end{table}
}}
The normal caption is needed for labels and references.
== The ''eqparbox'' package ==
On rare occasions, it might be necessary to stretch every row in a table to the natural width of its longest line, for instance when one has the same text in two languages and wishes to present these next to each other with lines synching up. A tabular environment helps control where lines should break, but cannot justify the text, which leads to ragged right edges. The {{LaTeX/Package|eqparbox}} package provides the command {{LaTeX/LaTeX|code=\eqmakebox<!---->}} which is like {{LaTeX/LaTeX|code=\makebox<!---->}} but instead of a {{LaTeX/Parameter|width}} argument, it takes a tag. During compilation it bookkeeps which {{LaTeX/LaTeX|code=\eqmakebox<!---->}} with a certain tag contains the widest text and can stretch all {{LaTeX/LaTeX|code=\eqmakebox<!---->}}es with the same tag to that width. Combined with the {{LaTeX/Package|array}} package, one can define a column specifier that justifies the text in all lines:comand
{{LaTeX/Usage|code=
\newsavebox{\tstretchbox}
\newcolumntype{S}[1]{%
>{\begin{lrbox}{\tstretchbox} }%
l%
<{\end{lrbox}%
\eqmakebox[#1][s]{\unhcopy\tstretchbox} }%
}
}}
See the documentation of the {{LaTeX/Package|eqparbox}} package for more details.
== The ''paracol'' package ==
The various tabular environments available for LaTeX are feature rich; however, they lack the ability to '''automatically page break large rows'''. The paracol package provides automatic page breaks in between rows and in certain cases can replace the tabular environment. Such situations could be common in documents that require translations and definitions, which may also includes lists.
For further detail see the documentation of the {{LaTeX/Package|paracol}} package.
== Floating with ''table'' ==
In WYSIWYG document processors, it is common to put tables in the middle of the text. This is what we have been doing until now.
Professional documents, however, often make it a point to print tables on a dedicated page so that they do not disrupt the flow. From the point of view of the source code, one has no idea on which page the current text is going to lie, so it is hardly possible to guess which page may be appropriate for our table. LaTeX can automate this task by abstracting objects such as tables, pictures, etc., and deciding for us where they might fit best. This abstraction is called a ''float''. Generally, an object that is floated will appear in the vicinity of its introduction in the source file, but one can choose to control its position also.
To tell LaTeX we want to use our table as a float, we need to put a {{LaTeX/Environment|table}} environment around the {{LaTeX/Environment|tabular}} environment, which is able to float and add a label and caption.
{{Warning|
Please understand: you do not ''have to'' use floating tables. If you want to place your tables where they lie in your source code and you do not need any label, do not use {{LaTeX/Environment|table}} at all! This is a very common misunderstanding among newcomers.
}}
The {{LaTeX/Environment|table}} environment initiates a type of float just as the environment {{LaTeX/Environment|figure}}. In fact, the two bear a lot of similarities (positioning, captions, etc.). More information about floating environments, captions etc. can be found in [[LaTeX/Floats,_Figures_and_Captions|Floats, Figures and Captions]].
The environment names may now seem quite confusing. Let's sum it up:
* {{LaTeX/Environment|tabular}} is for the content itself (columns, lines, etc.).
* {{LaTeX/Environment|table}} is for the location of the table on the document, plus caption and label support.
{{LaTeX/Usage|code=
\begin{table}[position specifier]
\centering
\begin{tabular}{{{!}}l{{!}}}
... your table ...
\end{tabular}
\caption{This table shows some data}
\label{tab:myfirsttable}
\end{table}
}}
In the table, we used a label, so now we can refer to it just like any other reference:
{{LaTeX/Usage|code=
\ref{tab:myfirsttable}
}}
The {{LaTeX/Environment|table}} environment is also useful when you want to have a
list of tables at the beginning or end of your document with the command
{{LaTeX/Usage|code=
\listoftables
}}
The captions now show up in the list of tables, if displayed.
You can set the optional parameter {{LaTeX/Parameter|position specifier}} to define the position of the table, where it should be placed. The following characters are all possible placements. Using sequences of it define your "wishlist" to LaTeX.
{| class="wikitable"
|-
| {{LaTeX/Parameter|h}}
| where the table is declared ('''h'''ere)
|-
| {{LaTeX/Parameter|t}}
| at the '''t'''op of the page
|-
| {{LaTeX/Parameter|b}}
| at the '''b'''ottom of the page
|-
| {{LaTeX/Parameter|p}}
| on a dedicated '''p'''age of floats
|-
| {{LaTeX/Parameter|!}}
|override the default float restrictions. E.g., the maximum size allowed of a {{LaTeX/Parameter|b}} float is normally quite small; if you want a large one, you need this {{LaTeX/Parameter|!}} parameter as well.
|-
|}
Default is {{LaTeX/Parameter|tbp}}, which means that it is by default placed on the top of the page. If that's not possible, it's placed at the bottom if possible, or finally with other floating environments on an extra page.
You can force LaTeX to use one given position. E.g. {{LaTeX/Parameter|[!h]}} forces LaTeX to place it exactly where you place it (Except when it's really impossible, e.g you place a table ''here'' and this place would be the last line on a page). Again, understand it correctly: it urges LaTeX to put the table at a specific place, but it will not be placed there if LaTeX thinks it will not look great. If you really want to place your table manually, do not use the {{LaTeX/Environment|table}} environment.
Centering the table horizontally works like everything else, using the {{LaTeX/LaTeX|code=\centering<!---->}} command just after opening the {{LaTeX/Environment|table}} environment, or by enclosing it with a {{LaTeX/Environment|center}} environment.
== Using spreadsheets and data analysis tools ==
For complex or dynamic tables, you may want to use a spreadsheet. You might save lots of time by building tables using specialized software and exporting them in LaTeX format. The following plugins and libraries are available for some popular software:
* [http://calc2latex.sourceforge.net/ calc2latex]: for LibreOffice and OpenOffice.org Calc spreadsheets,
* [http://www.ctan.org/tex-archive/support/excel2latex/ excel2latex]: for Microsoft Office Excel,
* [https://github.com/TheChymera/matrix2latex matrix2latex]: for Python and MATLAB,
* [http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_latex.html pandas]: pandas DataFrame's have a method to convert data they contain to latex,
* [http://rubygems.org/gems/latex-tools latex-tools]: a Ruby library,
* [http://cran.r-project.org/web/packages/xtable/index.html xtable]: a library for R,
* [http://orgmode.org/ org-mode]: for Emacs users, org-mode tables can be used inline in LaTeX documents, see [https://www.gnu.org/software/emacs/manual/html_node/org/A-LaTeX-example.html] for a tutorial.
* [http://emacswiki.org/emacs/AlignCommands Emacs align commands]: the align commands can clean up a messy LaTeX table.
* [http://truben.no/latex/table/ Online Table generator for LATeX]: An online tool for creating simple tables within the browser. LaTeX format is directly generated as you type.
* [http://www.tablesgenerator.com/ Create LaTeX tables online ]: Online tool.
However, copying the generated source code to your document is not convenient at all. For maximum flexibility, generate the source code to a separate file which you can input from your main document file with the {{LaTeX/LaTeX|code=\input<!---->}} command.
If your spreadsheet supports command-line, you can generate your complete document (table included) in one command, using a Makefile for example.
See [[LaTeX/Modular Documents|Modular Documents]] for more details.
== Need more features? ==
Have a look at one of the following packages:
* [http://www.ctan.org/pkg/hhline <code>hhline</code>]: do whatever you want with horizontal lines
* [http://www.ctan.org/pkg/array <code>array</code>]: gives you more freedom on how to define columns
* [http://www.ctan.org/pkg/colortbl <code>colortbl</code>]: make your table more colorful
* <code>[https://ctan.org/pkg/threeparttable threeparttable]</code> makes it possible to put footnotes both within the table and its caption
* [http://www.ctan.org/pkg/arydshln <code>arydshln</code>]: creates dashed horizontal and vertical lines
* [http://www.ctan.org/pkg/ctable <code>ctable</code>]: allows for footnotes under table and properly spaced caption above (incorporates booktabs package)
* [http://www.ctan.org/pkg/slashbox <code>slashbox</code>]: create 2D tables with the first cell containing a description for both axes. Not available in Tex Live 2011 or later.
* <code>[https://ctan.org/pkg/diagbox diagbox]</code>: compatible to <code>slashbox</code>, come with Tex Live 2011 or later
* [http://www.ctan.org/pkg/dcolumn <code>dcolumn</code>]: decimal point alignment of numeric cells
* [http://www.ctan.org/pkg/rccol <code>rccol</code>]: advanced decimal point alignment of numeric cells with rounding
* [http://www.ctan.org/pkg/numprint <code>numprint</code>]: print numbers, in the current mode (text or math) in order to use the correct font, with separators, exponent and/or rounded to a given number of digits. tabular(*), array, tabularx, and longtable environments are supported using all features of numprint
* [http://www.ctan.org/pkg/spreadtab <code>spreadtab</code>]: spread sheets allowing the use of formulae
* [http://ctan.org/tex-archive/macros/latex/contrib/siunitx <code>siunitx</code>]: alignment of tabular entries
* <code>[https://www.ctan.org/pkg/pgfplotstable pgfplotstable]</code>: loads, rounds, formats and postprocesses numerical tables, e.g. by importing the data directly from .csv (comma-separated value) files instead of manually writing the whole tables in LaTeX code. Programs such as Excel, LibreOffice Calc etc. can export data sheets as .csv files.
== References ==
{{reflist|2}}
<noinclude>
{{LaTeX/Bottom|Rotations|Title Creation}}
</noinclude>
[[fr:LaTeX/Faire_des_tableaux]]
[[nl:LaTeX/Tabellen]]
[[pl:LaTeX/Tabele]]
qyau0piob3w08n5epw7j76meibtfjy6
Haskell/Type declarations
0
45475
4675928
4666170
2026-10-13T23:06:46Z
Luciérnaga de conocimiento
3401314
4675928
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Elementary Haskell}}
You're not restricted to working with just the types provided by default with the language. There are many benefits to defining your own types:
* Code can be written in terms of the problem being solved, making programs easier to design, write and understand.
* Related pieces of data can be brought together in ways more convenient and meaningful than simply putting and getting values from lists or tuples.
* Pattern matching and the type system can be used to their fullest extent by making them work with your custom types.
Haskell has three basic ways to declare a new type:
* The <code>data</code> declaration, which defines new data types.
* The <code>type</code> declaration for type synonyms, that is, alternative names for existing types.
* The <code>newtype</code> declaration, which defines new data types equivalent to existing ones.
In this chapter, we will study <code>data</code> and <code>type</code>. In a later chapter, we will discuss <code>newtype</code> and see where it can be useful.
== <code>data</code> and constructor functions ==
<code>data</code> is used to define new data types mostly using existing ones as building blocks. Here's a data structure for elements in a simple list of anniversaries:
<syntaxhighlight lang="haskell">
data Anniversary = Birthday String Int Int Int -- name, year, month, day
| Wedding String String Int Int Int -- spouse name 1, spouse name 2, year, month, day
</syntaxhighlight>
This declares a new data type <code>Anniversary</code>, which can be either a Birthday or a Wedding. A Birthday ''contains'' one string and three integers and a Wedding ''contains'' two strings and three integers. The definitions of the two possibilities are separated by the vertical bar. The comments explain to readers of the code about the intended use of these new types. Moreover, with the declaration we also get two ''constructor functions'' for <code>Anniversary</code>; appropriately enough, they are called <code>Birthday</code> and <code>Wedding</code>. These functions provide a way to build a new <code>Anniversary</code>.
Types defined by <code>data</code> declarations are often referred to as ''algebraic data types'', which is something we will address further in later chapters.
As usual with Haskell, the case of the first letter is important: type names and constructor functions must start with capital letters. Other than this syntactic detail, constructor functions work pretty much like the "conventional" functions we have met so far. In fact, if you use <code>:t</code> in GHCi to query the type of, say, <code>Birthday</code>, you'll get:
{{Haskell/GHCi|1=
*Main> :t Birthday
Birthday :: String -> Int -> Int -> Int -> Anniversary
}}
Meaning it's just a function which takes one String and three Int as arguments and ''evaluates to'' an <code>Anniversary</code>. This anniversary will contain the four arguments we passed as specified by the <code>Birthday</code> constructor.
Calling constructors is no different from calling other functions. For example, suppose we have John Smith born on 3rd July 1968:
<syntaxhighlight lang="haskell">
johnSmith :: Anniversary
johnSmith = Birthday "John Smith" 1968 7 3
</syntaxhighlight>
He married Jane Smith on 4th March 1987:
<syntaxhighlight lang="haskell">
smithWedding :: Anniversary
smithWedding = Wedding "John Smith" "Jane Smith" 1987 3 4
</syntaxhighlight>
These two anniversaries can, for instance, be put in a list:
<syntaxhighlight lang="haskell">
anniversariesOfJohnSmith :: [Anniversary]
anniversariesOfJohnSmith = [johnSmith, smithWedding]
</syntaxhighlight>
Or you could just as easily have called the constructors straight away when building the list (although the resulting code looks a bit cluttered).
<syntaxhighlight lang="haskell">
anniversariesOfJohnSmith = [Birthday "John Smith" 1968 7 3, Wedding "John Smith" "Jane Smith" 1987 3 4]
</syntaxhighlight>
== Deconstructing types ==
To use our new data types, we must have a way to access their contents. For instance, one very basic operation with the anniversaries defined above would be extracting the names and dates they contain as a String. So we need a <code>showAnniversary</code> function (for the sake of code clarity, we used an auxiliary <code>showDate</code> function but let's ignore it for a moment):
<syntaxhighlight lang="haskell">
showDate :: Int -> Int -> Int -> String
showDate y m d = show y ++ "-" ++ show m ++ "-" ++ show d
showAnniversary :: Anniversary -> String
showAnniversary (Birthday name year month day) =
name ++ " born " ++ showDate year month day
showAnniversary (Wedding name1 name2 year month day) =
name1 ++ " married " ++ name2 ++ " on " ++ showDate year month day
</syntaxhighlight>
This example shows how we can deconstruct the values built in our data types. <code>showAnniversary</code> takes a single argument of type <code>Anniversary</code>. Instead of just providing a name for the argument on the left side of the definition, however, we specify one of the constructor functions and give names to each argument of the constructor (which correspond to the contents of the Anniversary). A more formal way of describing this "giving names" process is to say we are ''binding variables''. "Binding" is being used in the sense of assigning a variable to each of the values so that we can refer to them on the right side of the function definition.
To handle both "Birthday" and "Wedding" Anniversaries, we needed to provide ''two'' function definitions, one for each constructor. When <code>showAnniversary</code> is called, if the argument is a <code>Birthday</code> Anniversary, the first definition is used and the variables <code>name</code>, <code>year</code>, <code>month</code> and <code>day</code> are bound to its contents. If the argument is a <code>Wedding</code> Anniversary, then the second definition is used and the variables are bound in the same way. This process of using a different version of the function depending on the type of constructor is pretty much like what happens when we use a <code>case</code> statement or define a function piece-wise.
Note that the parentheses around the constructor name and the bound variables are mandatory; otherwise the compiler or interpreter would not take them as a single argument. Also, it is important to have it absolutely clear that the expression inside the parentheses is ''not'' a call to the constructor function, even though it may look just like one.
{{Exercises|1=
''Note: The solution of this exercise is given near the end of the chapter, so we recommend that you attempt it before getting there.''</br>
Reread the function definitions above. Then look closer at the <code>showDate</code> helper function. We said it was provided "for the sake of code clarity", but there is a certain clumsiness in the way it is used. You have to pass three separate Int arguments to it, but these arguments are always linked to each other as part of a single date. It would make no sense to do things like passing the year, month and day values of the Anniversary in a different order, or to pass the month value twice and omit the day.
* Could we use what we've seen in this chapter so far to reduce this clumsiness?
* Declare a <code>Date</code> type which is composed of three Int, corresponding to year, month and day. Then, rewrite <code>showDate</code> so that it uses the new Date data type. What changes will then be needed in <code>showAnniversary</code> and the <code>Anniversary</code> for them to make use of Date?.
}}
== <code>type</code> for making type synonyms ==
As mentioned in the introduction of this module, code clarity is one of the motivations for using custom types. In that spirit, it could be nice to make it clear that the Strings in the Anniversary type are being used as ''names'' while still being able to manipulate them like ordinary Strings. This calls for a <code>type</code> declaration:
<syntaxhighlight lang="haskell">
type Name = String
</syntaxhighlight>
The code above says that a <code>Name</code> is now a synonym for a <code>String</code>. Any function that takes a <code>String</code> will now take a <code>Name</code> as well (and vice-versa: functions that take <code>Name</code> will accept any <code>String</code>). The right hand side of a <code>type</code> declaration can be a more complex type as well. For example, <code>String</code> itself is defined in the standard libraries as
<syntaxhighlight lang="haskell">
type String = [Char]
</syntaxhighlight>
We can do something similar for the list of anniversaries we made use of:
<syntaxhighlight lang="haskell">
type AnniversaryBook = [Anniversary]
</syntaxhighlight>
Type synonyms are mostly just a convenience. They help make the roles of types clearer or provide an alias to such things as complicated list or tuple types. It is largely a matter of personal discretion to decide how type synonyms should be deployed. Abuse of synonyms could make code confusing (for instance, picture a long program using multiple names for common types like Int or String simultaneously).
Incorporating the suggested type synonyms and the <code>Date</code> type we proposed in the exercise(*) of the previous section the code we've written so far looks like this:
</br>
</br>
</br>
((*) '''last chance to try that exercise without looking at the spoilers.''')
</br>
</br>
</br>
<syntaxhighlight lang="haskell">
type Name = String
data Anniversary =
Birthday Name Date
| Wedding Name Name Date
data Date = Date Int Int Int -- Year, Month, Day
johnSmith :: Anniversary
johnSmith = Birthday "John Smith" (Date 1968 7 3)
smithWedding :: Anniversary
smithWedding = Wedding "John Smith" "Jane Smith" (Date 1987 3 4)
type AnniversaryBook = [Anniversary]
anniversariesOfJohnSmith :: AnniversaryBook
anniversariesOfJohnSmith = [johnSmith, smithWedding]
showDate :: Date -> String
showDate (Date y m d) = show y ++ "-" ++ show m ++ "-" ++ show d
showAnniversary :: Anniversary -> String
showAnniversary (Birthday name date) =
name ++ " born " ++ showDate date
showAnniversary (Wedding name1 name2 date) =
name1 ++ " married " ++ name2 ++ " on " ++ showDate date
</syntaxhighlight>
Even in a simple example like this one, there is a noticeable gain in simplicity and clarity compared to the same task using only Ints, Strings, and corresponding lists.
Note that the <code>Date</code> type has a constructor function which is called <code>Date</code> as well. That is perfectly valid and indeed giving the constructor the same name of the type when there is just one constructor is good practice, as a simple way of making the role of the function obvious.
{{body note|1=
After these initial examples, the mechanics of using constructor functions may look a bit unwieldy, particularly if you're familiar with analogous features in other languages. There are syntactical constructs that make dealing with constructors more convenient. These will be dealt with later on, when we return to the topic of constructors and data types to explore them in detail.
}}
{{Haskell/Navigation|chapter=Elementary Haskell}}
{{BookCat}}
e0xwjx0n5ltcobu4nd900zxhf7cfmss
Radiation Oncology/Protons
0
47873
4675969
4585746
2026-10-14T05:30:11Z
Jcb
90773
4675969
wikitext
text/x-wiki
{{Radiation_Oncology:TOC}}
<big>'''Proton Therapy'''</big>
==Clinical Chapters==
*[[Radiation Oncology/CNS/Protons|General CNS]]
**[[Radiation Oncology/CNS/Acoustic neuroma#Proton Therapy|Acoustic neuroma]]
**[[Radiation Oncology/CNS/Pituitary adenoma#Proton Therapy|Pituitary adenoma]]
**[[Radiation Oncology/Craniopharyngioma|Craniopharyngioma]]
**[[Radiation Oncology/Medulloblastoma/Protons|Medulloblastoma]]
**[[Radiation Oncology/CNS/Germinoma#Proton Therapy|Germinoma]]
**[[Radiation Oncology/Pilocytic Astrocytoma|Pediatric low grade glioma]]
**[[Radiation Oncology/CNS/Anaplastic glioma|Anaplastic glioma]]
**[[Radiation Oncology/CNS/High grade glioma/Adjuvant therapy#Proton Therapy|Glioblastoma]]
*[[Radiation Oncology/Retinoblastoma|Retinoblastoma]]
*[[Radiation Oncology/Head & Neck/Protons|Head & Neck]]
*[[Radiation Oncology/Breast/RT technique#Proton Therapy|Breast]]
*[[Radiation Oncology/Esophagus/Early Stage#Proton Therapy|Esophagus]]
*[[Radiation Oncology/Bile duct/Unresectable Disease#Proton therapy|Cholangiocarcinoma]]
*[[Radiation Oncology/Liver/HCC/Protons|Hepatocellular carcinoma]]
*[[Radiation Oncology/Lung/NSCLC/Protons|NSCLC]]
*[[Radiation Oncology/NHL/Protons|Non-Hodgkin's Lymphoma]]
*[[Radiation Oncology/Pancreas/Resectable#Proton Therapy|Pancreas]]
*[[Radiation Oncology/Prostate/Protons|Prostate]]
*[[Radiation Oncology/Cervix/Protons|Cervix]]
*[[Radiation Oncology/Chordoma#Proton Beam Therapy|Chordoma]]
*[[Radiation Oncology/CNS/Cancer pain|Cancer pain]]
==Facilities and Vendors==
*''Please see the [[Radiation Oncology/Corporate/Protons|facilities and vendors]] page''
==General Information==
*'''Michigan; 2011''' -- [http://www.ascopost.com/articles/september-15-2011/we-can-conduct-clinical-trials-of-protons.aspx ASCO Post] -- "We Can Conduct Clinical Trials of Protons" (Lawrence TS, ASCO Post, September 15, 2011, Volume 2, Issue 14)
**Conclusion: "In my opinion, proton facilities should not be permitted to continue to produce results that cannot be distinguished—except by the far greater price—from those produced by IMRT photons. Our patients deserve true improvements in outcome, rather than the hype and added expense that currently dominates the field."
*'''Independent Journalist; 2010''' {{PMID|20339139}} -- "The proton beam debate: are facilities outstripping the evidence?" (Goozner M, J Natl Cancer Inst. 2010 Apr 7;102(7):450-3. Epub 2010 Mar 25.)
**Comment
*'''Tufts; 2009''' {{PMID|19755348}} -- "Systematic Review: Charged-Particle Radiation Therapy for Cancer." (Terasawa T, Ann Intern Med. 2009 Sep 14. [Epub ahead of print])
**Literature review. 243 articles, 185 single-institution retrospective, 9 nonrandomized trials, 8 randomized trials
**Outcome: No statistically significant or important difference in overall, cancer-specific survival or total serious adverse events
**Conclusion: Evidence is needed
*'''Royal Marsden'''
**'''2009''' {{PMID|19672149}} -- "Current clinical evidence for proton therapy." (Brada M, Cancer J. 2009 Jul-Aug;15(4):319-24.)
***Updated review
**'''2007''' {{PMID|17350945}} -- "Proton therapy in clinical practice: current clinical evidence." (Brada M, J Clin Oncol. 2007 Mar 10;25(8):965-70.)
***Review
*'''Columbia; 2009''' {{PMID|19185838}} -- "Protons for radiotherapy: a 1946 proposal." (Hall E, Lancet Oncol. 2009 Feb;10(2):196.)
**Historical perspective
*'''Louisville; 2009''' {{PMID|19111269}} -- "Randomized prospective trials of innovative radiotherapy technology are necessary." (Halperin EC, J Am Coll Radiol. 2009 Jan;6(1):33-7.)
**Most important clinical problem facing radiation oncology is whether randomized prospective trials are necessary to assess innovative technologies. It is possible to identify innovations that should be required to meet the standard of proof of a benefit in a randomized prospective clinical trial before being introduced into widespread clinical practice.
*'''Yale; 2008''' {{PMID|19028271}} -- "Should proton-beam therapy be widely adopted?" (Schulz RJ, Int J Radiat Oncol Biol Phys. 2008 Dec 1;72(5):1307-9; discussion 1309–10.)
**Editorial (Schulz RJ): Clinical outcomes of PT generally indistinguishable from photons. Issues of capital and operating costs, and cost-effectiveness should be revisited
**Response (Suit H): Significantly less integral dose. Answers to comparative Phase III requests are readily answerable by treatment plan comparisons. Need to work on questions that are of unarguable importance, such as hypofractionation, organ tolerance, concurrent chemotherapy protocols, etc.
*'''21st Century Oncology; 2008''' {{PMID|18954812}} -- "A changing paradigm in the study and adoption of emerging health care technologies: coverage with evidence development." (Wallner PE, J Am Coll Radiol. 2008 Nov;5(11):1125-9.)
**Evaluation of drivers for health care. Increased interest to generate more appropriate and usefule "evidence" of benefit.
**Recommendation that "coverage with evidence development" could be used for proton therapy
*'''Harvard; 2008''' {{PMID|18262083}} -- "Magical protons?" (Goitein M, Int J Radiat Oncol Biol Phys. 2008 Mar 1;70(3):654-6.)
**Editorial. Few notes of caution about dangers of proton therapy
**Comment (Withers HR, UCLA) {{PMID|18954723}}
**Response (Goitein M, Harvard) {{PMID|20159368}}
*'''Harvard; 2008''' {{PMID|18237800}} -- "Should positive phase III clinical trial data be required before proton beam therapy is more widely adopted? No." (Suit H, Radiother Oncol. 2008 Feb;86(2):148-53. Epub 2008 Jan 30.)
**Distribution of biological dose superior for proton therapy in most situations. There is no medical rationale for clinical trials of protons, since they deliver lower biological dose to non-target tissues
**Conclusion: Talent, effort and funds for phase III trials should be better spent to investigate real problems
*'''Harvard/MD Anderson; 2008''' {{PMID|18182658}} -- "Should randomized clinical trials be required for proton radiotherapy?" (Goitein M and Cox JD, J Clin Oncol. 2008 Jan 10;26(2):175-6.)
**Editorial. Argument for protons: 1 better dose-distribution due to physical depth dose characteristics, 2) virtually no difference in tissue response per unit dose, 3) radiation delivered to normal tissues damages them. Argument against protons: 1) no randomized evidence. Editorial conclusion: Burden of proof on conventional x-ray therapy to justify that cost savings of photons are not accompanied by undesirable additional morbidity
**Patient comment ({{PMID|18443348}}): RCT in this instance do not meet equipoise; there will be lawsuits for offering ''inferior'' treatment
**Comment (Glatstein E, University of Pennsylvania) {{PMID|18443345}}: RCT should be done because there is an uncertainty about ''clinical'' benefits of protons
**Comment (Tepper JE, University of North Carolina) {{PMID|18443346}}: Need ''some'' evidence of benefit, and expensive technology should have higher standards than technology with minimal cost. At minimum, need high quality Phase II trials, which we don't have yet
**Comment (Lewis BE, UNDMJ) {{PMID|18443346}}: Financial concerns cloud the judgment of physician and hospital, both of whom stand to benefit from increased use of new expensive technologies. We must have the courage to generate high quality, disinterested, and unbiased data
**Comment (Macbeth FR, NCC Cardiff) {{PMID|18443346}}: Only evidence for superiority is base of skull cordomas and ocular tumors, but both are retrospective, and ''not proven.'' Payors (patient, insurance, HMO, taxpayers) deserve to know how much better the treatment is, given the significant expense
**Comment (Brada M, Royal Marsden) {{PMID|18443346}}: Information thus far originates from proponents of protons, with frequent commercial interest in the new equipment. Having some evidence of clinical benefit is not too much to ask
**<u>Rebuttal</u> (Goitein & Cox,) {{PMID|18443346}}: We need to move beyond fixation on RCT and get on with the business of designing, funding, and conducting large-scale clinical studies using ethically defensible methodologies that would have the broad acceptance of our patients
*'''Uppsala; 2007''' {{PMID|17499373}} -- "Proton beam therapy - do we need the randomised trials and can we do them?" (Glimelius B, Radiother Oncol. 2007 May;83(2):105-9. Epub 2007 May 11.)
**Editorial for issue containing Lodge and Olsen studies below
*'''Cochrane Review; 2007''' {{PMID|17502116}} -- "A systematic literature review of the clinical and cost-effectiveness of hadron therapy in cancer." (Lodge M, Radiother Oncol. 2007 May;83(2):110-22. Epub 2007 May 14.)
**Conclusion: Existing data do not suggest that rapid expansion of hadron therapy is appropriate
*'''Oslo; 2007''' {{PMID|17499374}} -- "Proton therapy - a systematic review of clinical effectiveness." (Olsen DR, Radiother Oncol. 2007 May;83(2):123-32. Epub 2007 May 11.)
**Review: 4 RCTs, 5 comparative studies, 44 cases series
**Conclusion: Only low-level evidence available to support proton use
*'''NCI; 2006''' {{PMID|17148768}} -- "Research groups promoting proton therapy "lite"." (Hede K, J Natl Cancer Inst. 2006 Dec 6;98(23):1682-4.)
**News brief
*'''Heidelberg; 2006''' {{PMID|17010908}} -- "Radiation therapy with charged particles." (Schulz-Ertner D, Semin Radiat Oncol. 2006 Oct;16(4):249-59.)
**Review of protons experience, then focus on carbon ions
*'''Duke; 2006''' {{PMID|16887485}} -- "Particle therapy and treatment of cancer." (Halperin EC, Lancet Oncol. 2006 Aug;7(8):676-85.)
**Historical perspective
*'''MGH/PSI; 2005''' {{PMID|16332585}} -- "Swedish protons." (Goitein M, Acta Oncol. 2005;44(8):793-7.)
**Editorial for an issue of Acta Oncologica dedicated to protons
*'''CNAO Italy; 2004''' {{PMID|15971303}} -- "Medical aspects of the National Center For Oncological Hadrontherapy (CNAO-Centro Nazionale Adroterapia Oncologica) in Italy." (Krengli M, Radiother Oncol. 2004 Dec;73 Suppl 2:S21-3.)
**Review of Centro Nazionale Adroterapia Oncologica (CNAO) rationale
*'''Milan'''
**'''2004''' {{PMID|15276173}} -- "Clinical and research validity of hadrontherapy with ion beams." (Orecchia R, Crit Rev Oncol Hematol. 2004 Aug;51(2):81-90.)
***Review of ion therapy literature
**'''1998''' {{PMID|9713294}} -- "Particle beam therapy (hadrontherapy): basis for interest and clinical experience." (Orecchia R, Eur J Cancer. 1998 Mar;34(4):459-68.)
***Review of indications for hadrontherapy
*'''Harvard; 1992''' {{PMID|1311773}} -- "Proton beams in radiation therapy." (Suit H, J Natl Cancer Inst. 1992 Feb 5;84(3):155-64.)
**Overview of proton therapy. 11,763 patients treated. 46% small intracranial lesions, 32% tumors of eye.
**Formation of PROG to evaluate efficacy of proton therapy
==Economic Issues==
*Please see the [[Radiation Oncology/Protons/Economics|Economics]] page
==Secondary Cancers==
*'''Columbia University'''
**'''2008''' {{PMID|18192046}} -- "Secondary neutrons in clinical proton radiotherapy: A charged issue." (Brenner DJ, Radiother Oncol. 2008 Feb;86(2):165-70. Epub 2008 Jan 14.)
**'''2007''' {{PMID|17668949}} -- "The impact of protons on the incidence of second malignancies in radiotherapy." (Hall EJ, Technol Cancer Res Treat. 2007 Aug;6(4 Suppl):31-4.)
**'''2006''' {{PMID|16618572}} -- "Intensity-modulated radiation therapy, protons, and the risk of second cancers." (Hall EJ, Int J Radiat Oncol Biol Phys. 2006 May 1;65(1):1-7.)
==Randomized Evidence==
*Please see the [[Radiation Oncology/Randomized/Protons|level I evidence in proton therapy]] page
==Intensity Modulated Proton Therapy (IMPT)==
==Image-Guided Proton Therapy (IGPT)==
*Shelby A. Lane et al. Image-Guided Proton Therapy: A Comprehensive Review. Cancers (Basel). 2023 May; 15(9): 2555. ({{PMID|37174022}})
==Proton Boron Capture Therapy (PBCT)==
*G A P Cirrone et al. Sci Rep. 2018. First experimental proof of Proton Boron Capture Therapy (PBCT) to enhance protontherapy effectiveness ({{PMID|29348437}})
==Proton Boron Fusion therapy (PBFT)==
*Joo-Young Jung et al. Oncotarget. 2017. Comparison between proton boron fusion therapy (PBFT) and boron neutron capture therapy (BNCT): a monte carlo study ({{PMID|28427153})
*Farshid Tabbakh et al. Sci Rep. 2020. Enhancement of Radiation Effectiveness in Proton Therapy: Comparison Between Fusion and Fission Methods and Further Approaches ({{PMID|32214140}})
316g23zb43t0gt1bzynbci0njrta1eb
OpenSSH/Cookbook/Public Key Authentication
0
51866
4675818
4675781
2026-10-13T12:28:46Z
Larsnooden
430753
space
4675818
wikitext
text/x-wiki
<noinclude>{{simple chapter navigation|previous=File Transfer with SFTP|next=Certificate-based Authentication}}</noinclude>
Authentication keys can improve efficiency, if done properly. As a bonus advantage, the passphrase and private key never leave the client<ref name="RFC4252§7">{{cite web |url=https://tools.ietf.org/html/rfc4252#section-7 |title=The Secure Shell (SSH) Authentication Protocol |publisher=IETF |year=2006| accessdate=2015-05-06}}</ref>. Key-based authentication is generally recommended for outward facing systems so that password authentication can be turned off.
==Key-based authentication==
OpenSSH can use public key cryptography for authentication. In public key cryptography, encryption and decryption are asymmetric. The keys are used in pairs, a public key to encrypt and a private key to decrypt. The [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)] utility can make RSA, Ed25519, MLDSA44-Ed25519, ECDSA, Ed25519-SK, or ECDSA-SK keys for authenticating. Even though DSA keys can still be made, being exactly 1024 bits in size, they are no longer recommended and should be avoided. RSA keys are allowed to vary from 1024 bits on up. The default is now 3072. However, there is only limited benefit after 2048 bits and that makes elliptic curve algorithms preferable. ECDSA can be 256, 384 or 521 bits in size. Ed25519, Ed25519-SK, and ECDSA-SK keys each have a fixed length of 256 bits. Shorter keys are faster, but less secure. Longer keys are much slower to work with but provide better protection, up to a point.
Keys can be named to help remember what they are for. Because the key files can be named anything it is possible to have many keys each named for different services or tasks. The comment field at the end of the public key can also be useful in helping to keep the keys sorted, if you have many of them or use them infrequently.
The process of key-based authentication uses these keys to make a couple of exchanges using the keys to encrypt and decrypt some short message. At the start, a copy of the client's public key is stored on the server and the client's private key is on the client, both stay where they are. The private key never leaves the client. As the client first contacts the server, the server responds by using the client's public key to encrypt a random number and return that encrypted random number as a challenge to the client. The client responds to the challenge by using the matching private key to decrypt the message and extract the random number. The client then makes an MD5 hash of the session ID along with the random number from the challenge and returns that hash to the server. The server then makes its own hash of the session ID and the random number and compares that to the hash returned by the client. If there is a match, the login is allowed. If there is not a match, then the next of any public keys on the server registered as belonging to the same account is tried until either a match is found or all the keys have been tried or the maximum number of failures has been reached. <ref name="How Key Challenges Work">{{cite web | url=http://www.unixwiz.net/techtips/ssh-agent-forwarding.html#chal | title=An Illustrated Guide to SSH Agent Forwarding | author=Steve Friedl | date=2006-02-22 | accessdate=2013-04-27 | publisher=Unixwiz.net }}</ref>
When an agent is used on the client side to manage authentication, the process is similar. The difference is that [http://man.openbsd.org/ssh.1 ssh(1)] passes the challenge off to the agent which then calculates the response and passes it back to [http://man.openbsd.org/ssh.1 ssh(1)] which then passes the agent's response back to the server.
===Basics of Public Key Authentication===
A matching pair of SSH keys, one public and one private, is needed for public key authentication. The [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)] utility is used to make such a key pair. Out of that pair the public key must be properly stored on the remote host before using key-based authentication. The default location for it is the designated '''authorized_keys''' file, usually one such file resides inside each remote user account. The private key stays stored safely on the client.
Once the keys have been prepared and the remote account configured, they can be used for login. Before starting, there must already be an account on the remote system. The details of doing that are outside of the scope of this book. However, once you have a remote account, there are four steps to set up key-based authentication for it:
'''1''') Prepare a directory on the client (say a laptop or a desktop) where the keys will stay, if there isn't one already. For example, if the '''.ssh''' directory is not on the client machine, create it and set the permissions correctly. It is important that it not be writable by any account except its owner:
<syntaxhighlight lang="shell-session">
$ mkdir ~/.ssh/
$ chmod 0700 ~/.ssh/
</syntaxhighlight>
'''2''') Create a key pair inside the designated directory. The example here creates an Ed25519 key pair in the directory '''~/.ssh'''. The option '''-t''' decides the key type and the option '''-f''' assigns the key file a name. It is good to give key files descriptive names, especially if larger numbers of keys are managed. Below, the public key will be named '''fred_example_org_ed25519.pub''' and the private key will be called '''fred_example_org_ed25519'''. Lastly, the '''-C''' option is used to embed a descriptive comment inside the private key itself. The comment is useful for figuring out later what the key is for when one has many keys or a lot of time has passed or both.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -t ed25519 -f ~/.ssh/fred_example_org_ed25519 \
-C "from fred's laptop to server.example.org"
</syntaxhighlight>
Be sure to enter a solid passphrase so that the private key gets encrypted using 128-bit AES. That way the private key can only be read or used when the passphrase is given.
Ed25519, Ed25519-SK, and ECDSA-SK keys have fixed lengths. For RSA and ECDSA keys, the '''-b''' option sets the number of bits used for those kinds of keys.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -o -b 4096 -t rsa -f ~/.ssh/fred_example_org_rsa \
-C "from fred's laptop to server.example.org"
</syntaxhighlight>
Since 6.5 a new private key format is available using a [http://man.openbsd.org/bcrypt.3 bcrypt(3)] key derivative function (KDF) to better protect keys at rest. This new format is always used for Ed25519 keys, and sometime in the future will be the default for all keys. But for right now it may be requested when generating or saving existing keys of other types via the '''-o''' option in [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)].
Details of the new format are found in the source code in the file '''PROTOCOL.key'''.
'''3''') Get the keys to the right places. Transfer only the public key to remote machine. The following assume the default locations for the authorized keys as specified in the server's configuration file by the '''AuthorizedKeysFile''' directive.
'''3a''') If the utility <code>ssh-copy-id</code> exists, and if password authentication is allowed, then it can be used to put the public key into place on the remote system. The ''.pub'' is optional here, the script will figure it out if omitted.
<syntaxhighlight lang="shell-session">
$ ssh-copy-id -i ~/.ssh/fred_example_org_ed25519 fred@server.example.org
</syntaxhighlight>
If that script was successful in transferring the public key, then go on to step 4 below and test the key. If not, then try transferring the public key manually as described in step 3b next.
'''3b''') Or the public key can be put in place manually on the remote machine. For that the remote '''.ssh''' directory is needed, and within that a special file to store the public keys, the default file name is '''authorized_keys'''. If either the '''authorized_keys''' file or '''.ssh''' directory do not exist on the remote machine, they need to be created.
<syntaxhighlight lang="shell-session">
$ mkdir -m 700 ~/.ssh/
$ touch ~/.ssh/authorized_keys
$ chmod 0600 ~/.ssh/authorized_keys
$ nano -w ~/.ssh/authorized_keys
</syntaxhighlight>
Then any editor which does not wrap long lines can be used to add the public key. However the '''authorized_keys''' file is edited to add the key, the key itself must be in the file whole and unbroken on a single line. For example, [http://linux.die.net/man/1/nano nano(1)] can be started with the '''-w''' option to prevent wrapping of long lines. (Another way to set line wrapping permanently in [http://linux.die.net/man/1/nano nano(1)] is by editing [http://linux.die.net/man/5/nanorc nanorc(5)].)
If the key pair is not already on the client, transfer both the public and private keys there. It is usually best to keep both the public and private keys together in the directory '''~/.ssh/''', though the public key is not always needed on the client after this step and could even be regenerated if it is ever needed again.
'''4''') Test the keys
While remaining logged in via the first terminal, use the client system to open another window and in it start another SSH session and try authenticating to the remote machine from the client using the private key.
<syntaxhighlight lang="shell-session">
$ ssh -i ~/.ssh/fred_example_org_ed25519 -l fred server.example.org
</syntaxhighlight>
The option '''-i''' tells [http://man.openbsd.org/ssh.1 ssh(1)] which private key to try.
Only after verifying that the key-based authentication works should you close the original window.
It is possible to make permanent shortcuts on the client using [http://man.openbsd.org/ssh_config.5 ssh_config(5)], explained further below, once key-based authentication is working. In particular, see the '''IdentityFile''', '''IdentitiesOnly''', and '''AddKeysToAgent''' configuration directives, to name three.
It is also a good idea to turn off password authentication, if and only if key-based authentication is setup for all the necessary remote accounts.
➥ '''Troubleshooting of Key-based Authentication''':
If the server refuses to accept the key and fails over to the next authentication method (e.g.: "Server refused our key"), then there are several possible mistakes to look for on the server side.
One of the most common errors is that the file and directory permissions are wrong. The authorized keys file must be owned by the user in question and not be group writable. Nor may the key file's directory be group or world writable.
<syntaxhighlight lang="shell-session">
$ chmod u=rwx,g=rx,o= ~/.ssh
$ chmod u=rw,g=,o= ~/.ssh/authorized_keys
</syntaxhighlight>
Another mistake that can happen is if the key inside the '''authorized_keys''' file on the remote host is broken by line breaks or has other whitespace in the middle. That can be fixed by joining up the lines and removing the spaces or by recopying the key more carefully.
And, though it should go without saying, the halves of the key pair need to match. The public key on the server needs to match the private key held on the client. If the public key is lost, then a new one can be generated with the '''-y''' option, but not the other way around. If the private key is lost, then the public key should be erased as it is no longer of any use. If many keys are in use for an account, it might be a good idea to add comments to them. On the client, it can be a good idea to know which server the key is for, either through the file name itself or through the comment field. A comment can be added using the '''-C''' option.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -t ed25519 -f ~/.ssh/fred_example_org_ed25519 -C "web server mirror"
</syntaxhighlight>
On the server, it can be important to annotate which client they key is from if there is more than one public key there in an account. There the comment can be added to the authorized keys file on the server in the last column if a comment does not already exist. Again, the format of the authorized keys file is given in the manual page for [http://man.openbsd.org/sshd.8 sshd(8)] in the section "AUTHORIZED_KEYS FILE FORMAT". If the keys are not labeled they can be hard to match, which might or might not be what you want.
====Associating Keys Permanently with a Server====
A key can be specified at run time, but to save retyping the same paths again and again, the '''Host''' directive in [http://man.openbsd.org/ssh_config.5 ssh_config(5)] can apply specific settings to a target host. In this case, by changing '''~/.ssh/config''' it is possible to assign particular keys to be tried automatically whenever making a connection to that specific host. After adding the following lines to '''~/.ssh/config''', all that's needed is to type <code>ssh ''web1''</code> to connect with the key for that server.
<syntaxhighlight lang="apache" line="1">
Host web1
Hostname 198.51.100.32
IdentitiesOnly yes
IdentityFile /home/fred/.ssh/web_key_ed25519
</syntaxhighlight>
The '''~/.ssh/config''' below uses different keys for ''server'' versus ''server.example.org'', regardless whether they resolve to the same machine. This is possible because the host name argument given to [http://man.openbsd.org/ssh.1 ssh(1)] is not converted to a canonicalized host name before matching.
<syntaxhighlight lang="apache" line="1">
Host server
IdentitiesOnly yes
IdentityFile /home/fred/.ssh/key_a_ed25519
Host server.example.org
IdentitiesOnly yes
IdentityFile /home/fred/.ssh/key_b_ed25519
</syntaxhighlight>
In this example the shorter name is tried first, but of course less ambiguous shortcuts can be made instead. The configuration file gets parsed on a first-match basis. So the most specific rules go at the beginning and the most general rules go at the end.
====Encrypted Home Directories====
When using encrypted home directories the keys must be stored in an unencrypted directory. That means somewhere outside the actual home directory which means [http://man.openbsd.org/sshd.8 sshd(8)] needs to be configured appropriately to find the keys in that special location.
Here is one method for solving the access problem. Each user is given a subdirectory under '''/etc/ssh/keys/''' which they can then use for storing their '''authorized_keys''' file. This is set in the server's configuration file '''/etc/ssh/sshd_config'''
<syntaxhighlight lang="apache" line="1">
AuthorizedKeysFile /etc/ssh/keys/%u/authorized_keys
</syntaxhighlight>
Setting a special location for the keys opens up more possibilities as to how the keys can be managed and multiple key file locations can be specified if they are separated by whitespace. The user does not have to have write permissions for the '''authorized_keys''' file. Only read permission is needed to be able to log in. But if the user is allowed to add, remove, or change their keys, then they will need write access to the file to do that.
One symptom of having an encrypted home directory is that key-based authentication only works when you are already logged into the same account, but fails when trying to make the first connection and log in for the first time.
Sometimes it is also necessary to add a script or call a program from '''/etc/ssh/sshrc''' immediately after authentication to decrypt the home directory.
====Passwordless Login====
One solution for passwordless logins is to still have a passphrase and work with an authentication agent in conjunction with a single-purpose key. Most desktop environments launch an SSH agent automatically these days. It will be visible in the '''SSH_AUTH_SOCK''' environment variable if it is. On accounts with an agent, [http://man.openbsd.org/ssh-add.1 ssh-add(1)] can load private keys into an available agent.
<syntaxhighlight lang="shell-session">
$ ssh-add ~/.ssh/fred_example_org_ed25519
</syntaxhighlight>
Thereafter, the client will automatically check the agent for the key when appropriate. If there are many keys in the agent, it will become necessary to set '''IdentitiesOnly'''. See the above section on using '''~/.ssh/config''' for that. See [[OpenSSH/Cookbook/Public_Key_Authentication#Key-based_Authentication_Using_an_Agent|Key-based Authentication Using an Agent]] below.
Another, riskier, way of allowing passwordless logins is to follow the steps above, but simply do not enter a passphrase when asked for one while creating the key. Note that using keys that lack a passphrase is very risky, so the key files should be very well protected and kept track of, and ideally locked down with a '''command=''' option or '''ForceCommand''' directive on the server. That includes those keys which will only be used as single-purpose keys as described below.
Timely key rotation becomes especially important. In general, it is not a good idea to make a key without a passphrase.
====Requiring Both Keys and a Password====
While users should have strong passphrases for their keys, there is no way to enforce or verify that. Indeed, since neither the private key nor its the passphrase ever leave the client machine there is nothing that the server can do to have any influence over that. Instead, it is possible to require both a key and a password. Starting with OpenSSH 6.2, it is possible for the server to require multiple authentication methods for login using the '''AuthenticationMethods''' directive.
<syntaxhighlight lang="apache" line="1">
AuthenticationMethods publickey,password
</syntaxhighlight>
This example from [http://man.openbsd.org/sshd_config.5 sshd_config(5)] requires that users first authenticate using a key and it only queries for a password if the key succeeds. Thus with that configuration it is not possible to get to the system password prompt without first authenticating with a valid key. Changing the order of the arguments changes the order of the authentication methods.
====Requiring Two or More Keys====
Since OpenSSH 6.8, the server now remembers which public keys have been used for authentication and refuses to accept previously-used keys. This allows a set up requiring that users authenticate using two different public keys, maybe one in the file system and the other in a hardware token.
<syntaxhighlight lang="apache" line="1">
AuthenticationMethods publickey,publickey
</syntaxhighlight>
The '''AuthenticationMethods''' directive, whether for keys or passwords, can also be set on the server under a '''Match''' directive to apply only to certain groups or situations.
====Requiring Certain Key Types For Authentication====
Also since OpenSSH 6.8, the '''PubkeyAcceptedKeyTypes''' directive, later changed to '''PubkeyAcceptedAlgorithms''', can specify which key algorithms are accepted for authentication. Those not in the comma-separated pattern list are not allowed.
<syntaxhighlight lang="apache" line="1">
PubkeyAcceptedAlgorithms ssh-ed25519*,ssh-rsa*,ecdsa-sha2*,sk-ssh-ed25519*,sk-ecdsa-sha2*
</syntaxhighlight>
Either the actual key types or a pattern can be in the list. Spaces are not allowed in the pattern list. The exact list of key types supported for authentication can be found by the '''-Q''' option using the client. The following two lines are equivalent.
<syntaxhighlight lang="shell-session">
$ ssh -Q key-sig | sort
$ ssh -Q PubkeyAcceptedAlgorithms | sort
</syntaxhighlight>
For host-based authentication, it is the '''HostbasedAcceptedAlgorithms''' directive which determines the key types which are allowed for authentication.
===Key-based Authentication Using the AuthorizedKeysCommand Directive===
It is possible to use a program or script to look up public keys rather than keeping them in a static file or files. Any command called by the '''AuthorizedKeysCommand''' directive needs to either produce a syntactically correct public key while returning the exit code for a successful run or else return the exit code for failure. The string sent to '''stdout''' will then be processed as part of the authentication work flow.
Here is a shell script<ref name="janpietmens">{{cite web |url=https://jpmens.net/2025/03/25/authorizedkeyscommand-in-sshd/ |title=SSH keys from a command: sshd's AuthorizedKeysCommand directive |accessdate=2025-04-04 |date=2025-03-25 | author=Jan-Piet Mens }}</ref> at its simplest, without constraints, demonstrating a public key lookup:
<syntaxhighlight lang="shell">
#!/bin/sh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKs/UouletvojgB1YeRZ4MY6iRblQ2ERDuNhQO4tOvdL"
exit 0
</syntaxhighlight>
For authentication to succeed, the script must return exit code 0 (success) after sending the syntactically correct matching public key to '''stdout'''. For the SSH daemon to even run the script in the first place, the script must have the correct file and directory permissions.
Both the '''AuthorizedKeysCommandUser''' directive and '''AuthorizedKeysCommand''' must be used together. The former designates which account the script or program use when run. If set to ''none'' or if it does not refer to a valid account then [http://man.openbsd.org/sshd sshd(8)] will just ignore the command. If '''AuthorizedKeysCommand''' is set, and '''AuthorizedKeysCommandUser''' is left empty or missing, then [http://man.openbsd.org/sshd sshd(8)] won't even run when invoked. The error will be:
<syntaxhighlight lang="text">
AuthorizedKeysCommand set without AuthorizedKeysCommandUser
</syntaxhighlight>
The '''AuthorizedKeysFile''' is always tried first when it is present in the server configuration. The '''AuthorizedKeysCommand''' directive will not even be tried when the authorized keys file can provide a relevant key first.
====A More Detailed Example Using the AuthorizedKeysCommand Directive====
By default the user name trying to log in is passed to the script when no tokens or arguments are provided. Whether or how that information is used is up to the script. The SSH daemon can also pass any combination of the tokens described in the TOKENS section of [http://man.openbsd.org/sshd_config sshd_config(5)] into the program or script being called. Furthermore, the program or script can even be a front end for a database, such as OpenLDAP, or any similar system, as long as '''stdout''' produces a public key.
Below is a more detailed example which uses a local script named '''keyfinder''' run with the account '''keys''' to look up the a public key for certain accounts. First in [http://man.openbsd.org/sshd_config sshd_config(5)] the two directives:
<syntaxhighlight lang="apache" line="1">
AuthorizedKeysCommand /usr/local/sbin/keyfinder %U
AuthorizedKeysCommandUser keys
</syntaxhighlight>
The script below is only a demonstration and a more complex program can call databases or do advanced lookups or heuristics:
<syntaxhighlight lang="shell">
#!/bin/sh
set -e
case $1 in
"1000")
echo "ssh-ed25519 AAAAC3NzaC1lZDIE5AAAAIK89...UT9hz"
;;
"1001")
echo "restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTAAIBvGx...Y0zxV"
;;
"1002")
echo "command=\"/usr/libexec/sftp-server\" ssh-ed25519 AAAAC3NzaC1lZDI1TE5AIPSyY...cPTg3"
;;
*)
exit 1
;;
esac
exit 0
</syntaxhighlight>
The '''AuthorizedKeysCommand''' scripts or programs can return any correctly formatted public key to '''stdout''' for consideration in the authentication process. That includes adding constraints to the keys. Above, the account with the UID 1000 has no constraints, while the account with UID 1001 is quite constrained. Finally, the account with the UID 1002 can only access the SFTP service. See the section "AUTHORIZED_KEYS FILE FORMAT" in [http://man.openbsd.org/sshd sshd(8)] for the full set of possibilities.
===Key-based Authentication Using an Agent===
When an authentication agent, such as [http://man.openbsd.org/ssh-agent.1 ssh-agent(1)], is going to be used, it should generally be started at the beginning of a session and used to launch the login session or X-session so that the environment variables pointing to the agent and its UNIX-domain socket are passed to each subsequent shell and process. Many desktop distros do this automatically upon login or startup.
Starting an agent entails setting a pair of environment variables:
* SSH_AGENT_PID : the process id of the agent
* SSH_AUTH_SOCK : the filename and full path to the UNIX-domain socket
The various SSH and SFTP clients find these variables automatically and use them to contact the agent and try when authentication is needed. However, it is mainly SSH_AUTH_SOCK which is ever used. If the shell or desktop session was launched using [http://man.openbsd.org/ssh-agent.1 ssh-agent(1)], then these variables are already set and available. If they are not available, then it is necessary to either set the variables manually inside each shell or for each application in order to use the agent or else to point to the agent's socket using the directive '''IdentityAgent''' in the client's configuration file.
Once an agent is available, a relevant private key needs to be loaded before the agent can be used. Once in the agent the private key can then be used many times. Private keys are loaded into an agent with [http://man.openbsd.org/ssh-add.1 ssh-add(1)].
<syntaxhighlight lang="shell-session">
$ ssh-add /home/fred/.ssh/mykey_ed25519
Identity added: /home/fred/.ssh/mykey_ed25519 (/home/fred/.ssh/mykey_ed25519)
</syntaxhighlight>
Keys stay in the agent for as long as it is running unless specified otherwise. A timeout can be set either with the '''-t''' option when starting the agent itself or when actually loading the key using [http://man.openbsd.org/ssh-add.1 ssh-add(1)]. In either case, the '''-t''' option will set a timeout interval, after which the key will be purged from the agent.
<syntaxhighlight lang="shell-session">
$ ssh-add -t 1h30m /home/fred/.ssh/mykey_ed25519
Identity added: /home/fred/.ssh/mykey_ed25519 (/home/fred/.ssh/mykey_ed25519)
Lifetime set to 5400 seconds
</syntaxhighlight>
The option '''-l''' will list the fingerprints of all of the identities in the agent.
<syntaxhighlight lang="shell-session">
$ ssh-add -l
256 SHA256:77mfUupj364g1WQ+O8NM1ELj0G1QRx/pHtvzvDvDlOk mykey for task x (ED25519)
3072 SHA256:7unq90B/XjrRbucm/fqTOJu0I1vPygVkN9FgzsJdXbk myotherkey rsa for task y (RSA)
</syntaxhighlight>
It is also possible to remove individual identities from the agent using '''-d''' which will remove them one at a time if identified by file name, but only if the file name is given and without the file name of the private key to be remove, '''-d''' will fail silently. Using '''-D''' instead will remove all of them at once without needing to specify any by name.
By default [http://man.openbsd.org/ssh-add.1 ssh-add(1)] uses the agent connected via the socket named in the environment variable '''SSH_AUTH_SOCK''', if it is set. Currently, that is its only option. However, for [http://man.openbsd.org/ssh.1 ssh(1)] an alternative to using the environment variable is the client configuration directive '''IdentityAgent''' which tells the SSH clients which socket to use to communicate with the agent. If both the environment variable and the configuration directive are available at the same time, then the value in '''IdentityAgent''' takes precedence over what's in the environment variable. '''IdentityAgent''' can also be set to ''none'' to prevent the connection from trying to use any agent at all.
The client configuration directive '''AddKeysToAgent''' can also be useful in getting keys into an agent as needed. When set, it automatically loads a key into a running agent the first time the key is called for if it is not already loaded. Likewise the '''IdentitiesOnly''' directive can ensure that the relevant key is offered on the first try. Rather than typing these out whenever the client is run, they can be added to '''~/.ssh/config''' and thereby added automatically for designated host connections.
====Agent Forwarding====
Agent forwarding is one means of passing through one or more intermediate hosts. However, the '''-J''' option for '''ProxyJump''' would be a safer option. See [[OpenSSH/Cookbook/Proxies_and_Jump_Hosts#Jump_Hosts_--_Passing_Through_a_Gateway_or_Two | Passing Through a Gateway or Two]] in the section on jump hosts about that. With agent forwarding, intermediate machines forward challenges and responses back and forth between the client and the final destination. This comes with some risks but eliminates the need for using passwords or holding keys on any of these intermediate machines.
A main advantage of agent forwarding is that the private key itself is not needed on any remote machine, thus hindering unwanted file system access to it. <ref name="OpenSSH key management, Part 3">{{cite web | url=http://www.ibm.com/developerworks/library/l-keyc3/ | title=Common threads: OpenSSH key management, Part 3 | author=Daniel Robbins | publisher=IBM | date=2002-02-01 | accessdate=2013-04-27}}</ref> Another advantage is that the actual agent to which the user has authenticated does not go anywhere and is thus less susceptible to analysis.
One risk with agents is that they can be re-used to tailgate in if the permissions allow it. Keys cannot be copied this way, but authentication is possible when there are incorrect permissions. Note that disabling agent forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders.
The risks of agent forwarding can be mitigated by confirming each use of a key by adding the '''-c''' option when adding the key to the agent. This requires the SSH_ASKPASS variable be set and available to the agent process, but will generate a prompt on the host running the agent upon each use of the key by a remote system. So if passing through one or more intermediate hosts, it is usually better to instead have the SSH client use stdio forwarding with '''-W''' or '''-J'''.
On the client side agent forwarding is disabled by default and so if it is to be used it must be enabled explicitly. Put the following line in [http://man.openbsd.org/ssh_config.5 ssh_config(5)] to enable agent forwarding for a particular server:
<syntaxhighlight lang="apache" line="1">
Host gateway.example.org
ForwardAgent yes
</syntaxhighlight>
On the server side the default configuration files allow authentication agent forwarding, so to use it, nothing needs to be done there, just on the client side. However, again, it would be preferable to take a look at '''ProxyJump''' instead.
=====Old Style, Somewhat Safer SSH Agent Forwarding=====
The best way to pass through one or more intermediate hosts is to use the '''ProxyJump''' option instead of authentication agent forwarding and thereby not risk exposing any private keys. If authentication agent forwarding must be used, then it would be advisable in the interest of following the principle of least privilege to forward an agent containing the minimum necessary number of keys. There are several ways to solve that.
In version 8.8 and earlier a partial solution is to make a one-off, ephemeral agent to hold just the one key or keys needed for the task at hand. Another partial solution would be to set up a user-accessible service at the operating system level and then use [http://man.openbsd.org/ssh_config.5 ssh_config] for the rest.
Automatically launching an ephemeral agent unique to each session can be done by crafting either a special shell alias or function to launch a single-use agent. Either the function or the alias can be written to require confirmation for each requested signature. The following example is a function is inspired by an updated blog post by Vincent Bernat<ref name="safer-agent-forwarding">{{cite web |url=https://vincent.bernat.ch/en/blog/2020-safer-ssh-agent-forwarding |title=Safer SSH agent forwarding |author=Vincent Bernat|date=2020-04-05 |accessdate=2020-10-04}}</ref> on SSH agent forwarding:
<syntaxhighlight lang="shell-session">
$ agentssh() {
ssh-agent ssh -o AddKeysToAgent=confirm -o ForwardAgent=yes
}
</syntaxhighlight>
Note the use of [http://man.openbsd.org/ssh-agent.1 ssh-agent(1)]. When invoking that alias, the SSH client will be launched with a unique, ephemeral supporting key agent. The alias sets up a new agent, including setting the two environment variables, and then sets two client options while calling the client. This arrangement still checks with [http://man.openbsd.org/ssh_config.5 ssh_config(5)] for other options and settings. When the SSH session is finished the agent which launched it ends and goes away, thus cleaning up after itself automatically.
Another way is to rely on the client's configuration file for some of the settings. Such methods rely mostly on [http://man.openbsd.org/ssh_config.5 ssh_config(5)] but still require an independent method to launch an ephemeral agent because the OpenSSH client is already running by the time it reads the configuration file and is thus not affected by any changes to environment variables caused by the configuration file and it is through the environment variables that contain information about the agent. However, when the path to the UNIX-domain socket used to communicate with the authentication agent is decided in advance then the '''IdentityAgent''' option can point to it once the one-off agent<ref name="wikimedia_ssh_agents">{{cite web |url=https://wikitech.wikimedia.org/wiki/Managing_multiple_SSH_agents#Linux_solutions |title=Managing multiple SSH agents |publisher=Wikimedia|accessdate=2020-04-07}}</ref> is actually launched. The following uses a specific agent's pre-defined socket whenever connecting to either of two particular domains:
<syntaxhighlight lang="apache" line="1">
Host *.wikimedia.org *.wmflabs.org
User fred
IdentitiesOnly yes
IdentityFile %d/.ssh/id_cloud_01
IdentityAgent /run/user/%i/ssh-cloud-01.socket
ForwardAgent yes
AddKeysToAgent yes
</syntaxhighlight>
The '''%d''' stands for the path to the home directory and the '''%i''' stands for the user id (UID) for the current account. In some cases the '''%i''' token might also come in handy when setting the '''IdentityAgent''' option inside the configuration file. Again, be careful when forwarding agents with which keys are in the forwarded agent. See the section "TOKENS" in [http://man.openbsd.org/ssh_config.5 ssh_config(5)] for more such abbreviations.
With those configuration settings, the authentication agent must already be up and running and point to the designated socket prior to starting the SSH client for that configuration to work. Additionally, it should place the socket in a directory which is inaccessible to any other accounts. [http://man.openbsd.org/ssh-agent.1 ssh-agent(1)] must use the '''-a''' option to name the socket:
<syntaxhighlight lang="shell-session">
$ ssh-agent -a /run/user/${UID}/ssh-cloud-01.socket
</syntaxhighlight>
That agent configuration can be launched manually or via a script or service manager. However, in the interests of privacy and security in general, agent forwarding is to be avoided. The configuration directive '''ProxyJump''' is the best alternative and, on older systems, host traversal using '''ProxyCommand''' with [http://man.openbsd.org/nc.1 netcat] are preferable. Again, see the section on [[OpenSSH/Cookbook/Proxies and Jump Hosts|Proxies and Jump Hosts]] for how those methods are used.
=====New Style SSH Agent Destination Constraints=====
From 8.9 onward, [http://man.openbsd.org/ssh-agent.1 ssh-agent(1)] will allow the agent to limit which hosts they will use for authentication as specified by [http://man.openbsd.org/ssh-add.1 ssh-add(1)] using the '''-h''' option. These constraints have been added through two agent protocol extensions and a modification to the public key authentication protocol. This feature may evolve, but for now the result is such that keys for account authentication can be loaded into the agent in four ways:
* no limits on forwarding (not recommended)
* local use only, these will not get forwarded
* forwarding, but only to specific remote hosts
* forwarding to specific remote hosts via specified routes
The intent is that the restrictions fail safely so that they do not allow authentication when one or more hosts in the route lack the needed protocol features. The destinations and routes cannot be modified once the keys are loaded, but multiple routes to the same destination can be loaded and the routes can be any number of hops. If the routes need changing, then the key must be reloaded into the agent with the new route or routes.
The general default for the client is to keep keys in the agent for local use only. However, that can be enforced explicitly by adding the '''-a''' option when starting the client or else setting the '''ForwardAgent''' directive in [http://man.openbsd.org/ssh_config.5 ssh_config(5)] to 'no' in the relevant configuration block.
In order to load keys for unlimited forwarding, which is not the best idea, just add them using [http://man.openbsd.org/ssh-add.1 ssh-add(1)] as normal. Then use the '''-A''' option with the client or set the '''ForwardAgent''' directive in [http://man.openbsd.org/ssh_config.5 ssh_config(5)] to 'yes' in the relevant configuration block.
In order to limit keys for connection only to a specific remote host, or to load keys for connection to a specific remote host with forwarding via one or more intermediate hosts, use the '''-h''' option when loading keys into the agent. Here the one key may be used only to connect to the specific destination:
<syntaxhighlight lang="shell-session">
$ ssh-agent -h server.example.org server.key.ed25519
</syntaxhighlight>
If an intermediate system is passed through, the best way is to use '''ProxyJump''' which is the '''-J''' option for the SSH Client. If agent forwarding must be allowed then the tightest way is to constrain which systems may use the keys, again using the '''-h''' option.
<syntaxhighlight lang="shell-session">
$ ssh-agent -h middle.example.org -h "middle.example.org>server.example.org" server.key.ed25519
</syntaxhighlight>
Multiple steps can be included, even multiple routes. They just have to be enumerated explicitly, though patterns may still be used for the destination hosts as well as specific names. Each host in the chain must support these protocol extensions for the connection to complete.
Any keys designated for forwarding are unusable for authentication on any other hosts than those which have been explicitly identified for forwarding. These permitted hosts are identified by host key or host certificate from the '''known_hosts''' file or another file designated by the '''-H''' option when loading the key with [http://man.openbsd.org/ssh-add.1 ssh-add(1)]. If '''-H''' is not used at the time the keys are loaded into the agent, then the default known hosts file(s) will be used: '''~/.ssh/known_hosts''', '''/etc/ssh/ssh_known_hosts''', '''~/.ssh/known_hosts2''', and '''/etc/ssh/ssh_known_hosts2'''.
In the case of keys, the '''known_hosts''' list must be maintained conscientiously <ref name="ssh-agent-restrictions">{{ cite web | author=Damien Miller|url=https://www.openssh.org/agent-restrict.html | title=SSH agent restriction | publisher=OpenSSH | date=2021-12-16|accessdate=2022-03-06}}</ref>, perhaps with the help of the '''UpdateHostkeys''' and '''CanonicalizeHostname''' client configuration directives. Use of certificates requires the agent to only need to be aware of the Certificate Authority (CA).
Again, see [[OpenSSH/Cookbook/Proxies_and_Jump_Hosts#Jump_Hosts_--_Passing_Through_a_Gateway_or_Two | Passing Through a Gateway or Two]] in the section on jump hosts about a way to pass through one or more intermediate machines without needing to forward an SSH agent.
====Checking the Agent for Specific Keys====
The [http://man.openbsd.org/ssh_add ssh_add(1)] utility's '''-T''' option can test whether a specific private key is available in the agent or not by looking up the matching public key. That can be useful in a shell script.
<syntaxhighlight lang="shell">
#!/bin/sh
key=/home/fred/.ssh/some.key.ed25519.pub
if ssh-add -T ${key}; then
echo "Key ${key} Found"
else
echo "Key ${key} missing"
fi
</syntaxhighlight>
Or it could be done with an alternate syntax just as well either in a script or in an interactive shell sessions,
<syntaxhighlight lang="shell-session">
$ key=/home/fred/.ssh/some.key.ed25519.pub
$ ssh-add -T ${key} && echo "Key found" || echo "Key missing"
</syntaxhighlight>
However, if the desired result would be to add key to the agent then the '''AddKeysToAgent''' client configuration option can ensure that a specific key is added to the SSH agent upon first use during any given login session. That can be done using '''-o AddKeysToAgent=yes''' as a run-time argument, or by modifying [http://man.openbsd.org/ssh_config ssh_config(5)] as appropriate:
<syntaxhighlight lang="apache" line="1">
Host www
HostName www.example.com
IdentityFile %d/.ssh/www.ed25519
IdentitiesOnly yes
AddKeysToAgent yes
</syntaxhighlight>
With those options in the configuration file, the first time <code>ssh www</code> is run the specified key will get added to the agent and remain available.
===Key-based Authentication Using A Hardware Security Token===
While stand-alone keys have been around for a long time, it has been possible since version 8.2 to use keys backed by hardware security tokens, such as OnlyKey, Yubikey, or many others, though the FIDO2 protocol. The Universal 2nd Factor (U2F) authentication is supported directly in OpenSSH through FIDO2 and does not need third party software. At the moment there are two types of hardware backed keys, ECDSA-SK and Ed25519-SK, but only the latest hardware tokens support the latter. If the key Ed25519-SK format is not supported by the token's firmware, then the following error message will be presented when attempts to use that key type are made:
<syntaxhighlight lang="text">
Key enrollment failed: invalid format
</syntaxhighlight>
If supported, either key type can be created with [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)]. The steps are almost identical to creating normal keys but the token must be available to the system (plugged in) first. Then if called for, the token's PIN must be entered and the token touched or otherwise activated. After that, the key creation proceeds as normal. Mind the key type as specified by the '''-t''' option.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -t ed25519-sk -f /home/fred/.ssh/server.ed25519-sk -C "web server for fred"
Generating public/private ed25519-sk key pair.
You may need to touch your authenticator to authorize key generation.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/fred/.ssh/server.ed25519-sk
Your public key has been saved in /home/fred/.ssh/server.ed25519-sk.pub
The key fingerprint is:
SHA256:41wVVDnKJ9gKr2Sj4CFuYMhcNvYebZ6zq0PWyP4rRDo web server
The key's randomart image is:
+[ED25519-SK 256]-+
| .o... |
| .o |
| +.. . |
| = . . ..= . |
|+ + * + So.. o |
|o+.EoO *+oo |
|.o oBo+++o |
| o .=.+. |
| . .=== |
+----[SHA256]-----+
</syntaxhighlight>
Once created, the public and private key files get handled like with any other type of key. But when authenticating, the hardware token must be present and activated when called for.
<syntaxhighlight lang="shell-session">
$ ssh -i /home/fred/.ssh/server.ed25519-sk server.example.org
Enter passphrase for key '/home/fred/.ssh/server.ed25519-sk':
Confirm user presence for key ED25519-SK SHA256:41wVVDnKJ9gKr2Sj4CFuYMhcNvYebZ6zq0PWyP4rRDo
</syntaxhighlight>
The resulting private key file is not actually the key itself but instead a "key handle" which is used by the hardware security token to derive the real private key on demand at the time it is actually used<ref name="OpenBSD_tech_U2F_FIDO">{{cite web |url=https://marc.info/?l=openbsd-tech&m=157376801917387&w=2 |title=OpenSSH U2F/FIDO support in base
|publisher=OpenBSD-Tech Mailing List | date=2019-11-14
|accessdate=2021-03-24}}</ref>. As a result, the hardware-backed private key file is useless without the accompanying hardware token. This also means that these key files are not portable across hardware tokens, say when having multiple tokens in reserve or as backup, even when used by the same account. So when multiple hardware tokens are in use, different key pairs must be generated for each token.
====Hardware Security Token Resident Private Key====
It is possible to store the private key within the token itself, but for the moment it cannot be used directly from inside the token and must first be saved as a file. Also, the key can only be loaded into the FIDO authenticator at the time of creation using the '''-O resident''' option with [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)]. Otherwise, the process is the same as above.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -O resident -t ed25519-sk -f /home/fred/.ssh/server.ed25519-sk -C "web server for fred"
. . .
</syntaxhighlight>
When needed, the resident key can be extracted from the FIDO2 hardware token and saved into a file using the '''-K''' option. At this stage a passphrase can be added to the file, but no passphrase is kept within the token itself, only an optional PIN protects the key there.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -K
Enter PIN for authenticator:
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Saved ED25519-SK key to id_ed25519_sk_rk
$ mv -i id_ed25519_sk_rk /home/fred/.ssh/server.ed25519-sk
</syntaxhighlight>
Since the output file name is fixed, any pre-existing file with that name can get overwritten but there will be a warning first. However, it is not recommended to keep the key on the hardware token because it provides more protection when kept separately.
==Single-purpose Keys==
Tailored single-purpose keys can eliminate use of remote root logins for many administrative activities. A finely tailored '''sudoers''' is needed along with an unprivileged account. When done right, it gives just enough access to get the job done, following the security principle of Least Privilege.
Single-purpose keys are accompanied by use of either the '''ForceCommand''' directive in [http://man.openbsd.org/ssh_config.5 sshd_config(5)] or the '''command="..."''' directive inside the '''authorized_keys''' file. The method is to generate a new key pair, transfer the public key to '''authorized-keys''' on the remote system, and then prepend the appropriate command or script there to the line with the key.
<syntaxhighlight lang="shell-session">
$ grep '^command' ~/.ssh/authorized_keys
command="/usr/local/bin/somescript.sh" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEcgdzDvSebOEjuegEx4W1I/aA7MM3owHfMr9yg2WH8H
</syntaxhighlight>
The '''command="..."''' directive inserted there overrides everything else and ensures that when logging in with just that key only the script '''/usr/local/bin/somescript.sh''' is run. If it is necessary to pass parameters to the script, have a look at the contents of the '''SSH_ORIGINAL_COMMAND''' environment variable and use it in a case statement. Do not ever trust the contents of that variable nor use the contents directly, always indirectly.
Single-purpose keys are useful for allowing only a tunnel and nothing more. The following key will only echo some text and then exit, unless used non-interactively with the '''-N''' option.
<syntaxhighlight lang="shell-session">
$ grep '^command' ~/.ssh/authorized_keys
command="/bin/echo do-not-send-commands" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBzTIWCaILN3tHx5WW+PMVDc7DfPM9xYNY61JgFmBGrA
</syntaxhighlight>
No matter what the user tries while logging in with that key, the session will only echo the given text and then exits. Using the '''-N''' option disables running the remote program, allowing the connection to stay open, allowing a tunnel.
<syntaxhighlight lang="shell-session">
$ ssh -L 3306:localhost:3306 \
-i ~/.ssh/tunnel_ed25519 \
-N \
-l fred \
server.example.com
</syntaxhighlight>
That creates a tunnel and stays connected despite a key configuration which would close an interactive session. See also the '''-n''' or '''-f''' option for [http://man.openbsd.org/ssh.1 ssh(1)].
===Single-purpose Keys to Avoid Remote Root Access===
The easy way is to write a short shell script, place it '''/usr/local/bin/''', and then configure '''sudoers''' to allow the otherwise unprivileged account to run just that script and only that script.
<syntaxhighlight lang="apache" line="1">
%wheel ALL=(root:root) NOPASSWD: /usr/sbin/service httpd stop
%wheel ALL=(root:root) NOPASSWD: /usr/sbin/service httpd start
</syntaxhighlight>
Then the key calls the script using '''command="..."''' inside '''authorized_keys'''. Here the one key starts the web server, the other stops the web server.
<syntaxhighlight lang="shell-session">
$ grep '^command' ~/.ssh/authorized_keys
command="/usr/bin/sudo /usr/sbin/service httpd stop" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEcgdzDvSebOEjuegEx4W1I/aA7MM3owHfMr9yg2WH8H
command="/usr/bin/sudo /usr/sbin/service httpd start" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMidyqZ6OCvbWqA8Zn+FjhpYE6NoWSxVjFnFUk6MrNZ4
</syntaxhighlight>
Complicated programs like [http://linux.die.net/man/1/rsync rsync(1)], [http://man.openbsd.org/tar.1 tar(1)], [http://linux.die.net/man/1/mysqldump mysqldump(1)], and so on require an advanced approach when building a single-purpose key. For them, the '''-v''' option can show exactly what is being passed to the server so that '''sudoers''' can be set up correctly. That way they can be restricted to only access designated parts of the file system. For example, here is what <code>ssh -v</code> shows from one particular usage of [http://linux.die.net/man/1/rsync rsync(1)], note the "Sending command" line:
<syntaxhighlight lang="shell-session">
$ rsync -e 'ssh -v' fred@server.example.org:/etc/ ./backup/etc/
. . .
debug1: Sending command: rsync --server --sender -e.LsfxC . /etc/
. . .
</syntaxhighlight>
That output can then be added to '''sudoers''' so that the key can do only that function.
<syntaxhighlight lang="shell-session">
%backup ALL=(root:root) NOPASSWD: /usr/bin/rsync --server --sender -e.LsfxC . /etc/
</syntaxhighlight>
Then to tie it all together, the account "backup" needs a key:
<syntaxhighlight lang="shell-session">
$ grep '^command' ~/.ssh/authorized_keys
command="/usr/bin/rsync --server --sender -e.LsfxC . /etc/" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMm0rs4eY8djqBb3dIEgbQ8lmdlxb9IAEuX/qFCTxFgb
</syntaxhighlight>
Many of these programs have a '''--dry-run''' or equivalent option. Remember to use it when figuring out the right settings.
===Read-only Access to Keys===
In some cases it is necessary to prevent accounts from being able to changing their own authentication keys. However, such situations may be a better case for using certificates. However, if done with keys it is accomplished by putting the key file in an external directory where the user has read-only access, both to the directory and to the key file. Then the '''AuthorizedKeysFile''' directive assigns where [http://man.openbsd.org/sshd.8 sshd(8)] looks for the keys and can point to a secured location for the keys instead of the default location.
A good alternate location could be a new directory '''/etc/ssh/authorized_keys''' which could store the selected accounts' key files there. The change can be made to apply to only a group of accounts by putting the settings under a '''Match''' directive. The default location for keys on most systems is usually '''~/.ssh/authorized_keys'''.
<syntaxhighlight lang="apache" line="1">
Match Group sftpusers
AuthorizedKeysFile /etc/ssh/authorized_keys/%u
</syntaxhighlight>
Then the permissions there would allow the keys to be read but not written:
<syntaxhighlight lang="shell-session">
$ ls -dhln /etc/ssh/
drwxr-x--x 3 0 0 4.0K Mar 30 22:16 /etc/ssh/authorized_keys/
$ ls -dhln /etc/ssh/*.pub
-rw-r--r-- 1 0 0 173 Mar 23 13:34 /etc/ssh/fred
-rw-r--r-- 1 0 0 93 Mar 23 13:34 /etc/ssh/user1
-rw-r--r-- 1 0 0 565 Mar 23 13:34 /etc/ssh/user2
. . .
</syntaxhighlight>
The keys could even be within subdirectories, though the same restrictions apply regarding permissions and ownership.
For chrooted SFTP, the method is the same to keep the key files out of reach of the accounts:
<syntaxhighlight lang="apache" line="1">
Match Group sftpusers
ChrootDirectory /home
ForceCommand internal-sftp -d %u
AuthorizedKeysFile /etc/ssh/authorized_keys/%u
</syntaxhighlight>
Of course a '''Match''' directive is not essential. The settings could be made to apply to all accounts by putting the directive in the main part of the server configuration file instead.
==Mark Public Keys as Revoked==
Keys can be revoked. Keys that have been revoked can be stored in '''/etc/ssh/revoked_keys''', a file specified in [http://man.openbsd.org/ssh_config.5 sshd_config(5)] using the directive '''RevokedKeys''', so that [http://man.openbsd.org/sshd.8 sshd(8)] will prevent attempts to log in with them. No warning or error on the client side will be given if a revoked key is tried. Authentication will simply progress to the next key or method.
The revoked keys file should contain a list of public keys, one per line, that have been revoked and can no longer be used to connect to the server. The key cannot contain any extras, such as [[OpenSSH/Client_Configuration_Files#Available_key_login_options | login options]] or it will be ignored. If one of the revoked keys is tried during a login attempt, the server will simply ignore it and move on to the next authentication method. An entry will be made in the logs of the attempt, including the key's fingerprint. See the section on [[OpenSSH/Logging_and_Troubleshooting | logging]] for a little more on that.
<syntaxhighlight lang="apache" line="1">
RevokedKeys /etc/ssh/revoked_keys
</syntaxhighlight>
The '''RevokedKeys''' configuration directive is not set in [http://man.openbsd.org/ssh_config.5 sshd_config(5)] by default. It must be set explicitly if it is to be used. This is another situation that might be better fulfilled through using certificate since a validity interval can be set in any combination of seconds, minutes, hours, days, or weeks can be set for certificates while keys are valid indefinitely.
===Key Revocation Lists===
A Key Revocation List (KRL) is a compact, binary form of representing revoked keys and certificates. In order to use a KRL, the server's configuration file must point to a valid list using the '''RevokedKeys''' directive. KRLs themselves are generated with [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)] and can be created from scratch or edited in place. Here a new one is made, populated with a single public key:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -k -f /etc/ssh/revoked_keys -z 1 ~/.ssh/old_key_rsa.pub
</syntaxhighlight>
Here an existing KRL is updated by adding the '''-u''' option:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -u -k -f /etc/ssh/revoked_keys -z 2 ~/.ssh/old_key_dsa.pub
</syntaxhighlight>
Once a KRL is in place, it is possible to test if a specific key or certificate is in the revocation list.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -Q -f /etc/ssh/revoked_keys ~/.ssh/old_key_rsa.pub
</syntaxhighlight>
Only public keys and certificates will be loaded into the KRL. Corrupt or broken keys will not be loaded and will produce an error message if tried. Like with the regular '''RevokedKeys''' list, the public key destined for the KRL cannot contain any extras like login options or it will produce an error when an attempt is made to load it into the KRL or search the KRL for it.
==Verify a Host Key by Fingerprint==
The above examples have been about using keys to authenticate the client to the server. A different context in which keys are used is when the server identifies itself to the client, which happens automatically at the beginning of each non-multiplexed session. In order for that identification to happen the client acquires a public key from the server, usually on or prior to first contact, which it can subsequently use to ensure that it is connecting to the same server again and not an impostor. The default locations for storing these acquired host keys on the client are in '''/etc/ssh/ssh_known_hosts''', if managed by the system administrator, or in '''~/.ssh/known_hosts''' if managed by the client's own account. The format of the contents is a line with a host address and its matching public key. The file is described in detail in the [http://man.openbsd.org/sshd.8 sshd(8)] manual page in the section "SSH_KNOWN_HOSTS FILE FORMAT".
When connecting for the first time to a remote host, the server's host key should be verified in order to ensure that the client is connecting to the right machine and not an impostor or anything else. Usually this verification is done by comparing the fingerprint of the server's host key rather than trying to compare the whole key itself. By default the client will show the fingerprint if the key is not already found in the '''known_hosts''' register.
<syntaxhighlight lang="shell-session">
$ ssh -l fred server.example.org
The authenticity of host 'server.example.org (192.0.32.10)' can't be established.
ECDSA key fingerprint is SHA256:LPFiMYrrCYQVsVUPzjOHv+ZjyxCHlVYJMBVFerVCP7k.
Are you sure you want to continue connecting (yes/no)?
</syntaxhighlight>
That can be compared to a fingerprint received out of band, say by post, e-mail, SMS, courier, and so on. Specifically, the example represents the key's fingerprint as a base64 encoded SHA256 checksum. That is the default style. The fingerprint can also be displayed as an MD5 hash in hexadecimal instead by passing the client's '''FingerprintHash''' configuration directive as a runtime argument or setting it in [http://man.openbsd.org/ssh_config.5 ssh_config(5)].
<syntaxhighlight lang="shell-session">
$ ssh -o FingerprintHash=md5 host.example.org
The authenticity of host 'host.example.org (192.0.32.203)' can't be established.
RSA key fingerprint is MD5:10:4a:ec:d2:f1:38:f7:ea:0a:a0:0f:17:57:ea:a6:16.
Are you sure you want to continue connecting (yes/no)?
</syntaxhighlight>
But the default in new versions is SHA256 in base64 has a lower chance of collision.
In OpenSSH 6.7 and earlier, the client showed fingerprints as a hexadecimal MD5 checksum instead a of the base64-encoded SHA256 checksum currently used:
<syntaxhighlight lang="shell-session">
$ ssh -l fred server.example.org
The authenticity of host 'server.example.org (192.0.32.10)' can't be established.
RSA key fingerprint is 4a:11:ef:d3:f2:48:f8:ea:1a:a2:0d:17:57:ea:a6:16.
Are you sure you want to continue connecting (yes/no)?
</syntaxhighlight>
Another way of comparing keys is to use the ASCII art visual host key. See further below about that.
===Downloading keys===
Even though a host’s key is usually displayed for review the first time the SSH client tries to connect, it can also be fetched on demand at any time using [http://man.openbsd.org/ssh-keyscan.1 ssh-keyscan(1)]:
<syntaxhighlight lang="shell-session">
$ ssh-keyscan server.example.org
# server.example.org:22 SSH-2.0-OpenSSH_10.6
server.example.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEWKepJgkC2XTG5cAr2Nyew6hOp5AjG7vi2RYFtPWqN3bo5XGuCX2d2YVyn++/2PtyMYBaKWyFpCNTT9X0F1Epg=
# server.example.org:22 SSH-2.0-OpenSSH_10.6
server.example.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDKyERe8k+fnsrt4JrcLD3AW0kXj90r9ybrEZuY/CTrXIqYSizO335SxGJoWrKijaRy8htuueMkmNfxxhnBPoAjul/4T/FCRGKaV0jC96xYNnKcXbnXxSLVQ0OW2EIPvQhw/TU/G3vEqtiRYGyaNcZS6xrnVv3xuPuvVC1VRKspNLEq7zfvToC0OB89X5DIbvBbHY13PjJ0NrDdX3sSA8lxPsYagBuDIvyxH0S4Z5fQHeYrdvENS5zX6LwJeMeGSOqDuD0Zb4hpKxhaGVwP5e435VcFuImbFaDPM4w71PzaSUEj+tnUA0mGDoLiCrpW3txkJszog9lN3C/nLGghFaT7ajrfH55qut81JnvdhMju9+SzxrKPJmtQZfKVLIc4whEbtFsPCdm2bstz7ROWxTJ3t/Vr8/QVm2G2aY4FHuPwo2jUQDbQA7mCV+fe1sADy2jLzGhn1TCeYvWSv5PNJAT97IrLfD3+0Uo+qJD/6CU7F8oabj1Ql2H8fPN5kGSWfkM=
# server.example.org:22 SSH-2.0-OpenSSH_10.6
server.example.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJo5gc4VrxVQ5apAOd7qK6UqGlLMpWOPuunjB53JBN2s
# server.example.org:22 SSH-2.0-OpenSSH_10.6
# server.example.org:22 SSH-2.0-OpenSSH_10.6
# server.example.org:22 SSH-2.0-OpenSSH_10.6
server.example.org ssh-mldsa44-ed25519 AAAAE3NzaC1tbGRzYTQ0LWVkMjU1MTkAAAVAyIw5r9FaniSYqBX0yd9vgBz5nCkebaQlMQN9N0p//Ukfn/CnZ3YtZWn6pUGjDM85/bqdL1gqah1OLfnl1eHk0qvTACrym07uKaMLoEHuakIXHbTi/ELPRoRP3F+DpEgjtYSjLc/fJiobRMgSvmLJxTUzZTStsqWAL1L9/1zuwHEngR+THpUcCSTi6KKkYcQiWGOFwpO22VdiuOg+zdQSH+9jW6eXYk1z81KU6UlHZps8zVrlqCd3FDDghgbH5U8DcGN2t6GvVfn6jFjpEk0ouj0of3/7010eRXjnv3QSbprCpMq73lAemQM+3LvTtrMBhFWNhCXhyOHfO1Yq7c8xaOwlFK78PlERjdHTvVJaCaDFDy7Pg9I+wxv+uC+W0wtzJ2S1y9XCYUgJo9yEiIGuSZdhMkYUwMnXLzQMm44hQOW153pdlHWze3kESCLg/LJf9RbUoSB43t6rghSHEiUkIi5TtCtFZ4nAGeH+wVwlB9Fwog5uZuJN1FYuuY5sSrLHJAQDUwudkdak0ifOhtPtsM/ClYr3baolQ/qi0ABYUVLKSV5b+A5DlTXa23zc7JAXm2YVfkWpOfVJG4TY81wrJoDumsd1y3XaH28/4QbADsZCE3wYsBou8ff0xKgPu8xm2K+sYSmzUbBGprArAQA0LtIDGNGqrb4JsZ1ru+viwzfSlxV7Nz7ZrSw6h+Ddq4J9A6oKXy6YS3uf1GFOtBQm6JfuyMHQEEUtYZrU4UK3C/fKHx9vjuw7YdhsL8JRgxbF14qJLFizkmVbK2e6aWEE4iCqLLLlZ0dC2peYUUqyGb9PsW7sewYzGbipzPpQ/GobRT3Obc3Gmu8P386pDGR7hmkOpFmVwIcfc431cUmZixK7CkPxzUvfaAAQkmNs/p4eNNoP0gq/xPGsV14/heULbWp/njGWk1ysjjGxP6YMwHcEZpUdSGbD05zbL0KkMtmKsr8yuJYjdVAgtH2bVAvrxXRXLgavmm97VYYq1A9rOYiQFlMrKRg6yZhT10Xt8Hukf6ySLk+fieFc3nH99YeysoA5rsfp9kdXr65GpwrBerZlf/20ZLJ7s4xaYb9SukR/8tiPt9iAVQjqPdb0MseZVrzhKo/jK44JHbHejHMoMMs7etPAS5TIjHxcJTP66B3eO9A0l2fAage2ka7ehTnHivxD3EE9KnqYBjIHDU7o6dTrX7UyQsdhax9bPKEL7OEtm6hXXfwzy4GdqGi124BclFAF0LeBSvBUgmSKIn3wfzJx/XXbt512eOn3WZk2v0TsiteH9kPEgDxVkUykawg2tleak9rTFMzYpDZRHvZD7uHWUZ8ktr2FEKWgq7/1Q2c80Z6H75VK9l1d3KZuoiWoF1s73R7ZAM+CWSrR+S5h+3AhYubDKPa/af+Lnlqe6ocVTqQPYaaRz25/cLBg6pgbdh18Ru6h3ljG2KiysyXeuoEoM5xVYtdIW7l9NeKDpGbZPAOqywXUpK+UCGjumIl7c48KCTIYcdtolnEbfVNBh0LRuftcVI+uF9cvQ0XacaNbgkYJYCjv4VR/n58EJ1b0c7tQBrVqMjDjIUKGhCMQqAeD3g75jeD60bBmVNPrq8RK+zH5VIa5eaBs3eitN98eVzd4b6UYTQd1QxLQZMrhQf4InRj39TZfGvQR5SXlLZQlweVHYkMps3IKbs3B3DCqlWCPUAnTAJBAG7HqWEYr5uEaKBawBSAx9jCQz00T+bp8KXpkOPzZCD6dfEfpHY6Rv6kmGJkiPUCb2hoX145HrS357G12+wDxKLN833oPVC0z
</syntaxhighlight>
Once a key is acquired, its fingerprint can be shown using [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)] to read from '''stdin'''. This can be done directly with a pipe.
<syntaxhighlight lang="shell-session">
$ ssh-keyscan server.example.org | ssh-keygen -l -f -
3072 SHA256:tQlw3vy325KrQibndP3gLS/YXUZjTLVA5yDFpg/Bb6I server.example.org (RSA)
256 SHA256:snnAtb/9csdy0BGhPjdg+VNWqN5bxCa/ge4C6zZ8muk server.example.org (ECDSA)
256 SHA256:agRZDZn8awhQ+tc19Ip/whkHoV33Ln2REO7v1kcYbdU server.example.org (ED25519)
512 SHA256:3Wdc6GbLIcc5mbuF2mhhokhARdMLuMK+ESRfJ+sM0QE server.example.org (MLDSA44-ED25519)
</syntaxhighlight>
If there is more than one public key type is available from the server on the port polled, then [http://man.openbsd.org/ssh-keyscan.1 ssh-keyscan(1)] will fetch each of them. If there is more than one key fed via '''stdin''' or a file, then [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)] will process them in order. Prior to OpenSSH 7.2 manual fingerprinting was a two step process, the key was read to a file and then processed for its fingerprint.
<syntaxhighlight lang="shell-session">
$ ssh-keyscan -t ed25519 host.example.org > key.pub
# host.example.org SSH-2.0-OpenSSH_6.8
$ ssh-keygen -lf key.pub
256 SHA256:ZmS+IoHh31CmQZ4NJjv3z58Pfa0zMaOgxu8yAcpuwuw host.example.org (ED25519)
</syntaxhighlight>
Note that some output from [http://man.openbsd.org/ssh-keyscan.1 ssh-keyscan(1)] is sent to '''stderr''' instead of '''stdout'''.
A hash, or fingerprint, can be generated manually with [http://linux.die.net/man/1/awk awk(1)], [http://linux.die.net/man/1/sed sed(1)] and [http://linux.die.net/man/1/xxd xxd(1)], on systems where they are found.
<syntaxhighlight lang="shell-session">
$ awk '{print $2}' key.pub | base64 -d | md5sum -b | sed 's/../&:/g; s/: .*$//'
$ awk '{print $2}' key.pub | base64 -d | sha256sum -b | sed 's/ .*$//' | xxd -r -p | base64
</syntaxhighlight>
It is possible to find all hosts from a file which have new or different keys from those in '''known_hosts''', if the host names are in clear text and not stored as hashes.
<syntaxhighlight lang="shell-session">
$ ssh-keyscan -t ed25519,mldsa44-ed25519 -f ssh_hosts | \
sort -u - ~/.ssh/known_hosts | \
diff ~/.ssh/known_hosts -
</syntaxhighlight>
====Using ssh-keyscan(1) with ssh_config(5)====
The utility [http://man.openbsd.org/ssh-keyscan.1 ssh-keyscan(1)] does not parse [http://man.openbsd.org/ssh_config.5 ssh_config(5)]. That is in part to keep the code base simple. There are a lot of configuration options which would be complicated to implement, including but not limited to '''ProxyJump''', '''ProxyCommand''', '''Match''', '''BindInterface''', and '''CanonicalizeHostname'''<ref name="keyscan">{{cite mailing list |url=https://lists.mindrot.org/pipermail/openssh-unix-dev/2023-March/040605.html | title=Why does ssh-keyscan not use .ssh/config? |publisher=mindrot.org | access-date=2023-03-01 | date=2023-03-01 | mailing-list=OpenSSH UNIX-dev | first=Damien | last=Miller }}</ref> . Resolving host names via the client configuration file can be done by wrapping the utility in a short shell function:
<syntaxhighlight lang="shell">
my-ssh-keyscan() {
for host in "$@" ; do
ssh-keyscan $(ssh -G "$host" | awk '/^hostname/ {print $2}')
done
}
</syntaxhighlight>
That shell function uses the '''-G''' option of [http://man.openbsd.org/ssh.1 ssh(1)] to resolve each host name using [http://man.openbsd.org/ssh_config.5 ssh_config(5)] and then check the resulting host name for SSH keys.
===ASCII Art Visual Host Key===
An ASCII art representation of the key can be displayed along with the SHA256 base64 fingerprint:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -l -v -f key
256 SHA256:BClQBFAGuz55+tgHM1aazI8FUo8eJiwmMcqg2U3UgWU www.example.org (ED25519)
+--[ED25519 256]--+
|o+=*++Eo |
|+o .+.o. |
|B=.oo. . |
|*B.=.o . |
|= B * S |
|. .@ . |
| +..B |
| *. o |
| o.o. |
+----[SHA256]-----+
</syntaxhighlight>
In OpenSSH 6.7 and earlier the fingerprint is in MD5 hexadecimal form.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -l -v -f key
2048 37:af:05:99:e7:fb:86:6c:98:ee:14:a6:30:06:bc:f0 www.example.net (RSA)
+--[ RSA 2048]----+
| o |
| o . |
| o o |
| o + |
| . . S |
| E .. |
| .o.* .. |
| .*=.+o |
| ..==+. |
+-----------------+
</syntaxhighlight>
==More on Verifying SSH Keys==
Keys on the client or the server can be verified against known good keys by comparing the base64-encoded SHA256 fingerprints.
===Verifying Stray Client Keys===
Sometimes is is necessary to compare two uncertain key files to check if they are part of the same key pair. However, public keys are more or less disposable. So the easy way in such situations on the client machine is to just rename or erase the old, problematic, public key and replace it with a new one generated from the existing private key.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -y -f ~/.ssh/my_key_ed25519
</syntaxhighlight>
But if the two parts must really be compared, it is done in two steps using [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)]. First, a new public key is re-generated from the known private key and used to make a fingerprint to '''stdout'''. Next, the fingerprint of the unknown public key is generated for comparison. In this example, the private key '''my_key_a_ed25519''' and the public key '''my_key_b_ed25519.pub''' are compared:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -y -f my_key_a_ed25519 | ssh-keygen -l -f -
$ ssh-keygen -l -f my_key_b_ed25519.pub
</syntaxhighlight>
The result is a base64-encoded SHA256 checksum for each key with the one fingerprint displayed right below the other for easy visual comparison. Older versions don't support reading from '''stdin''' so an intermediate file will be needed then. Even older versions will only show an MD5 checksum for each key. Either way, automation with a shell script is simple enough to accomplish but outside the scope of this book.
===Verifying Server Keys===
Reliable verification of a server's host key must be done when first connecting. It can be necessary to contact the system administrator who can provide it out of band so as to know the fingerprint in advance and have it ready to verify the first connection.
Here is an example of the server's Ed25519 key being read and its fingerprint shown as SHA256 base64:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub
256 SHA256:bFzzouaWmE5HuZIv+YnGUYI2q06i6M43V+6jMU3LHpA root@server.example.org (ED25519)
</syntaxhighlight>
And here the corresponding ECDSA key is read, but shown as an MD5 hexadecimal hash:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -E md5 -l -f /etc/ssh/ssh_host_ecdsa_key.pub
256 MD5:ed:d2:34:b4:93:fd:0e:eb:08:ee:b3:c4:b3:4f:28:e4 root@server.example.net (ECDSA)
</syntaxhighlight>
Prior to 6.8, the fingerprint was expressed as an MD5 hexadecimal hash:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub
2048 MD5:e4:a0:f4:19:46:d7:a4:cc:be:ea:9b:65:a7:62:db:2c root@server.example.net (RSA)
</syntaxhighlight>
It is also possible to use [http://man.openbsd.org/ssh-keyscan.1 ssh-keyscan(1)] to get keys from an active SSH server. However, the fingerprints still needs to be verified out of band.
====Warning: Remote Host Identification Has Changed!====
If a server's key does not match what the client finds has been recorded in either the system's or the local account's '''authorized_keys''' files, then the client will issue a warning along with the fingerprint of the suspicious key.
<pre>
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:bFzzouaWmE5HuZIv+YnGUYI2q06i6M43V+6jMU3LHpA.
Please contact your system administrator.
Add correct host key in /home/fred/.ssh/known_hosts to get rid of this message.
Offending ED25519 key in /home/fred/.ssh/known_hosts:11
Host key for server.example.org has changed and you have requested strict checking.
Host key verification failed.
</pre>
Three reasons for the warning are common.
One reason is that the server's keys were replaced, often because the server's operating system was reinstalled without backing up the old keys. Another reason can be when the system administrator has phased out deprecated or compromised keys. However that can be planned better and if there is time to plan the migration, new keys can just be added to the server and have the clients use the '''UpdateHostKeys''' option so that the new keys are accepted if the old keys match. A third situation is when the connection is made to the wrong machine, such as when the remote system changes IP addresses because of dynamic address allocation.
In all three cases where the key has changed there is only one thing to do: contact the system administrator and verify the key. Ask if the OpenSSH-server was recently reinstalled, or was the machine restored from an old backup? Keep in mind that the system administrator may be you yourself in some cases.
The case which is rather rare but serious enough that it should be ruled out for sure is that the wrong machine is part of a man-in-the-middle attack.
In all four cases, an authentic key fingerprint can be acquired by any method where it is possible to verify the integrity and origin of the message, for example via PGP-signed e-mail. If physical access is possible, then use the console to get the right fingerprint. Once the authentic key fingerprint is available, return to the client machine where you got the error and remove the old key from '''~/.ssh/known_hosts'''
<syntaxhighlight lang="shell-session">
$ ssh-keygen -R server.example.org
</syntaxhighlight>
Then try logging in, but compare the key fingerprints first and proceed if and '''only''' if the key fingerprint matches what you received out of band. If the key fingerprint matches, then go through with the login process and the key will be automatically added. If the key fingerprint does not match, stop immediately and figure out what you are connecting to. It would be a good idea to get on the phone, a real phone not a computer phone, to the remote machine's system administrator or the network administrator.
===Multiple Keys for a Host, Multiple Hosts for a Key in known_hosts===
Multiple host names or IP addresses can use the same key in the '''known_hosts''' file by using pattern matching or simply by listing multiple systems for the same key. That can be done in either the global list of keys in '''/etc/ssh/ssh_known_hosts''' and the local, account-specific lists of keys in each account's '''~/.ssh/known_hosts''' file. Labs, computational clusters, and similar pools of machines can make use of keys in that way. Here is a key shared by three specific hosts, identified by name, one host per line:
<pre>
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
server2 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
server3 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
</pre>
Or a range can be specified by using globbing to a limited extent in either '''/etc/ssh/ssh_known_hosts''' or '''~/.ssh/known_hosts'''.
<pre>
172.19.40.* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
</pre>
Conversely, a pool of servers might have multiple keys for the same address. In that case, it is necessary to make multiple entries in either '''/etc/ssh/ssh_known_hosts''' or '''~/.ssh/known_hosts''' for each key.
<pre>
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBrsIIaDl/bJ40vyprvF+HYAq+kE2jWUsOt+WqIheaBw fred@desk.example.org
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC2CgwWTPH/qZDeHmW7ZUea18wa9As7Txq3P5dXCfoXj fred@desk.example.org
</pre>
Thus in order to get a pool of servers to share a pool of keys, each server-key combination must be added manually to the '''known_hosts''' file:
<pre>
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBrsIIaDl/bJ40vyprvF+HYAq+kE2jWUsOt+WqIheaBw fred@desk.example.org
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC2CgwWTPH/qZDeHmW7ZUea18wa9As7Txq3P5dXCfoXj fred@desk.example.org
server2 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICPSs4OR2LT89mv2tM4TKqeVhh4XvoLQ77MSBmjyrMGm fred@desk.example.org
server2 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHChTzAoJr53A7VP1BdMHqLTFK5cz/2Vc065+VcpP4VA fred@desk.example.org
server2 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHP+4BvU4DzwYQgznARxx/qyBWmu49PAywHwDRgslRaM fred@desk.example.org
</pre>
Though upgrading to certificates might be a more appropriate approach that manually updating lots of keys.
===Another way of Dealing with Dynamic (roaming) IP Addresses===
It is possible to manually point to the right key using '''HostKeyAlias''' either as part of [http://man.openbsd.org/ssh_config.5 ssh_config(5)] or as a runtime parameter. Here the key for machine ''Foobar'' is used to connect to host 192.168.11.15
<syntaxhighlight lang="shell-session">
$ ssh -o StrictHostKeyChecking=accept-new \
-o HostKeyAlias=foobar \
192.168.11.15
</syntaxhighlight>
This is useful when DHCP is not configured to try to keep the same addresses for the same machines over time or when using certain stdio forwarding methods to pass through intermediate hosts.
===Host Key Update and Rotation in known_hosts===
A protocol extension to rotate weak public keys out of '''known_hosts''' has been in OpenSSH from version 6.8<ref name="djm_rotation">
{{cite web
| title=Key rotation in OpenSSH 6.8+
| author=Damien Miller
| url=http://blog.djm.net.au/2015/02/key-rotation-in-openssh-68.html
| date=2015-02-01
| publisher=DJM's Personal Weblog
| accessdate=2016-03-05
}}
</ref> and later. With it the server is able to inform the client of all its host keys and update '''known_hosts''' with new ones when at least one trusted key already known. This method still requires the private keys be available to the server <ref name="djm_rotation_redux">
{{cite web
| title=Hostkey rotation, redux
| author=Damien Miller
| url=http://blog.djm.net.au/2015/02/hostkey-rotation-redux.html
| date=2015-02-17
| publisher=DJM's Personal Weblog
| accessdate=2016-03-05
}}
</ref> so that proofs can be completed. In [http://man.openbsd.org/ssh_config.5 ssh_config(5)], the directive '''UpdateHostKeys''' specifies whether the client should accept updates of additional host keys from the server after authentication is completed and add them to '''known_hosts'''. A server can offer multiple keys of the same type for a period before removing the deprecated key from those offered, thus allowing an automated option for rotating keys as well as for upgrading from weaker algorithms to stronger ones. See also [https://datatracker.ietf.org/doc/html/rfc4819 RFC 4819: Secure Shell Public Key Subsystem] about key management standards.
==Converting Between SSH Key Formats==
OpenSSH has its own format for keys which it uses by default when new keys are made. However, other SSH clients and servers may use other formats such as [https://www.rfc-editor.org/rfc/rfc4716 RFC 4716], [https://www.rfc-editor.org/rfc/rfc5958 PKCS8], or [https://www.rfc-editor.org/rfc/rfc1421 PEM]. Any of these can be converted to the default OpenSSH format by [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)]. The default to format to try to convert from is RFC4716. The utility [https://linux.die.net/man/1/puttygen puttygen(1)] makes keys in that format for [https://linux.die.net/man/1/putty putty(1)] and they need conversion when used with OpenSSH's server.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -i -f /var/tmp/key_public.ppk
</syntaxhighlight>
However, you can use the '''-m''' option to specify either that format explicitly or else choose another one to convert from.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -i -m RFC4716 -f /var/tmp/key_public.ppk
$ ssh-keygen -i -m PKCS8 -f /var/tmp/key_public.ppk
</syntaxhighlight>
Both examples above are for importing public keys into OpenSSH's own format.
By default OpenSSH will write newly-generated keys in its own format, so the '''-m''' option is obligatory to produce public keys in another format.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -e -m PKCS8 -f ~/.ssh/key.pub
</syntaxhighlight>
It is not yet possible to export private keys from the OpenSSH format to one of the other formats using the '''-e''' option. Even if a private key is specified as input, a public key is produced:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -e -m RFC4716 -f ~/.ssh/key
</syntaxhighlight>
Not all key types are supported by all key formats.
It is also possible to use export to display the key pair as a traditional hex dump.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -e -m hexdump -f ~/.ssh/key
Enter passphrase for "key":
Public ED25519 key:
buffer len = 51
0000: 00 00 00 0b 73 73 68 2d 65 64 32 35 35 31 39 00 ....ssh-ed25519.
0016: 00 00 20 b0 c5 cc 2c cb d8 8b 8d 75 80 eb e6 e9 .. ...,....u....
0032: 2c f4 36 08 7b 5b ad ad 0b 54 4f 7f 21 9d 1b e8 ,.6.{[...TO.!...
0048: 9e e0 32 ..2
Private ED25519 key:
buffer len = 119
0000: 00 00 00 0b 73 73 68 2d 65 64 32 35 35 31 39 00 ....ssh-ed25519.
0016: 00 00 20 b0 c5 cc 2c cb d8 8b 8d 75 80 eb e6 e9 .. ...,....u....
0032: 2c f4 36 08 7b 5b ad ad 0b 54 4f 7f 21 9d 1b e8 ,.6.{[...TO.!...
0048: 9e e0 32 00 00 00 40 e1 c3 a2 4d d9 89 49 72 9b ..2...@...M..Ir.
0064: 86 72 6c 07 17 1b 40 4f 62 50 62 45 4f 4c cf cf .rl...@ObPbEOL..
0080: 57 8b 9d c0 04 8f 9b b0 c5 cc 2c cb d8 8b 8d 75 W.........,....u
0096: 80 eb e6 e9 2c f4 36 08 7b 5b ad ad 0b 54 4f 7f ....,.6.{[...TO.
0112: 21 9d 1b e8 9e e0 32 !.....2
</syntaxhighlight>
<noinclude>
== References ==
{{reflist}}
{{OpenSSH/TOC|mini}}
</noinclude>
{{BookCat}}
{{status|100%}}
kkk31yd5k7dz32rkdex1oja9rwzg4fb
4675819
4675818
2026-10-13T12:29:24Z
Larsnooden
430753
space
4675819
wikitext
text/x-wiki
<noinclude>{{simple chapter navigation|previous=File Transfer with SFTP|next=Certificate-based Authentication}}</noinclude>
Authentication keys can improve efficiency, if done properly. As a bonus advantage, the passphrase and private key never leave the client<ref name="RFC4252§7">{{cite web |url=https://tools.ietf.org/html/rfc4252#section-7 |title=The Secure Shell (SSH) Authentication Protocol |publisher=IETF |year=2006| accessdate=2015-05-06}}</ref>. Key-based authentication is generally recommended for outward facing systems so that password authentication can be turned off.
==Key-based authentication==
OpenSSH can use public key cryptography for authentication. In public key cryptography, encryption and decryption are asymmetric. The keys are used in pairs, a public key to encrypt and a private key to decrypt. The [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)] utility can make RSA, Ed25519, MLDSA44-Ed25519, ECDSA, Ed25519-SK, or ECDSA-SK keys for authenticating. Even though DSA keys can still be made, being exactly 1024 bits in size, they are no longer recommended and should be avoided. RSA keys are allowed to vary from 1024 bits on up. The default is now 3072. However, there is only limited benefit after 2048 bits and that makes elliptic curve algorithms preferable. ECDSA can be 256, 384 or 521 bits in size. Ed25519, Ed25519-SK, and ECDSA-SK keys each have a fixed length of 256 bits. Shorter keys are faster, but less secure. Longer keys are much slower to work with but provide better protection, up to a point.
Keys can be named to help remember what they are for. Because the key files can be named anything it is possible to have many keys each named for different services or tasks. The comment field at the end of the public key can also be useful in helping to keep the keys sorted, if you have many of them or use them infrequently.
The process of key-based authentication uses these keys to make a couple of exchanges using the keys to encrypt and decrypt some short message. At the start, a copy of the client's public key is stored on the server and the client's private key is on the client, both stay where they are. The private key never leaves the client. As the client first contacts the server, the server responds by using the client's public key to encrypt a random number and return that encrypted random number as a challenge to the client. The client responds to the challenge by using the matching private key to decrypt the message and extract the random number. The client then makes an MD5 hash of the session ID along with the random number from the challenge and returns that hash to the server. The server then makes its own hash of the session ID and the random number and compares that to the hash returned by the client. If there is a match, the login is allowed. If there is not a match, then the next of any public keys on the server registered as belonging to the same account is tried until either a match is found or all the keys have been tried or the maximum number of failures has been reached. <ref name="How Key Challenges Work">{{cite web | url=http://www.unixwiz.net/techtips/ssh-agent-forwarding.html#chal | title=An Illustrated Guide to SSH Agent Forwarding | author=Steve Friedl | date=2006-02-22 | accessdate=2013-04-27 | publisher=Unixwiz.net }}</ref>
When an agent is used on the client side to manage authentication, the process is similar. The difference is that [http://man.openbsd.org/ssh.1 ssh(1)] passes the challenge off to the agent which then calculates the response and passes it back to [http://man.openbsd.org/ssh.1 ssh(1)] which then passes the agent's response back to the server.
===Basics of Public Key Authentication===
A matching pair of SSH keys, one public and one private, is needed for public key authentication. The [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)] utility is used to make such a key pair. Out of that pair the public key must be properly stored on the remote host before using key-based authentication. The default location for it is the designated '''authorized_keys''' file, usually one such file resides inside each remote user account. The private key stays stored safely on the client.
Once the keys have been prepared and the remote account configured, they can be used for login. Before starting, there must already be an account on the remote system. The details of doing that are outside of the scope of this book. However, once you have a remote account, there are four steps to set up key-based authentication for it:
'''1''') Prepare a directory on the client (say a laptop or a desktop) where the keys will stay, if there isn't one already. For example, if the '''.ssh''' directory is not on the client machine, create it and set the permissions correctly. It is important that it not be writable by any account except its owner:
<syntaxhighlight lang="shell-session">
$ mkdir ~/.ssh/
$ chmod 0700 ~/.ssh/
</syntaxhighlight>
'''2''') Create a key pair inside the designated directory. The example here creates an Ed25519 key pair in the directory '''~/.ssh'''. The option '''-t''' decides the key type and the option '''-f''' assigns the key file a name. It is good to give key files descriptive names, especially if larger numbers of keys are managed. Below, the public key will be named '''fred_example_org_ed25519.pub''' and the private key will be called '''fred_example_org_ed25519'''. Lastly, the '''-C''' option is used to embed a descriptive comment inside the private key itself. The comment is useful for figuring out later what the key is for when one has many keys or a lot of time has passed or both.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -t ed25519 -f ~/.ssh/fred_example_org_ed25519 \
-C "from fred's laptop to server.example.org"
</syntaxhighlight>
Be sure to enter a solid passphrase so that the private key gets encrypted using 128-bit AES. That way the private key can only be read or used when the passphrase is given.
Ed25519, Ed25519-SK, and ECDSA-SK keys have fixed lengths. For RSA and ECDSA keys, the '''-b''' option sets the number of bits used for those kinds of keys.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -o -b 4096 -t rsa -f ~/.ssh/fred_example_org_rsa \
-C "from fred's laptop to server.example.org"
</syntaxhighlight>
Since 6.5 a new private key format is available using a [http://man.openbsd.org/bcrypt.3 bcrypt(3)] key derivative function (KDF) to better protect keys at rest. This new format is always used for Ed25519 keys, and sometime in the future will be the default for all keys. But for right now it may be requested when generating or saving existing keys of other types via the '''-o''' option in [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)].
Details of the new format are found in the source code in the file '''PROTOCOL.key'''.
'''3''') Get the keys to the right places. Transfer only the public key to remote machine. The following assume the default locations for the authorized keys as specified in the server's configuration file by the '''AuthorizedKeysFile''' directive.
'''3a''') If the utility <code>ssh-copy-id</code> exists, and if password authentication is allowed, then it can be used to put the public key into place on the remote system. The ''.pub'' is optional here, the script will figure it out if omitted.
<syntaxhighlight lang="shell-session">
$ ssh-copy-id -i ~/.ssh/fred_example_org_ed25519 fred@server.example.org
</syntaxhighlight>
If that script was successful in transferring the public key, then go on to step 4 below and test the key. If not, then try transferring the public key manually as described in step 3b next.
'''3b''') Or the public key can be put in place manually on the remote machine. For that the remote '''.ssh''' directory is needed, and within that a special file to store the public keys, the default file name is '''authorized_keys'''. If either the '''authorized_keys''' file or '''.ssh''' directory do not exist on the remote machine, they need to be created.
<syntaxhighlight lang="shell-session">
$ mkdir -m 700 ~/.ssh/
$ touch ~/.ssh/authorized_keys
$ chmod 0600 ~/.ssh/authorized_keys
$ nano -w ~/.ssh/authorized_keys
</syntaxhighlight>
Then any editor which does not wrap long lines can be used to add the public key. However the '''authorized_keys''' file is edited to add the key, the key itself must be in the file whole and unbroken on a single line. For example, [http://linux.die.net/man/1/nano nano(1)] can be started with the '''-w''' option to prevent wrapping of long lines. (Another way to set line wrapping permanently in [http://linux.die.net/man/1/nano nano(1)] is by editing [http://linux.die.net/man/5/nanorc nanorc(5)].)
If the key pair is not already on the client, transfer both the public and private keys there. It is usually best to keep both the public and private keys together in the directory '''~/.ssh/''', though the public key is not always needed on the client after this step and could even be regenerated if it is ever needed again.
'''4''') Test the keys
While remaining logged in via the first terminal, use the client system to open another window and in it start another SSH session and try authenticating to the remote machine from the client using the private key.
<syntaxhighlight lang="shell-session">
$ ssh -i ~/.ssh/fred_example_org_ed25519 -l fred server.example.org
</syntaxhighlight>
The option '''-i''' tells [http://man.openbsd.org/ssh.1 ssh(1)] which private key to try.
Only after verifying that the key-based authentication works should you close the original window.
It is possible to make permanent shortcuts on the client using [http://man.openbsd.org/ssh_config.5 ssh_config(5)], explained further below, once key-based authentication is working. In particular, see the '''IdentityFile''', '''IdentitiesOnly''', and '''AddKeysToAgent''' configuration directives, to name three.
It is also a good idea to turn off password authentication, if and only if key-based authentication is setup for all the necessary remote accounts.
➥ '''Troubleshooting of Key-based Authentication''':
If the server refuses to accept the key and fails over to the next authentication method (e.g.: "Server refused our key"), then there are several possible mistakes to look for on the server side.
One of the most common errors is that the file and directory permissions are wrong. The authorized keys file must be owned by the user in question and not be group writable. Nor may the key file's directory be group or world writable.
<syntaxhighlight lang="shell-session">
$ chmod u=rwx,g=rx,o= ~/.ssh
$ chmod u=rw,g=,o= ~/.ssh/authorized_keys
</syntaxhighlight>
Another mistake that can happen is if the key inside the '''authorized_keys''' file on the remote host is broken by line breaks or has other whitespace in the middle. That can be fixed by joining up the lines and removing the spaces or by recopying the key more carefully.
And, though it should go without saying, the halves of the key pair need to match. The public key on the server needs to match the private key held on the client. If the public key is lost, then a new one can be generated with the '''-y''' option, but not the other way around. If the private key is lost, then the public key should be erased as it is no longer of any use. If many keys are in use for an account, it might be a good idea to add comments to them. On the client, it can be a good idea to know which server the key is for, either through the file name itself or through the comment field. A comment can be added using the '''-C''' option.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -t ed25519 -f ~/.ssh/fred_example_org_ed25519 -C "web server mirror"
</syntaxhighlight>
On the server, it can be important to annotate which client they key is from if there is more than one public key there in an account. There the comment can be added to the authorized keys file on the server in the last column if a comment does not already exist. Again, the format of the authorized keys file is given in the manual page for [http://man.openbsd.org/sshd.8 sshd(8)] in the section "AUTHORIZED_KEYS FILE FORMAT". If the keys are not labeled they can be hard to match, which might or might not be what you want.
====Associating Keys Permanently with a Server====
A key can be specified at run time, but to save retyping the same paths again and again, the '''Host''' directive in [http://man.openbsd.org/ssh_config.5 ssh_config(5)] can apply specific settings to a target host. In this case, by changing '''~/.ssh/config''' it is possible to assign particular keys to be tried automatically whenever making a connection to that specific host. After adding the following lines to '''~/.ssh/config''', all that's needed is to type <code>ssh ''web1''</code> to connect with the key for that server.
<syntaxhighlight lang="apache" line="1">
Host web1
Hostname 198.51.100.32
IdentitiesOnly yes
IdentityFile /home/fred/.ssh/web_key_ed25519
</syntaxhighlight>
The '''~/.ssh/config''' below uses different keys for ''server'' versus ''server.example.org'', regardless whether they resolve to the same machine. This is possible because the host name argument given to [http://man.openbsd.org/ssh.1 ssh(1)] is not converted to a canonicalized host name before matching.
<syntaxhighlight lang="apache" line="1">
Host server
IdentitiesOnly yes
IdentityFile /home/fred/.ssh/key_a_ed25519
Host server.example.org
IdentitiesOnly yes
IdentityFile /home/fred/.ssh/key_b_ed25519
</syntaxhighlight>
In this example the shorter name is tried first, but of course less ambiguous shortcuts can be made instead. The configuration file gets parsed on a first-match basis. So the most specific rules go at the beginning and the most general rules go at the end.
====Encrypted Home Directories====
When using encrypted home directories the keys must be stored in an unencrypted directory. That means somewhere outside the actual home directory which means [http://man.openbsd.org/sshd.8 sshd(8)] needs to be configured appropriately to find the keys in that special location.
Here is one method for solving the access problem. Each user is given a subdirectory under '''/etc/ssh/keys/''' which they can then use for storing their '''authorized_keys''' file. This is set in the server's configuration file '''/etc/ssh/sshd_config'''
<syntaxhighlight lang="apache" line="1">
AuthorizedKeysFile /etc/ssh/keys/%u/authorized_keys
</syntaxhighlight>
Setting a special location for the keys opens up more possibilities as to how the keys can be managed and multiple key file locations can be specified if they are separated by whitespace. The user does not have to have write permissions for the '''authorized_keys''' file. Only read permission is needed to be able to log in. But if the user is allowed to add, remove, or change their keys, then they will need write access to the file to do that.
One symptom of having an encrypted home directory is that key-based authentication only works when you are already logged into the same account, but fails when trying to make the first connection and log in for the first time.
Sometimes it is also necessary to add a script or call a program from '''/etc/ssh/sshrc''' immediately after authentication to decrypt the home directory.
====Passwordless Login====
One solution for passwordless logins is to still have a passphrase and work with an authentication agent in conjunction with a single-purpose key. Most desktop environments launch an SSH agent automatically these days. It will be visible in the '''SSH_AUTH_SOCK''' environment variable if it is. On accounts with an agent, [http://man.openbsd.org/ssh-add.1 ssh-add(1)] can load private keys into an available agent.
<syntaxhighlight lang="shell-session">
$ ssh-add ~/.ssh/fred_example_org_ed25519
</syntaxhighlight>
Thereafter, the client will automatically check the agent for the key when appropriate. If there are many keys in the agent, it will become necessary to set '''IdentitiesOnly'''. See the above section on using '''~/.ssh/config''' for that. See [[OpenSSH/Cookbook/Public_Key_Authentication#Key-based_Authentication_Using_an_Agent|Key-based Authentication Using an Agent]] below.
Another, riskier, way of allowing passwordless logins is to follow the steps above, but simply do not enter a passphrase when asked for one while creating the key. Note that using keys that lack a passphrase is very risky, so the key files should be very well protected and kept track of, and ideally locked down with a '''command=''' option or '''ForceCommand''' directive on the server. That includes those keys which will only be used as single-purpose keys as described below.
Timely key rotation becomes especially important. In general, it is not a good idea to make a key without a passphrase.
====Requiring Both Keys and a Password====
While users should have strong passphrases for their keys, there is no way to enforce or verify that. Indeed, since neither the private key nor its the passphrase ever leave the client machine there is nothing that the server can do to have any influence over that. Instead, it is possible to require both a key and a password. Starting with OpenSSH 6.2, it is possible for the server to require multiple authentication methods for login using the '''AuthenticationMethods''' directive.
<syntaxhighlight lang="apache" line="1">
AuthenticationMethods publickey,password
</syntaxhighlight>
This example from [http://man.openbsd.org/sshd_config.5 sshd_config(5)] requires that users first authenticate using a key and it only queries for a password if the key succeeds. Thus with that configuration it is not possible to get to the system password prompt without first authenticating with a valid key. Changing the order of the arguments changes the order of the authentication methods.
====Requiring Two or More Keys====
Since OpenSSH 6.8, the server now remembers which public keys have been used for authentication and refuses to accept previously-used keys. This allows a set up requiring that users authenticate using two different public keys, maybe one in the file system and the other in a hardware token.
<syntaxhighlight lang="apache" line="1">
AuthenticationMethods publickey,publickey
</syntaxhighlight>
The '''AuthenticationMethods''' directive, whether for keys or passwords, can also be set on the server under a '''Match''' directive to apply only to certain groups or situations.
====Requiring Certain Key Types For Authentication====
Also since OpenSSH 6.8, the '''PubkeyAcceptedKeyTypes''' directive, later changed to '''PubkeyAcceptedAlgorithms''', can specify which key algorithms are accepted for authentication. Those not in the comma-separated pattern list are not allowed.
<syntaxhighlight lang="apache" line="1">
PubkeyAcceptedAlgorithms ssh-ed25519*,ssh-rsa*,ecdsa-sha2*,sk-ssh-ed25519*,sk-ecdsa-sha2*
</syntaxhighlight>
Either the actual key types or a pattern can be in the list. Spaces are not allowed in the pattern list. The exact list of key types supported for authentication can be found by the '''-Q''' option using the client. The following two lines are equivalent.
<syntaxhighlight lang="shell-session">
$ ssh -Q key-sig | sort
$ ssh -Q PubkeyAcceptedAlgorithms | sort
</syntaxhighlight>
For host-based authentication, it is the '''HostbasedAcceptedAlgorithms''' directive which determines the key types which are allowed for authentication.
===Key-based Authentication Using the AuthorizedKeysCommand Directive===
It is possible to use a program or script to look up public keys rather than keeping them in a static file or files. Any command called by the '''AuthorizedKeysCommand''' directive needs to either produce a syntactically correct public key while returning the exit code for a successful run or else return the exit code for failure. The string sent to '''stdout''' will then be processed as part of the authentication work flow.
Here is a shell script<ref name="janpietmens">{{cite web |url=https://jpmens.net/2025/03/25/authorizedkeyscommand-in-sshd/ |title=SSH keys from a command: sshd's AuthorizedKeysCommand directive |accessdate=2025-04-04 |date=2025-03-25 | author=Jan-Piet Mens }}</ref> at its simplest, without constraints, demonstrating a public key lookup:
<syntaxhighlight lang="shell">
#!/bin/sh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKs/UouletvojgB1YeRZ4MY6iRblQ2ERDuNhQO4tOvdL"
exit 0
</syntaxhighlight>
For authentication to succeed, the script must return exit code 0 (success) after sending the syntactically correct matching public key to '''stdout'''. For the SSH daemon to even run the script in the first place, the script must have the correct file and directory permissions.
Both the '''AuthorizedKeysCommandUser''' directive and '''AuthorizedKeysCommand''' must be used together. The former designates which account the script or program use when run. If set to ''none'' or if it does not refer to a valid account then [http://man.openbsd.org/sshd sshd(8)] will just ignore the command. If '''AuthorizedKeysCommand''' is set, and '''AuthorizedKeysCommandUser''' is left empty or missing, then [http://man.openbsd.org/sshd sshd(8)] won't even run when invoked. The error will be:
<syntaxhighlight lang="text">
AuthorizedKeysCommand set without AuthorizedKeysCommandUser
</syntaxhighlight>
The '''AuthorizedKeysFile''' is always tried first when it is present in the server configuration. The '''AuthorizedKeysCommand''' directive will not even be tried when the authorized keys file can provide a relevant key first.
====A More Detailed Example Using the AuthorizedKeysCommand Directive====
By default the user name trying to log in is passed to the script when no tokens or arguments are provided. Whether or how that information is used is up to the script. The SSH daemon can also pass any combination of the tokens described in the TOKENS section of [http://man.openbsd.org/sshd_config sshd_config(5)] into the program or script being called. Furthermore, the program or script can even be a front end for a database, such as OpenLDAP, or any similar system, as long as '''stdout''' produces a public key.
Below is a more detailed example which uses a local script named '''keyfinder''' run with the account '''keys''' to look up the a public key for certain accounts. First in [http://man.openbsd.org/sshd_config sshd_config(5)] the two directives:
<syntaxhighlight lang="apache" line="1">
AuthorizedKeysCommand /usr/local/sbin/keyfinder %U
AuthorizedKeysCommandUser keys
</syntaxhighlight>
The script below is only a demonstration and a more complex program can call databases or do advanced lookups or heuristics:
<syntaxhighlight lang="shell">
#!/bin/sh
set -e
case $1 in
"1000")
echo "ssh-ed25519 AAAAC3NzaC1lZDIE5AAAAIK89...UT9hz"
;;
"1001")
echo "restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTAAIBvGx...Y0zxV"
;;
"1002")
echo "command=\"/usr/libexec/sftp-server\" ssh-ed25519 AAAAC3NzaC1lZDI1TE5AIPSyY...cPTg3"
;;
*)
exit 1
;;
esac
exit 0
</syntaxhighlight>
The '''AuthorizedKeysCommand''' scripts or programs can return any correctly formatted public key to '''stdout''' for consideration in the authentication process. That includes adding constraints to the keys. Above, the account with the UID 1000 has no constraints, while the account with UID 1001 is quite constrained. Finally, the account with the UID 1002 can only access the SFTP service. See the section "AUTHORIZED_KEYS FILE FORMAT" in [http://man.openbsd.org/sshd sshd(8)] for the full set of possibilities.
===Key-based Authentication Using an Agent===
When an authentication agent, such as [http://man.openbsd.org/ssh-agent.1 ssh-agent(1)], is going to be used, it should generally be started at the beginning of a session and used to launch the login session or X-session so that the environment variables pointing to the agent and its UNIX-domain socket are passed to each subsequent shell and process. Many desktop distros do this automatically upon login or startup.
Starting an agent entails setting a pair of environment variables:
* SSH_AGENT_PID : the process id of the agent
* SSH_AUTH_SOCK : the filename and full path to the UNIX-domain socket
The various SSH and SFTP clients find these variables automatically and use them to contact the agent and try when authentication is needed. However, it is mainly SSH_AUTH_SOCK which is ever used. If the shell or desktop session was launched using [http://man.openbsd.org/ssh-agent.1 ssh-agent(1)], then these variables are already set and available. If they are not available, then it is necessary to either set the variables manually inside each shell or for each application in order to use the agent or else to point to the agent's socket using the directive '''IdentityAgent''' in the client's configuration file.
Once an agent is available, a relevant private key needs to be loaded before the agent can be used. Once in the agent the private key can then be used many times. Private keys are loaded into an agent with [http://man.openbsd.org/ssh-add.1 ssh-add(1)].
<syntaxhighlight lang="shell-session">
$ ssh-add /home/fred/.ssh/mykey_ed25519
Identity added: /home/fred/.ssh/mykey_ed25519 (/home/fred/.ssh/mykey_ed25519)
</syntaxhighlight>
Keys stay in the agent for as long as it is running unless specified otherwise. A timeout can be set either with the '''-t''' option when starting the agent itself or when actually loading the key using [http://man.openbsd.org/ssh-add.1 ssh-add(1)]. In either case, the '''-t''' option will set a timeout interval, after which the key will be purged from the agent.
<syntaxhighlight lang="shell-session">
$ ssh-add -t 1h30m /home/fred/.ssh/mykey_ed25519
Identity added: /home/fred/.ssh/mykey_ed25519 (/home/fred/.ssh/mykey_ed25519)
Lifetime set to 5400 seconds
</syntaxhighlight>
The option '''-l''' will list the fingerprints of all of the identities in the agent.
<syntaxhighlight lang="shell-session">
$ ssh-add -l
256 SHA256:77mfUupj364g1WQ+O8NM1ELj0G1QRx/pHtvzvDvDlOk mykey for task x (ED25519)
3072 SHA256:7unq90B/XjrRbucm/fqTOJu0I1vPygVkN9FgzsJdXbk myotherkey rsa for task y (RSA)
</syntaxhighlight>
It is also possible to remove individual identities from the agent using '''-d''' which will remove them one at a time if identified by file name, but only if the file name is given and without the file name of the private key to be remove, '''-d''' will fail silently. Using '''-D''' instead will remove all of them at once without needing to specify any by name.
By default [http://man.openbsd.org/ssh-add.1 ssh-add(1)] uses the agent connected via the socket named in the environment variable '''SSH_AUTH_SOCK''', if it is set. Currently, that is its only option. However, for [http://man.openbsd.org/ssh.1 ssh(1)] an alternative to using the environment variable is the client configuration directive '''IdentityAgent''' which tells the SSH clients which socket to use to communicate with the agent. If both the environment variable and the configuration directive are available at the same time, then the value in '''IdentityAgent''' takes precedence over what's in the environment variable. '''IdentityAgent''' can also be set to ''none'' to prevent the connection from trying to use any agent at all.
The client configuration directive '''AddKeysToAgent''' can also be useful in getting keys into an agent as needed. When set, it automatically loads a key into a running agent the first time the key is called for if it is not already loaded. Likewise the '''IdentitiesOnly''' directive can ensure that the relevant key is offered on the first try. Rather than typing these out whenever the client is run, they can be added to '''~/.ssh/config''' and thereby added automatically for designated host connections.
====Agent Forwarding====
Agent forwarding is one means of passing through one or more intermediate hosts. However, the '''-J''' option for '''ProxyJump''' would be a safer option. See [[OpenSSH/Cookbook/Proxies_and_Jump_Hosts#Jump_Hosts_--_Passing_Through_a_Gateway_or_Two | Passing Through a Gateway or Two]] in the section on jump hosts about that. With agent forwarding, intermediate machines forward challenges and responses back and forth between the client and the final destination. This comes with some risks but eliminates the need for using passwords or holding keys on any of these intermediate machines.
A main advantage of agent forwarding is that the private key itself is not needed on any remote machine, thus hindering unwanted file system access to it. <ref name="OpenSSH key management, Part 3">{{cite web | url=http://www.ibm.com/developerworks/library/l-keyc3/ | title=Common threads: OpenSSH key management, Part 3 | author=Daniel Robbins | publisher=IBM | date=2002-02-01 | accessdate=2013-04-27}}</ref> Another advantage is that the actual agent to which the user has authenticated does not go anywhere and is thus less susceptible to analysis.
One risk with agents is that they can be re-used to tailgate in if the permissions allow it. Keys cannot be copied this way, but authentication is possible when there are incorrect permissions. Note that disabling agent forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders.
The risks of agent forwarding can be mitigated by confirming each use of a key by adding the '''-c''' option when adding the key to the agent. This requires the SSH_ASKPASS variable be set and available to the agent process, but will generate a prompt on the host running the agent upon each use of the key by a remote system. So if passing through one or more intermediate hosts, it is usually better to instead have the SSH client use stdio forwarding with '''-W''' or '''-J'''.
On the client side agent forwarding is disabled by default and so if it is to be used it must be enabled explicitly. Put the following line in [http://man.openbsd.org/ssh_config.5 ssh_config(5)] to enable agent forwarding for a particular server:
<syntaxhighlight lang="apache" line="1">
Host gateway.example.org
ForwardAgent yes
</syntaxhighlight>
On the server side the default configuration files allow authentication agent forwarding, so to use it, nothing needs to be done there, just on the client side. However, again, it would be preferable to take a look at '''ProxyJump''' instead.
=====Old Style, Somewhat Safer SSH Agent Forwarding=====
The best way to pass through one or more intermediate hosts is to use the '''ProxyJump''' option instead of authentication agent forwarding and thereby not risk exposing any private keys. If authentication agent forwarding must be used, then it would be advisable in the interest of following the principle of least privilege to forward an agent containing the minimum necessary number of keys. There are several ways to solve that.
In version 8.8 and earlier a partial solution is to make a one-off, ephemeral agent to hold just the one key or keys needed for the task at hand. Another partial solution would be to set up a user-accessible service at the operating system level and then use [http://man.openbsd.org/ssh_config.5 ssh_config] for the rest.
Automatically launching an ephemeral agent unique to each session can be done by crafting either a special shell alias or function to launch a single-use agent. Either the function or the alias can be written to require confirmation for each requested signature. The following example is a function is inspired by an updated blog post by Vincent Bernat<ref name="safer-agent-forwarding">{{cite web |url=https://vincent.bernat.ch/en/blog/2020-safer-ssh-agent-forwarding |title=Safer SSH agent forwarding |author=Vincent Bernat|date=2020-04-05 |accessdate=2020-10-04}}</ref> on SSH agent forwarding:
<syntaxhighlight lang="shell-session">
$ agentssh() {
ssh-agent ssh -o AddKeysToAgent=confirm -o ForwardAgent=yes
}
</syntaxhighlight>
Note the use of [http://man.openbsd.org/ssh-agent.1 ssh-agent(1)]. When invoking that alias, the SSH client will be launched with a unique, ephemeral supporting key agent. The alias sets up a new agent, including setting the two environment variables, and then sets two client options while calling the client. This arrangement still checks with [http://man.openbsd.org/ssh_config.5 ssh_config(5)] for other options and settings. When the SSH session is finished the agent which launched it ends and goes away, thus cleaning up after itself automatically.
Another way is to rely on the client's configuration file for some of the settings. Such methods rely mostly on [http://man.openbsd.org/ssh_config.5 ssh_config(5)] but still require an independent method to launch an ephemeral agent because the OpenSSH client is already running by the time it reads the configuration file and is thus not affected by any changes to environment variables caused by the configuration file and it is through the environment variables that contain information about the agent. However, when the path to the UNIX-domain socket used to communicate with the authentication agent is decided in advance then the '''IdentityAgent''' option can point to it once the one-off agent<ref name="wikimedia_ssh_agents">{{cite web |url=https://wikitech.wikimedia.org/wiki/Managing_multiple_SSH_agents#Linux_solutions |title=Managing multiple SSH agents |publisher=Wikimedia|accessdate=2020-04-07}}</ref> is actually launched. The following uses a specific agent's pre-defined socket whenever connecting to either of two particular domains:
<syntaxhighlight lang="apache" line="1">
Host *.wikimedia.org *.wmflabs.org
User fred
IdentitiesOnly yes
IdentityFile %d/.ssh/id_cloud_01
IdentityAgent /run/user/%i/ssh-cloud-01.socket
ForwardAgent yes
AddKeysToAgent yes
</syntaxhighlight>
The '''%d''' stands for the path to the home directory and the '''%i''' stands for the user id (UID) for the current account. In some cases the '''%i''' token might also come in handy when setting the '''IdentityAgent''' option inside the configuration file. Again, be careful when forwarding agents with which keys are in the forwarded agent. See the section "TOKENS" in [http://man.openbsd.org/ssh_config.5 ssh_config(5)] for more such abbreviations.
With those configuration settings, the authentication agent must already be up and running and point to the designated socket prior to starting the SSH client for that configuration to work. Additionally, it should place the socket in a directory which is inaccessible to any other accounts. [http://man.openbsd.org/ssh-agent.1 ssh-agent(1)] must use the '''-a''' option to name the socket:
<syntaxhighlight lang="shell-session">
$ ssh-agent -a /run/user/${UID}/ssh-cloud-01.socket
</syntaxhighlight>
That agent configuration can be launched manually or via a script or service manager. However, in the interests of privacy and security in general, agent forwarding is to be avoided. The configuration directive '''ProxyJump''' is the best alternative and, on older systems, host traversal using '''ProxyCommand''' with [http://man.openbsd.org/nc.1 netcat] are preferable. Again, see the section on [[OpenSSH/Cookbook/Proxies and Jump Hosts|Proxies and Jump Hosts]] for how those methods are used.
=====New Style SSH Agent Destination Constraints=====
From 8.9 onward, [http://man.openbsd.org/ssh-agent.1 ssh-agent(1)] will allow the agent to limit which hosts they will use for authentication as specified by [http://man.openbsd.org/ssh-add.1 ssh-add(1)] using the '''-h''' option. These constraints have been added through two agent protocol extensions and a modification to the public key authentication protocol. This feature may evolve, but for now the result is such that keys for account authentication can be loaded into the agent in four ways:
* no limits on forwarding (not recommended)
* local use only, these will not get forwarded
* forwarding, but only to specific remote hosts
* forwarding to specific remote hosts via specified routes
The intent is that the restrictions fail safely so that they do not allow authentication when one or more hosts in the route lack the needed protocol features. The destinations and routes cannot be modified once the keys are loaded, but multiple routes to the same destination can be loaded and the routes can be any number of hops. If the routes need changing, then the key must be reloaded into the agent with the new route or routes.
The general default for the client is to keep keys in the agent for local use only. However, that can be enforced explicitly by adding the '''-a''' option when starting the client or else setting the '''ForwardAgent''' directive in [http://man.openbsd.org/ssh_config.5 ssh_config(5)] to 'no' in the relevant configuration block.
In order to load keys for unlimited forwarding, which is not the best idea, just add them using [http://man.openbsd.org/ssh-add.1 ssh-add(1)] as normal. Then use the '''-A''' option with the client or set the '''ForwardAgent''' directive in [http://man.openbsd.org/ssh_config.5 ssh_config(5)] to 'yes' in the relevant configuration block.
In order to limit keys for connection only to a specific remote host, or to load keys for connection to a specific remote host with forwarding via one or more intermediate hosts, use the '''-h''' option when loading keys into the agent. Here the one key may be used only to connect to the specific destination:
<syntaxhighlight lang="shell-session">
$ ssh-agent -h server.example.org server.key.ed25519
</syntaxhighlight>
If an intermediate system is passed through, the best way is to use '''ProxyJump''' which is the '''-J''' option for the SSH Client. If agent forwarding must be allowed then the tightest way is to constrain which systems may use the keys, again using the '''-h''' option.
<syntaxhighlight lang="shell-session">
$ ssh-agent -h middle.example.org -h "middle.example.org>server.example.org" server.key.ed25519
</syntaxhighlight>
Multiple steps can be included, even multiple routes. They just have to be enumerated explicitly, though patterns may still be used for the destination hosts as well as specific names. Each host in the chain must support these protocol extensions for the connection to complete.
Any keys designated for forwarding are unusable for authentication on any other hosts than those which have been explicitly identified for forwarding. These permitted hosts are identified by host key or host certificate from the '''known_hosts''' file or another file designated by the '''-H''' option when loading the key with [http://man.openbsd.org/ssh-add.1 ssh-add(1)]. If '''-H''' is not used at the time the keys are loaded into the agent, then the default known hosts file(s) will be used: '''~/.ssh/known_hosts''', '''/etc/ssh/ssh_known_hosts''', '''~/.ssh/known_hosts2''', and '''/etc/ssh/ssh_known_hosts2'''.
In the case of keys, the '''known_hosts''' list must be maintained conscientiously <ref name="ssh-agent-restrictions">{{ cite web | author=Damien Miller|url=https://www.openssh.org/agent-restrict.html | title=SSH agent restriction | publisher=OpenSSH | date=2021-12-16|accessdate=2022-03-06}}</ref>, perhaps with the help of the '''UpdateHostkeys''' and '''CanonicalizeHostname''' client configuration directives. Use of certificates requires the agent to only need to be aware of the Certificate Authority (CA).
Again, see [[OpenSSH/Cookbook/Proxies_and_Jump_Hosts#Jump_Hosts_--_Passing_Through_a_Gateway_or_Two | Passing Through a Gateway or Two]] in the section on jump hosts about a way to pass through one or more intermediate machines without needing to forward an SSH agent.
====Checking the Agent for Specific Keys====
The [http://man.openbsd.org/ssh_add ssh_add(1)] utility's '''-T''' option can test whether a specific private key is available in the agent or not by looking up the matching public key. That can be useful in a shell script.
<syntaxhighlight lang="shell">
#!/bin/sh
key=/home/fred/.ssh/some.key.ed25519.pub
if ssh-add -T ${key}; then
echo "Key ${key} Found"
else
echo "Key ${key} missing"
fi
</syntaxhighlight>
Or it could be done with an alternate syntax just as well either in a script or in an interactive shell sessions,
<syntaxhighlight lang="shell-session">
$ key=/home/fred/.ssh/some.key.ed25519.pub
$ ssh-add -T ${key} && echo "Key found" || echo "Key missing"
</syntaxhighlight>
However, if the desired result would be to add key to the agent then the '''AddKeysToAgent''' client configuration option can ensure that a specific key is added to the SSH agent upon first use during any given login session. That can be done using '''-o AddKeysToAgent=yes''' as a run-time argument, or by modifying [http://man.openbsd.org/ssh_config ssh_config(5)] as appropriate:
<syntaxhighlight lang="apache" line="1">
Host www
HostName www.example.com
IdentityFile %d/.ssh/www.ed25519
IdentitiesOnly yes
AddKeysToAgent yes
</syntaxhighlight>
With those options in the configuration file, the first time <code>ssh www</code> is run the specified key will get added to the agent and remain available.
===Key-based Authentication Using A Hardware Security Token===
While stand-alone keys have been around for a long time, it has been possible since version 8.2 to use keys backed by hardware security tokens, such as OnlyKey, Yubikey, or many others, though the FIDO2 protocol. The Universal 2nd Factor (U2F) authentication is supported directly in OpenSSH through FIDO2 and does not need third party software. At the moment there are two types of hardware backed keys, ECDSA-SK and Ed25519-SK, but only the latest hardware tokens support the latter. If the key Ed25519-SK format is not supported by the token's firmware, then the following error message will be presented when attempts to use that key type are made:
<syntaxhighlight lang="text">
Key enrollment failed: invalid format
</syntaxhighlight>
If supported, either key type can be created with [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)]. The steps are almost identical to creating normal keys but the token must be available to the system (plugged in) first. Then if called for, the token's PIN must be entered and the token touched or otherwise activated. After that, the key creation proceeds as normal. Mind the key type as specified by the '''-t''' option.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -t ed25519-sk -f /home/fred/.ssh/server.ed25519-sk -C "web server for fred"
Generating public/private ed25519-sk key pair.
You may need to touch your authenticator to authorize key generation.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/fred/.ssh/server.ed25519-sk
Your public key has been saved in /home/fred/.ssh/server.ed25519-sk.pub
The key fingerprint is:
SHA256:41wVVDnKJ9gKr2Sj4CFuYMhcNvYebZ6zq0PWyP4rRDo web server
The key's randomart image is:
+[ED25519-SK 256]-+
| .o... |
| .o |
| +.. . |
| = . . ..= . |
|+ + * + So.. o |
|o+.EoO *+oo |
|.o oBo+++o |
| o .=.+. |
| . .=== |
+----[SHA256]-----+
</syntaxhighlight>
Once created, the public and private key files get handled like with any other type of key. But when authenticating, the hardware token must be present and activated when called for.
<syntaxhighlight lang="shell-session">
$ ssh -i /home/fred/.ssh/server.ed25519-sk server.example.org
Enter passphrase for key '/home/fred/.ssh/server.ed25519-sk':
Confirm user presence for key ED25519-SK SHA256:41wVVDnKJ9gKr2Sj4CFuYMhcNvYebZ6zq0PWyP4rRDo
</syntaxhighlight>
The resulting private key file is not actually the key itself but instead a "key handle" which is used by the hardware security token to derive the real private key on demand at the time it is actually used<ref name="OpenBSD_tech_U2F_FIDO">{{cite web |url=https://marc.info/?l=openbsd-tech&m=157376801917387&w=2 |title=OpenSSH U2F/FIDO support in base
|publisher=OpenBSD-Tech Mailing List | date=2019-11-14
|accessdate=2021-03-24}}</ref>. As a result, the hardware-backed private key file is useless without the accompanying hardware token. This also means that these key files are not portable across hardware tokens, say when having multiple tokens in reserve or as backup, even when used by the same account. So when multiple hardware tokens are in use, different key pairs must be generated for each token.
====Hardware Security Token Resident Private Key====
It is possible to store the private key within the token itself, but for the moment it cannot be used directly from inside the token and must first be saved as a file. Also, the key can only be loaded into the FIDO authenticator at the time of creation using the '''-O resident''' option with [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)]. Otherwise, the process is the same as above.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -O resident -t ed25519-sk -f /home/fred/.ssh/server.ed25519-sk -C "web server for fred"
. . .
</syntaxhighlight>
When needed, the resident key can be extracted from the FIDO2 hardware token and saved into a file using the '''-K''' option. At this stage a passphrase can be added to the file, but no passphrase is kept within the token itself, only an optional PIN protects the key there.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -K
Enter PIN for authenticator:
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Saved ED25519-SK key to id_ed25519_sk_rk
$ mv -i id_ed25519_sk_rk /home/fred/.ssh/server.ed25519-sk
</syntaxhighlight>
Since the output file name is fixed, any pre-existing file with that name can get overwritten but there will be a warning first. However, it is not recommended to keep the key on the hardware token because it provides more protection when kept separately.
==Single-purpose Keys==
Tailored single-purpose keys can eliminate use of remote root logins for many administrative activities. A finely tailored '''sudoers''' is needed along with an unprivileged account. When done right, it gives just enough access to get the job done, following the security principle of Least Privilege.
Single-purpose keys are accompanied by use of either the '''ForceCommand''' directive in [http://man.openbsd.org/ssh_config.5 sshd_config(5)] or the '''command="..."''' directive inside the '''authorized_keys''' file. The method is to generate a new key pair, transfer the public key to '''authorized-keys''' on the remote system, and then prepend the appropriate command or script there to the line with the key.
<syntaxhighlight lang="shell-session">
$ grep '^command' ~/.ssh/authorized_keys
command="/usr/local/bin/somescript.sh" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEcgdzDvSebOEjuegEx4W1I/aA7MM3owHfMr9yg2WH8H
</syntaxhighlight>
The '''command="..."''' directive inserted there overrides everything else and ensures that when logging in with just that key only the script '''/usr/local/bin/somescript.sh''' is run. If it is necessary to pass parameters to the script, have a look at the contents of the '''SSH_ORIGINAL_COMMAND''' environment variable and use it in a case statement. Do not ever trust the contents of that variable nor use the contents directly, always indirectly.
Single-purpose keys are useful for allowing only a tunnel and nothing more. The following key will only echo some text and then exit, unless used non-interactively with the '''-N''' option.
<syntaxhighlight lang="shell-session">
$ grep '^command' ~/.ssh/authorized_keys
command="/bin/echo do-not-send-commands" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBzTIWCaILN3tHx5WW+PMVDc7DfPM9xYNY61JgFmBGrA
</syntaxhighlight>
No matter what the user tries while logging in with that key, the session will only echo the given text and then exits. Using the '''-N''' option disables running the remote program, allowing the connection to stay open, allowing a tunnel.
<syntaxhighlight lang="shell-session">
$ ssh -L 3306:localhost:3306 \
-i ~/.ssh/tunnel_ed25519 \
-N \
-l fred \
server.example.com
</syntaxhighlight>
That creates a tunnel and stays connected despite a key configuration which would close an interactive session. See also the '''-n''' or '''-f''' option for [http://man.openbsd.org/ssh.1 ssh(1)].
===Single-purpose Keys to Avoid Remote Root Access===
The easy way is to write a short shell script, place it '''/usr/local/bin/''', and then configure '''sudoers''' to allow the otherwise unprivileged account to run just that script and only that script.
<syntaxhighlight lang="apache" line="1">
%wheel ALL=(root:root) NOPASSWD: /usr/sbin/service httpd stop
%wheel ALL=(root:root) NOPASSWD: /usr/sbin/service httpd start
</syntaxhighlight>
Then the key calls the script using '''command="..."''' inside '''authorized_keys'''. Here the one key starts the web server, the other stops the web server.
<syntaxhighlight lang="shell-session">
$ grep '^command' ~/.ssh/authorized_keys
command="/usr/bin/sudo /usr/sbin/service httpd stop" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEcgdzDvSebOEjuegEx4W1I/aA7MM3owHfMr9yg2WH8H
command="/usr/bin/sudo /usr/sbin/service httpd start" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMidyqZ6OCvbWqA8Zn+FjhpYE6NoWSxVjFnFUk6MrNZ4
</syntaxhighlight>
Complicated programs like [http://linux.die.net/man/1/rsync rsync(1)], [http://man.openbsd.org/tar.1 tar(1)], [http://linux.die.net/man/1/mysqldump mysqldump(1)], and so on require an advanced approach when building a single-purpose key. For them, the '''-v''' option can show exactly what is being passed to the server so that '''sudoers''' can be set up correctly. That way they can be restricted to only access designated parts of the file system. For example, here is what <code>ssh -v</code> shows from one particular usage of [http://linux.die.net/man/1/rsync rsync(1)], note the "Sending command" line:
<syntaxhighlight lang="shell-session">
$ rsync -e 'ssh -v' fred@server.example.org:/etc/ ./backup/etc/
. . .
debug1: Sending command: rsync --server --sender -e.LsfxC . /etc/
. . .
</syntaxhighlight>
That output can then be added to '''sudoers''' so that the key can do only that function.
<syntaxhighlight lang="shell-session">
%backup ALL=(root:root) NOPASSWD: /usr/bin/rsync --server --sender -e.LsfxC . /etc/
</syntaxhighlight>
Then to tie it all together, the account "backup" needs a key:
<syntaxhighlight lang="shell-session">
$ grep '^command' ~/.ssh/authorized_keys
command="/usr/bin/rsync --server --sender -e.LsfxC . /etc/" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMm0rs4eY8djqBb3dIEgbQ8lmdlxb9IAEuX/qFCTxFgb
</syntaxhighlight>
Many of these programs have a '''--dry-run''' or equivalent option. Remember to use it when figuring out the right settings.
===Read-only Access to Keys===
In some cases it is necessary to prevent accounts from being able to changing their own authentication keys. However, such situations may be a better case for using certificates. However, if done with keys it is accomplished by putting the key file in an external directory where the user has read-only access, both to the directory and to the key file. Then the '''AuthorizedKeysFile''' directive assigns where [http://man.openbsd.org/sshd.8 sshd(8)] looks for the keys and can point to a secured location for the keys instead of the default location.
A good alternate location could be a new directory '''/etc/ssh/authorized_keys''' which could store the selected accounts' key files there. The change can be made to apply to only a group of accounts by putting the settings under a '''Match''' directive. The default location for keys on most systems is usually '''~/.ssh/authorized_keys'''.
<syntaxhighlight lang="apache" line="1">
Match Group sftpusers
AuthorizedKeysFile /etc/ssh/authorized_keys/%u
</syntaxhighlight>
Then the permissions there would allow the keys to be read but not written:
<syntaxhighlight lang="shell-session">
$ ls -dhln /etc/ssh/
drwxr-x--x 3 0 0 4.0K Mar 30 22:16 /etc/ssh/authorized_keys/
$ ls -dhln /etc/ssh/*.pub
-rw-r--r-- 1 0 0 173 Mar 23 13:34 /etc/ssh/fred
-rw-r--r-- 1 0 0 93 Mar 23 13:34 /etc/ssh/user1
-rw-r--r-- 1 0 0 565 Mar 23 13:34 /etc/ssh/user2
. . .
</syntaxhighlight>
The keys could even be within subdirectories, though the same restrictions apply regarding permissions and ownership.
For chrooted SFTP, the method is the same to keep the key files out of reach of the accounts:
<syntaxhighlight lang="apache" line="1">
Match Group sftpusers
ChrootDirectory /home
ForceCommand internal-sftp -d %u
AuthorizedKeysFile /etc/ssh/authorized_keys/%u
</syntaxhighlight>
Of course a '''Match''' directive is not essential. The settings could be made to apply to all accounts by putting the directive in the main part of the server configuration file instead.
==Mark Public Keys as Revoked==
Keys can be revoked. Keys that have been revoked can be stored in '''/etc/ssh/revoked_keys''', a file specified in [http://man.openbsd.org/ssh_config.5 sshd_config(5)] using the directive '''RevokedKeys''', so that [http://man.openbsd.org/sshd.8 sshd(8)] will prevent attempts to log in with them. No warning or error on the client side will be given if a revoked key is tried. Authentication will simply progress to the next key or method.
The revoked keys file should contain a list of public keys, one per line, that have been revoked and can no longer be used to connect to the server. The key cannot contain any extras, such as [[OpenSSH/Client_Configuration_Files#Available_key_login_options | login options]] or it will be ignored. If one of the revoked keys is tried during a login attempt, the server will simply ignore it and move on to the next authentication method. An entry will be made in the logs of the attempt, including the key's fingerprint. See the section on [[OpenSSH/Logging_and_Troubleshooting | logging]] for a little more on that.
<syntaxhighlight lang="apache" line="1">
RevokedKeys /etc/ssh/revoked_keys
</syntaxhighlight>
The '''RevokedKeys''' configuration directive is not set in [http://man.openbsd.org/ssh_config.5 sshd_config(5)] by default. It must be set explicitly if it is to be used. This is another situation that might be better fulfilled through using certificate since a validity interval can be set in any combination of seconds, minutes, hours, days, or weeks can be set for certificates while keys are valid indefinitely.
===Key Revocation Lists===
A Key Revocation List (KRL) is a compact, binary form of representing revoked keys and certificates. In order to use a KRL, the server's configuration file must point to a valid list using the '''RevokedKeys''' directive. KRLs themselves are generated with [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)] and can be created from scratch or edited in place. Here a new one is made, populated with a single public key:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -k -f /etc/ssh/revoked_keys -z 1 ~/.ssh/old_key_rsa.pub
</syntaxhighlight>
Here an existing KRL is updated by adding the '''-u''' option:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -u -k -f /etc/ssh/revoked_keys -z 2 ~/.ssh/old_key_dsa.pub
</syntaxhighlight>
Once a KRL is in place, it is possible to test if a specific key or certificate is in the revocation list.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -Q -f /etc/ssh/revoked_keys ~/.ssh/old_key_rsa.pub
</syntaxhighlight>
Only public keys and certificates will be loaded into the KRL. Corrupt or broken keys will not be loaded and will produce an error message if tried. Like with the regular '''RevokedKeys''' list, the public key destined for the KRL cannot contain any extras like login options or it will produce an error when an attempt is made to load it into the KRL or search the KRL for it.
==Verify a Host Key by Fingerprint==
The above examples have been about using keys to authenticate the client to the server. A different context in which keys are used is when the server identifies itself to the client, which happens automatically at the beginning of each non-multiplexed session. In order for that identification to happen the client acquires a public key from the server, usually on or prior to first contact, which it can subsequently use to ensure that it is connecting to the same server again and not an impostor. The default locations for storing these acquired host keys on the client are in '''/etc/ssh/ssh_known_hosts''', if managed by the system administrator, or in '''~/.ssh/known_hosts''' if managed by the client's own account. The format of the contents is a line with a host address and its matching public key. The file is described in detail in the [http://man.openbsd.org/sshd.8 sshd(8)] manual page in the section "SSH_KNOWN_HOSTS FILE FORMAT".
When connecting for the first time to a remote host, the server's host key should be verified in order to ensure that the client is connecting to the right machine and not an impostor or anything else. Usually this verification is done by comparing the fingerprint of the server's host key rather than trying to compare the whole key itself. By default the client will show the fingerprint if the key is not already found in the '''known_hosts''' register.
<syntaxhighlight lang="shell-session">
$ ssh -l fred server.example.org
The authenticity of host 'server.example.org (192.0.32.10)' can't be established.
ECDSA key fingerprint is SHA256:LPFiMYrrCYQVsVUPzjOHv+ZjyxCHlVYJMBVFerVCP7k.
Are you sure you want to continue connecting (yes/no)?
</syntaxhighlight>
That can be compared to a fingerprint received out of band, say by post, e-mail, SMS, courier, and so on. Specifically, the example represents the key's fingerprint as a base64 encoded SHA256 checksum. That is the default style. The fingerprint can also be displayed as an MD5 hash in hexadecimal instead by passing the client's '''FingerprintHash''' configuration directive as a runtime argument or setting it in [http://man.openbsd.org/ssh_config.5 ssh_config(5)].
<syntaxhighlight lang="shell-session">
$ ssh -o FingerprintHash=md5 host.example.org
The authenticity of host 'host.example.org (192.0.32.203)' can't be established.
RSA key fingerprint is MD5:10:4a:ec:d2:f1:38:f7:ea:0a:a0:0f:17:57:ea:a6:16.
Are you sure you want to continue connecting (yes/no)?
</syntaxhighlight>
But the default in new versions is SHA256 in base64 has a lower chance of collision.
In OpenSSH 6.7 and earlier, the client showed fingerprints as a hexadecimal MD5 checksum instead a of the base64-encoded SHA256 checksum currently used:
<syntaxhighlight lang="shell-session">
$ ssh -l fred server.example.org
The authenticity of host 'server.example.org (192.0.32.10)' can't be established.
RSA key fingerprint is 4a:11:ef:d3:f2:48:f8:ea:1a:a2:0d:17:57:ea:a6:16.
Are you sure you want to continue connecting (yes/no)?
</syntaxhighlight>
Another way of comparing keys is to use the ASCII art visual host key. See further below about that.
===Downloading keys===
Even though a host’s key is usually displayed for review the first time the SSH client tries to connect, it can also be fetched on demand at any time using [http://man.openbsd.org/ssh-keyscan.1 ssh-keyscan(1)]:
<syntaxhighlight lang="shell-session">
$ ssh-keyscan server.example.org
# server.example.org:22 SSH-2.0-OpenSSH_10.6
server.example.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEWKepJgkC2XTG5cAr2Nyew6hOp5AjG7vi2RYFtPWqN3bo5XGuCX2d2YVyn++/2PtyMYBaKWyFpCNTT9X0F1Epg=
# server.example.org:22 SSH-2.0-OpenSSH_10.6
server.example.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDKyERe8k+fnsrt4JrcLD3AW0kXj90r9ybrEZuY/CTrXIqYSizO335SxGJoWrKijaRy8htuueMkmNfxxhnBPoAjul/4T/FCRGKaV0jC96xYNnKcXbnXxSLVQ0OW2EIPvQhw/TU/G3vEqtiRYGyaNcZS6xrnVv3xuPuvVC1VRKspNLEq7zfvToC0OB89X5DIbvBbHY13PjJ0NrDdX3sSA8lxPsYagBuDIvyxH0S4Z5fQHeYrdvENS5zX6LwJeMeGSOqDuD0Zb4hpKxhaGVwP5e435VcFuImbFaDPM4w71PzaSUEj+tnUA0mGDoLiCrpW3txkJszog9lN3C/nLGghFaT7ajrfH55qut81JnvdhMju9+SzxrKPJmtQZfKVLIc4whEbtFsPCdm2bstz7ROWxTJ3t/Vr8/QVm2G2aY4FHuPwo2jUQDbQA7mCV+fe1sADy2jLzGhn1TCeYvWSv5PNJAT97IrLfD3+0Uo+qJD/6CU7F8oabj1Ql2H8fPN5kGSWfkM=
# server.example.org:22 SSH-2.0-OpenSSH_10.6
server.example.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJo5gc4VrxVQ5apAOd7qK6UqGlLMpWOPuunjB53JBN2s
# server.example.org:22 SSH-2.0-OpenSSH_10.6
# server.example.org:22 SSH-2.0-OpenSSH_10.6
# server.example.org:22 SSH-2.0-OpenSSH_10.6
server.example.org ssh-mldsa44-ed25519 AAAAE3NzaC1tbGRzYTQ0LWVkMjU1MTkAAAVAyIw5r9FaniSYqBX0yd9vgBz5nCkebaQlMQN9N0p//Ukfn/CnZ3YtZWn6pUGjDM85/bqdL1gqah1OLfnl1eHk0qvTACrym07uKaMLoEHuakIXHbTi/ELPRoRP3F+DpEgjtYSjLc/fJiobRMgSvmLJxTUzZTStsqWAL1L9/1zuwHEngR+THpUcCSTi6KKkYcQiWGOFwpO22VdiuOg+zdQSH+9jW6eXYk1z81KU6UlHZps8zVrlqCd3FDDghgbH5U8DcGN2t6GvVfn6jFjpEk0ouj0of3/7010eRXjnv3QSbprCpMq73lAemQM+3LvTtrMBhFWNhCXhyOHfO1Yq7c8xaOwlFK78PlERjdHTvVJaCaDFDy7Pg9I+wxv+uC+W0wtzJ2S1y9XCYUgJo9yEiIGuSZdhMkYUwMnXLzQMm44hQOW153pdlHWze3kESCLg/LJf9RbUoSB43t6rghSHEiUkIi5TtCtFZ4nAGeH+wVwlB9Fwog5uZuJN1FYuuY5sSrLHJAQDUwudkdak0ifOhtPtsM/ClYr3baolQ/qi0ABYUVLKSV5b+A5DlTXa23zc7JAXm2YVfkWpOfVJG4TY81wrJoDumsd1y3XaH28/4QbADsZCE3wYsBou8ff0xKgPu8xm2K+sYSmzUbBGprArAQA0LtIDGNGqrb4JsZ1ru+viwzfSlxV7Nz7ZrSw6h+Ddq4J9A6oKXy6YS3uf1GFOtBQm6JfuyMHQEEUtYZrU4UK3C/fKHx9vjuw7YdhsL8JRgxbF14qJLFizkmVbK2e6aWEE4iCqLLLlZ0dC2peYUUqyGb9PsW7sewYzGbipzPpQ/GobRT3Obc3Gmu8P386pDGR7hmkOpFmVwIcfc431cUmZixK7CkPxzUvfaAAQkmNs/p4eNNoP0gq/xPGsV14/heULbWp/njGWk1ysjjGxP6YMwHcEZpUdSGbD05zbL0KkMtmKsr8yuJYjdVAgtH2bVAvrxXRXLgavmm97VYYq1A9rOYiQFlMrKRg6yZhT10Xt8Hukf6ySLk+fieFc3nH99YeysoA5rsfp9kdXr65GpwrBerZlf/20ZLJ7s4xaYb9SukR/8tiPt9iAVQjqPdb0MseZVrzhKo/jK44JHbHejHMoMMs7etPAS5TIjHxcJTP66B3eO9A0l2fAage2ka7ehTnHivxD3EE9KnqYBjIHDU7o6dTrX7UyQsdhax9bPKEL7OEtm6hXXfwzy4GdqGi124BclFAF0LeBSvBUgmSKIn3wfzJx/XXbt512eOn3WZk2v0TsiteH9kPEgDxVkUykawg2tleak9rTFMzYpDZRHvZD7uHWUZ8ktr2FEKWgq7/1Q2c80Z6H75VK9l1d3KZuoiWoF1s73R7ZAM+CWSrR+S5h+3AhYubDKPa/af+Lnlqe6ocVTqQPYaaRz25/cLBg6pgbdh18Ru6h3ljG2KiysyXeuoEoM5xVYtdIW7l9NeKDpGbZPAOqywXUpK+UCGjumIl7c48KCTIYcdtolnEbfVNBh0LRuftcVI+uF9cvQ0XacaNbgkYJYCjv4VR/n58EJ1b0c7tQBrVqMjDjIUKGhCMQqAeD3g75jeD60bBmVNPrq8RK+zH5VIa5eaBs3eitN98eVzd4b6UYTQd1QxLQZMrhQf4InRj39TZfGvQR5SXlLZQlweVHYkMps3IKbs3B3DCqlWCPUAnTAJBAG7HqWEYr5uEaKBawBSAx9jCQz00T+bp8KXpkOPzZCD6dfEfpHY6Rv6kmGJkiPUCb2hoX145HrS357G12+wDxKLN833oPVC0z
</syntaxhighlight>
Once a key is acquired, its fingerprint can be shown using [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)] to read from '''stdin'''. This can be done directly with a pipe.
<syntaxhighlight lang="shell-session">
$ ssh-keyscan server.example.org | ssh-keygen -l -f -
3072 SHA256:tQlw3vy325KrQibndP3gLS/YXUZjTLVA5yDFpg/Bb6I server.example.org (RSA)
256 SHA256:snnAtb/9csdy0BGhPjdg+VNWqN5bxCa/ge4C6zZ8muk server.example.org (ECDSA)
256 SHA256:agRZDZn8awhQ+tc19Ip/whkHoV33Ln2REO7v1kcYbdU server.example.org (ED25519)
512 SHA256:3Wdc6GbLIcc5mbuF2mhhokhARdMLuMK+ESRfJ+sM0QE server.example.org (MLDSA44-ED25519)
</syntaxhighlight>
If there is more than one public key type is available from the server on the port polled, then [http://man.openbsd.org/ssh-keyscan.1 ssh-keyscan(1)] will fetch each of them. If there is more than one key fed via '''stdin''' or a file, then [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)] will process them in order. Prior to OpenSSH 7.2 manual fingerprinting was a two step process, the key was read to a file and then processed for its fingerprint.
<syntaxhighlight lang="shell-session">
$ ssh-keyscan -t ed25519 host.example.org > key.pub
# host.example.org SSH-2.0-OpenSSH_6.8
$ ssh-keygen -lf key.pub
256 SHA256:ZmS+IoHh31CmQZ4NJjv3z58Pfa0zMaOgxu8yAcpuwuw host.example.org (ED25519)
</syntaxhighlight>
Note that some output from [http://man.openbsd.org/ssh-keyscan.1 ssh-keyscan(1)] is sent to '''stderr''' instead of '''stdout'''.
A hash, or fingerprint, can be generated manually with [http://linux.die.net/man/1/awk awk(1)], [http://linux.die.net/man/1/sed sed(1)] and [http://linux.die.net/man/1/xxd xxd(1)], on systems where they are found.
<syntaxhighlight lang="shell-session">
$ awk '{print $2}' key.pub | base64 -d | md5sum -b | sed 's/../&:/g; s/: .*$//'
$ awk '{print $2}' key.pub | base64 -d | sha256sum -b | sed 's/ .*$//' | xxd -r -p | base64
</syntaxhighlight>
It is possible to find all hosts from a file which have new or different keys from those in '''known_hosts''', if the host names are in clear text and not stored as hashes.
<syntaxhighlight lang="shell-session">
$ ssh-keyscan -t ed25519,mldsa44-ed25519 -f ssh_hosts | \
sort -u - ~/.ssh/known_hosts | \
diff ~/.ssh/known_hosts -
</syntaxhighlight>
====Using ssh-keyscan(1) with ssh_config(5)====
The utility [http://man.openbsd.org/ssh-keyscan.1 ssh-keyscan(1)] does not parse [http://man.openbsd.org/ssh_config.5 ssh_config(5)]. That is in part to keep the code base simple. There are a lot of configuration options which would be complicated to implement, including but not limited to '''ProxyJump''', '''ProxyCommand''', '''Match''', '''BindInterface''', and '''CanonicalizeHostname'''<ref name="keyscan">{{cite mailing list |url=https://lists.mindrot.org/pipermail/openssh-unix-dev/2023-March/040605.html | title=Why does ssh-keyscan not use .ssh/config? |publisher=mindrot.org | access-date=2023-03-01 | date=2023-03-01 | mailing-list=OpenSSH UNIX-dev | first=Damien | last=Miller }}</ref> . Resolving host names via the client configuration file can be done by wrapping the utility in a short shell function:
<syntaxhighlight lang="shell">
my-ssh-keyscan() {
for host in "$@" ; do
ssh-keyscan $(ssh -G "$host" | awk '/^hostname/ {print $2}')
done
}
</syntaxhighlight>
That shell function uses the '''-G''' option of [http://man.openbsd.org/ssh.1 ssh(1)] to resolve each host name using [http://man.openbsd.org/ssh_config.5 ssh_config(5)] and then check the resulting host name for SSH keys.
===ASCII Art Visual Host Key===
An ASCII art representation of the key can be displayed along with the SHA256 base64 fingerprint:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -l -v -f key
256 SHA256:BClQBFAGuz55+tgHM1aazI8FUo8eJiwmMcqg2U3UgWU www.example.org (ED25519)
+--[ED25519 256]--+
|o+=*++Eo |
|+o .+.o. |
|B=.oo. . |
|*B.=.o . |
|= B * S |
|. .@ . |
| +..B |
| *. o |
| o.o. |
+----[SHA256]-----+
</syntaxhighlight>
In OpenSSH 6.7 and earlier the fingerprint is in MD5 hexadecimal form.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -l -v -f key
2048 37:af:05:99:e7:fb:86:6c:98:ee:14:a6:30:06:bc:f0 www.example.net (RSA)
+--[ RSA 2048]----+
| o |
| o . |
| o o |
| o + |
| . . S |
| E .. |
| .o.* .. |
| .*=.+o |
| ..==+. |
+-----------------+
</syntaxhighlight>
==More on Verifying SSH Keys==
Keys on the client or the server can be verified against known good keys by comparing the base64-encoded SHA256 fingerprints.
===Verifying Stray Client Keys===
Sometimes is is necessary to compare two uncertain key files to check if they are part of the same key pair. However, public keys are more or less disposable. So the easy way in such situations on the client machine is to just rename or erase the old, problematic, public key and replace it with a new one generated from the existing private key.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -y -f ~/.ssh/my_key_ed25519
</syntaxhighlight>
But if the two parts must really be compared, it is done in two steps using [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)]. First, a new public key is re-generated from the known private key and used to make a fingerprint to '''stdout'''. Next, the fingerprint of the unknown public key is generated for comparison. In this example, the private key '''my_key_a_ed25519''' and the public key '''my_key_b_ed25519.pub''' are compared:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -y -f my_key_a_ed25519 | ssh-keygen -l -f -
$ ssh-keygen -l -f my_key_b_ed25519.pub
</syntaxhighlight>
The result is a base64-encoded SHA256 checksum for each key with the one fingerprint displayed right below the other for easy visual comparison. Older versions don't support reading from '''stdin''' so an intermediate file will be needed then. Even older versions will only show an MD5 checksum for each key. Either way, automation with a shell script is simple enough to accomplish but outside the scope of this book.
===Verifying Server Keys===
Reliable verification of a server's host key must be done when first connecting. It can be necessary to contact the system administrator who can provide it out of band so as to know the fingerprint in advance and have it ready to verify the first connection.
Here is an example of the server's Ed25519 key being read and its fingerprint shown as SHA256 base64:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub
256 SHA256:bFzzouaWmE5HuZIv+YnGUYI2q06i6M43V+6jMU3LHpA root@server.example.org (ED25519)
</syntaxhighlight>
And here the corresponding ECDSA key is read, but shown as an MD5 hexadecimal hash:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -E md5 -l -f /etc/ssh/ssh_host_ecdsa_key.pub
256 MD5:ed:d2:34:b4:93:fd:0e:eb:08:ee:b3:c4:b3:4f:28:e4 root@server.example.net (ECDSA)
</syntaxhighlight>
Prior to 6.8, the fingerprint was expressed as an MD5 hexadecimal hash:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub
2048 MD5:e4:a0:f4:19:46:d7:a4:cc:be:ea:9b:65:a7:62:db:2c root@server.example.net (RSA)
</syntaxhighlight>
It is also possible to use [http://man.openbsd.org/ssh-keyscan.1 ssh-keyscan(1)] to get keys from an active SSH server. However, the fingerprints still needs to be verified out of band.
====Warning: Remote Host Identification Has Changed!====
If a server's key does not match what the client finds has been recorded in either the system's or the local account's '''authorized_keys''' files, then the client will issue a warning along with the fingerprint of the suspicious key.
<pre>
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:bFzzouaWmE5HuZIv+YnGUYI2q06i6M43V+6jMU3LHpA.
Please contact your system administrator.
Add correct host key in /home/fred/.ssh/known_hosts to get rid of this message.
Offending ED25519 key in /home/fred/.ssh/known_hosts:11
Host key for server.example.org has changed and you have requested strict checking.
Host key verification failed.
</pre>
Three reasons for the warning are common.
One reason is that the server's keys were replaced, often because the server's operating system was reinstalled without backing up the old keys. Another reason can be when the system administrator has phased out deprecated or compromised keys. However that can be planned better and if there is time to plan the migration, new keys can just be added to the server and have the clients use the '''UpdateHostKeys''' option so that the new keys are accepted if the old keys match. A third situation is when the connection is made to the wrong machine, such as when the remote system changes IP addresses because of dynamic address allocation.
In all three cases where the key has changed there is only one thing to do: contact the system administrator and verify the key. Ask if the OpenSSH-server was recently reinstalled, or was the machine restored from an old backup? Keep in mind that the system administrator may be you yourself in some cases.
The case which is rather rare but serious enough that it should be ruled out for sure is that the wrong machine is part of a man-in-the-middle attack.
In all four cases, an authentic key fingerprint can be acquired by any method where it is possible to verify the integrity and origin of the message, for example via PGP-signed e-mail. If physical access is possible, then use the console to get the right fingerprint. Once the authentic key fingerprint is available, return to the client machine where you got the error and remove the old key from '''~/.ssh/known_hosts'''
<syntaxhighlight lang="shell-session">
$ ssh-keygen -R server.example.org
</syntaxhighlight>
Then try logging in, but compare the key fingerprints first and proceed if and '''only''' if the key fingerprint matches what you received out of band. If the key fingerprint matches, then go through with the login process and the key will be automatically added. If the key fingerprint does not match, stop immediately and figure out what you are connecting to. It would be a good idea to get on the phone, a real phone not a computer phone, to the remote machine's system administrator or the network administrator.
===Multiple Keys for a Host, Multiple Hosts for a Key in known_hosts===
Multiple host names or IP addresses can use the same key in the '''known_hosts''' file by using pattern matching or simply by listing multiple systems for the same key. That can be done in either the global list of keys in '''/etc/ssh/ssh_known_hosts''' and the local, account-specific lists of keys in each account's '''~/.ssh/known_hosts''' file. Labs, computational clusters, and similar pools of machines can make use of keys in that way. Here is a key shared by three specific hosts, identified by name, one host per line:
<pre>
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
server2 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
server3 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
</pre>
Or a range can be specified by using globbing to a limited extent in either '''/etc/ssh/ssh_known_hosts''' or '''~/.ssh/known_hosts'''.
<pre>
172.19.40.* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
</pre>
Conversely, a pool of servers might have multiple keys for the same address. In that case, it is necessary to make multiple entries in either '''/etc/ssh/ssh_known_hosts''' or '''~/.ssh/known_hosts''' for each key.
<pre>
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBrsIIaDl/bJ40vyprvF+HYAq+kE2jWUsOt+WqIheaBw fred@desk.example.org
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC2CgwWTPH/qZDeHmW7ZUea18wa9As7Txq3P5dXCfoXj fred@desk.example.org
</pre>
Thus in order to get a pool of servers to share a pool of keys, each server-key combination must be added manually to the '''known_hosts''' file:
<pre>
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIId09yQEh9634wNXR+y7L79th2M4awBgCwqWJobJuQ fred@desk.example.org
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBrsIIaDl/bJ40vyprvF+HYAq+kE2jWUsOt+WqIheaBw fred@desk.example.org
server1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC2CgwWTPH/qZDeHmW7ZUea18wa9As7Txq3P5dXCfoXj fred@desk.example.org
server2 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICPSs4OR2LT89mv2tM4TKqeVhh4XvoLQ77MSBmjyrMGm fred@desk.example.org
server2 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHChTzAoJr53A7VP1BdMHqLTFK5cz/2Vc065+VcpP4VA fred@desk.example.org
server2 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHP+4BvU4DzwYQgznARxx/qyBWmu49PAywHwDRgslRaM fred@desk.example.org
</pre>
Though upgrading to certificates might be a more appropriate approach that manually updating lots of keys.
===Another way of Dealing with Dynamic (roaming) IP Addresses===
It is possible to manually point to the right key using '''HostKeyAlias''' either as part of [http://man.openbsd.org/ssh_config.5 ssh_config(5)] or as a runtime parameter. Here the key for machine ''Foobar'' is used to connect to host 192.168.11.15
<syntaxhighlight lang="shell-session">
$ ssh -o StrictHostKeyChecking=accept-new \
-o HostKeyAlias=foobar \
192.168.11.15
</syntaxhighlight>
This is useful when DHCP is not configured to try to keep the same addresses for the same machines over time or when using certain stdio forwarding methods to pass through intermediate hosts.
===Host Key Update and Rotation in known_hosts===
A protocol extension to rotate weak public keys out of '''known_hosts''' has been in OpenSSH from version 6.8<ref name="djm_rotation">
{{cite web
| title=Key rotation in OpenSSH 6.8+
| author=Damien Miller
| url=http://blog.djm.net.au/2015/02/key-rotation-in-openssh-68.html
| date=2015-02-01
| publisher=DJM's Personal Weblog
| accessdate=2016-03-05
}}
</ref> and later. With it the server is able to inform the client of all its host keys and update '''known_hosts''' with new ones when at least one trusted key already known. This method still requires the private keys be available to the server <ref name="djm_rotation_redux">
{{cite web
| title=Hostkey rotation, redux
| author=Damien Miller
| url=http://blog.djm.net.au/2015/02/hostkey-rotation-redux.html
| date=2015-02-17
| publisher=DJM's Personal Weblog
| accessdate=2016-03-05
}}
</ref> so that proofs can be completed. In [http://man.openbsd.org/ssh_config.5 ssh_config(5)], the directive '''UpdateHostKeys''' specifies whether the client should accept updates of additional host keys from the server after authentication is completed and add them to '''known_hosts'''. A server can offer multiple keys of the same type for a period before removing the deprecated key from those offered, thus allowing an automated option for rotating keys as well as for upgrading from weaker algorithms to stronger ones. See also [https://datatracker.ietf.org/doc/html/rfc4819 RFC 4819: Secure Shell Public Key Subsystem] about key management standards.
==Converting Between SSH Key Formats==
OpenSSH has its own format for keys which it uses by default when new keys are made. However, other SSH clients and servers may use other formats such as [https://www.rfc-editor.org/rfc/rfc4716 RFC 4716], [https://www.rfc-editor.org/rfc/rfc5958 PKCS8], or [https://www.rfc-editor.org/rfc/rfc1421 PEM]. Any of these can be converted to the default OpenSSH format by [http://man.openbsd.org/ssh-keygen.1 ssh-keygen(1)]. The default to format to try to convert from is RFC 4716. The utility [https://linux.die.net/man/1/puttygen puttygen(1)] makes keys in that format for [https://linux.die.net/man/1/putty putty(1)] and they need conversion when used with OpenSSH's server.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -i -f /var/tmp/key_public.ppk
</syntaxhighlight>
However, you can use the '''-m''' option to specify either that format explicitly or else choose another one to convert from.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -i -m RFC4716 -f /var/tmp/key_public.ppk
$ ssh-keygen -i -m PKCS8 -f /var/tmp/key_public.ppk
</syntaxhighlight>
Both examples above are for importing public keys into OpenSSH's own format.
By default OpenSSH will write newly-generated keys in its own format, so the '''-m''' option is obligatory to produce public keys in another format.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -e -m PKCS8 -f ~/.ssh/key.pub
</syntaxhighlight>
It is not yet possible to export private keys from the OpenSSH format to one of the other formats using the '''-e''' option. Even if a private key is specified as input, a public key is produced:
<syntaxhighlight lang="shell-session">
$ ssh-keygen -e -m RFC4716 -f ~/.ssh/key
</syntaxhighlight>
Not all key types are supported by all key formats.
It is also possible to use export to display the key pair as a traditional hex dump.
<syntaxhighlight lang="shell-session">
$ ssh-keygen -e -m hexdump -f ~/.ssh/key
Enter passphrase for "key":
Public ED25519 key:
buffer len = 51
0000: 00 00 00 0b 73 73 68 2d 65 64 32 35 35 31 39 00 ....ssh-ed25519.
0016: 00 00 20 b0 c5 cc 2c cb d8 8b 8d 75 80 eb e6 e9 .. ...,....u....
0032: 2c f4 36 08 7b 5b ad ad 0b 54 4f 7f 21 9d 1b e8 ,.6.{[...TO.!...
0048: 9e e0 32 ..2
Private ED25519 key:
buffer len = 119
0000: 00 00 00 0b 73 73 68 2d 65 64 32 35 35 31 39 00 ....ssh-ed25519.
0016: 00 00 20 b0 c5 cc 2c cb d8 8b 8d 75 80 eb e6 e9 .. ...,....u....
0032: 2c f4 36 08 7b 5b ad ad 0b 54 4f 7f 21 9d 1b e8 ,.6.{[...TO.!...
0048: 9e e0 32 00 00 00 40 e1 c3 a2 4d d9 89 49 72 9b ..2...@...M..Ir.
0064: 86 72 6c 07 17 1b 40 4f 62 50 62 45 4f 4c cf cf .rl...@ObPbEOL..
0080: 57 8b 9d c0 04 8f 9b b0 c5 cc 2c cb d8 8b 8d 75 W.........,....u
0096: 80 eb e6 e9 2c f4 36 08 7b 5b ad ad 0b 54 4f 7f ....,.6.{[...TO.
0112: 21 9d 1b e8 9e e0 32 !.....2
</syntaxhighlight>
<noinclude>
== References ==
{{reflist}}
{{OpenSSH/TOC|mini}}
</noinclude>
{{BookCat}}
{{status|100%}}
le3ajzz9qnrxqr2xwnipgp48cnb6h3k
Haskell/Classes and types
0
54044
4676013
4666182
2026-10-14T11:05:10Z
Luciérnaga de conocimiento
3401314
4676013
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Intermediate Haskell|noexercises=1}}
Back in [[../Type basics II|Type basics II]] we had a brief encounter with type classes as the mechanism used with number types. As we hinted back then, however, classes have many other uses.
Broadly speaking, the point of type classes is to ensure that certain operations will be available for values of chosen types. For example, if we know a type belongs to (or, to use the jargon, ''instantiates'') the class <code>Fractional</code>, then we are guaranteed, among other things, to be able to perform real division with its values.<ref>''To programmers coming from object-oriented languages'': A class in Haskell in all likelihood is ''not'' what you expect - don't let the terms confuse you. While some of the uses of type classes resemble what is done with abstract classes or Java interfaces, there are fundamental differences which will become clear as we advance.</ref>
== Classes and instances ==
Up to now we have seen how existing type classes appear in signatures such as:
<syntaxhighlight lang = "haskell">
(==) :: (Eq a) => a -> a -> Bool
</syntaxhighlight>
Now it is time to switch perspectives. First, we quote the definition of the <code>Eq</code> class from Prelude:
<syntaxhighlight lang = "haskell">
class Eq a where
(==), (/=) :: a -> a -> Bool
-- Minimal complete definition:
-- (==) or (/=)
x /= y = not (x == y)
x == y = not (x /= y)
</syntaxhighlight>
The definition states that if a type <code>a</code> is to be made an ''instance'' of the class <code>Eq</code> it must support the functions <code>(==)</code> and <code>(/=)</code> - the ''class methods'' - both of them having type <code>a -> a -> Bool</code>. Additionally, the class provides default definitions for <code>(==)</code> and <code>(/=)</code> ''in terms of each other''. As a consequence, there is no need for a type in <code>Eq</code> to provide both definitions - given one of them, the other will be generated automatically.
With a class defined, we proceed to make existing types instances of it. Here is an arbitrary example of an algebraic data type made into an instance of <code>Eq</code> by an ''instance declaration'':
<syntaxhighlight lang = "haskell">
data Foo = Foo {x :: Integer, str :: String}
instance Eq Foo where
(Foo x1 str1) == (Foo x2 str2) = (x1 == x2) && (str1 == str2)
</syntaxhighlight>
And now we can apply <code>(==)</code> and <code>(/=)</code> to <code>Foo</code> values in the usual way:
{{Haskell/GHCi|1=
*Main> Foo 3 "orange" == Foo 6 "apple"
False
*Main> Foo 3 "orange" /= Foo 6 "apple"
True
}}
A few important remarks:
* The class <code>Eq</code> is defined in the Standard Prelude. This code sample defines the type <code>Foo</code> and then declares it to be an instance of <code>Eq</code>. The three definitions (class, data type, and instance) are ''completely separate'' and there is no rule about how they are grouped. This works both ways: you could just as easily create a new class <code>Bar</code> and then declare the type <code>Integer</code> to be an instance of it.
* ''Classes are not types'', but categories of types, and so the instances of a class are types instead of values.<ref>This is a key difference from most OO languages, where a class is also itself a type.</ref>
* The definition of <code>(==)</code> for <code>Foo</code> relies on the fact that the values of its fields (namely <code>Integer</code> and <code>String</code>) are also members of <code>Eq</code>. In fact, almost all types in Haskell are members of <code>Eq</code> (the most notable exception being functions).
* Type synonyms defined with <code>type</code> keyword cannot be made instances of a class.
== Deriving ==
Since equality tests between values are commonplace, in all likelihood most of the data types you create in any real program should be members of <code>Eq</code>. A lot of them will also be members of other Prelude classes such as <code>Ord</code> and <code>Show</code>. To avoid large amounts of boilerplate for every new type, Haskell has a convenient way to declare the "obvious" instance definitions using the keyword <code>deriving</code>. So, <code>Foo</code> would be written as:
<syntaxhighlight lang = "haskell">
data Foo = Foo {x :: Integer, str :: String}
deriving (Eq, Ord, Show)
</syntaxhighlight>
This makes <code>Foo</code> an instance of <code>Eq</code> with an automatically generated definition of <code>==</code> exactly equivalent to the one we just wrote, and also makes it an instance of <code>Ord</code> and <code>Show</code> for good measure.
You can only use <code>deriving</code> with a limited set of built-in classes, which are described ''very'' briefly below:
; Eq : Equality operators <code>==</code> and <code>/=</code>
; Ord : Comparison operators <code>< <= > >=</code>; <code>min</code>, <code>max</code>, and <code>compare</code>.
; Enum : For enumerations only. Allows the use of list syntax such as <code>[Blue .. Green]</code>.
; Bounded : Also for enumerations, but can also be used on types that have only one constructor. Provides <code>minBound</code> and <code>maxBound</code> as the lowest and highest values that the type can take.
; Show : Defines the function <code>show</code>, which converts a value into a string, and other related functions.
; Read : Defines the function <code>read</code>, which parses a string into a value of the type, and other related functions.
The precise rules for deriving the relevant functions are given in the language report. However, they can generally be relied upon to be the "right thing" for most cases. The types of elements inside the data type must also be instances of the class you are deriving.
This provision of special "magic" function synthesis for a limited set of predefined classes goes against the general Haskell philosophy that "built in things are not special", but it does save a lot of typing. Besides that, deriving instances stops us from writing them in the wrong way (an example: an instance of <code>Eq</code> such that <code>x == y</code> would not be equal to <code>y == x</code> would be flat out wrong). <ref>There are ways to make the magic apply to other classes. GHC extensions allow <code>deriving</code> for a few other common classes for which there is only one correct way of writing the instances, and the GHC generics machinery make it possible to generate instances automatically for custom classes.</ref>
== Class inheritance ==
Classes can inherit from other classes. For example, here is the main part of the definition of <code>Ord</code> in Prelude:
<syntaxhighlight lang = "haskell">
class (Eq a) => Ord a where
compare :: a -> a -> Ordering
(<), (<=), (>=), (>) :: a -> a -> Bool
max, min :: a -> a -> a
</syntaxhighlight>
The actual definition is rather longer and includes default implementations for most of the functions. The point here is that <code>Ord</code> inherits from <code>Eq</code>. This is indicated by the <code>=></code> notation in the first line, which mirrors the way classes appear in type signatures. Here, it means that for a type to be an instance of <code>Ord</code> it must also be an instance of <code>Eq</code>, and hence needs to implement the <code>==</code> and <code>/=</code> operations.<ref>If you check the full definition in the {{Haskell/Lib|Prelude}} specification, the reason for that becomes clear: the default implementations involve applying <code>(==)</code> to the values being compared.</ref>
A class can inherit from several other classes: just put all of its superclasses in the parentheses before the <code>=></code>. Let us illustrate that with yet another Prelude quote:
<syntaxhighlight lang = "haskell">
class (Num a, Ord a) => Real a where
-- | the rational equivalent of its real argument with full precision
toRational :: a -> Rational
</syntaxhighlight>
== Standard classes ==
This diagram, adapted from the Haskell Report, shows the relationships between the classes and types in the Standard Prelude. The names in bold are the classes, while the non-bold text stands for the types that are instances of each class (<code>(->)</code> refers to functions and <code>[]</code>, to lists). The arrows linking classes indicate the inheritance relationships, pointing to the inheriting class.
[[File:Base-classes.svg|frame|Summary of the hierarchy of base typeclasses]]
== Type constraints ==
With all pieces in place, we can go full circle by returning to the very first example involving classes in this book:
<syntaxhighlight lang = "haskell">
(+) :: (Num a) => a -> a -> a
</syntaxhighlight>
<code>(Num a) =></code> is a ''type constraint'', which restricts the type <code>a</code> to instances of the class <code>Num</code>. In fact, <code>(+)</code> is a method of <code>Num</code>, along with quite a few other functions (notably, <code>(*)</code> and <code>(-)</code>; but not <code>(/)</code>).
You can put several limits into a type signature like this:
<syntaxhighlight lang = "haskell">
foo :: (Num a, Show a, Show b) => a -> a -> b -> String
foo x y t =
show x ++ " plus " ++ show y ++ " is " ++ show (x+y) ++ ". " ++ show t
</syntaxhighlight>
Here, the arguments <code>x</code> and <code>y</code> must be of the same type, and that type must be an instance of both <code>Num</code> and <code>Show</code>. Furthermore, the final argument <code>t</code> must be of some (possibly different) type that is also an instance of <code>Show</code>. This example also displays clearly how constraints propagate from the functions used in a definition (in this case, <code>(+)</code> and <code>show</code>) to the function being defined.
=== Other uses ===
Beyond simple type signatures, type constraints can be introduced in a number of other places:
* <code>instance</code> declarations (typical with parametrized types<!--; we will present an example of such usage shortly-->);
* <code>class</code> declarations (constraints can be introduced in the method signatures in the usual way for any type variable other than the one defining the class<ref>Constraints for the type defining the class should be set via class inheritance.</ref>);
* <code>data</code> declarations,<ref>And <code>newtype</code> declarations as well, but not <code>type</code>.</ref> where they act as constraints for the constructor signatures.
{{body note|1=
Type constraints in <code>data</code> declarations are less useful than it might seem at first. Consider:
<syntaxhighlight lang = "haskell">
data (Num a) => Foo a = F1 a | F2 a String
</syntaxhighlight>
Here, <code>Foo</code> is a type with two constructors, both taking an argument of a type <code>a</code> which must be in <code>Num</code>. However, the <code>(Num a) =></code> constraint is only effective for the <code>F1</code> and <code>F2</code> constructors, and not for other functions involving <code>Foo</code>. Therefore, in the following example...
<syntaxhighlight lang = "haskell">
fooSquared :: (Num a) => Foo a -> Foo a
fooSquared (F1 x) = F1 (x * x)
fooSquared (F2 x s) = F2 (x * x) s
</syntaxhighlight>
... even though the constructors ensure <code>a</code> will be some type in <code>Num</code> we can't avoid duplicating the constraint in the signature of <code>fooSquared</code>.<ref>''Extra note for the curious'': This issue is related to some of the problems tackled by the advanced features discussed in the "Fun with types" chapter of the Advanced Track.</ref>
}}
== A concerted example ==
To provide a better view of the interplay between types, classes, and constraints, we will present a very simple and somewhat contrived example. We will define a <code>Located</code> class, a <code>Movable</code> class which inherits from it, and a function with a <code>Movable</code> constraint implemented using the methods of the parent class, i.e. <code>Located</code>.
<syntaxhighlight lang = "haskell">
-- Location, in two dimensions.
class Located a where
getLocation :: a -> (Int, Int)
class (Located a) => Movable a where
setLocation :: (Int, Int) -> a -> a
-- An example type, with accompanying instances.
data NamedPoint = NamedPoint
{ pointName :: String
, pointX :: Int
, pointY :: Int
} deriving (Show)
instance Located NamedPoint where
getLocation p = (pointX p, pointY p)
instance Movable NamedPoint where
setLocation (x, y) p = p { pointX = x, pointY = y }
-- Moves a value of a Movable type by the specified displacement.
-- This works for any movable, including NamedPoint.
move :: (Movable a) => (Int, Int) -> a -> a
move (dx, dy) p = setLocation (x + dx, y + dy) p
where
(x, y) = getLocation p
</syntaxhighlight>
=== A word of advice ===
Do not read too much into the <code>Movable</code> example just above; it is merely a demonstration of class-related language features. It would be a mistake to think that every single functionality which might be conceivably generalized, such as <code>setLocation</code>, needs a type class of its own. In particular, if all your <code>Located</code> instances should be able to be moved as well then <code>Movable</code> is unnecessary - and if there is just one instance there is no need for type classes at all! Classes are best used when there are several types instantiating it (or if you expect others to write additional instances) and you do not want users to know or care about the differences between the types. An extreme example would be <code>Show</code>: general-purpose functionality implemented by an immense number of types, about which you do not need to know a thing before calling <code>show</code>. In the following chapters, we will explore a number of important type classes in the libraries; they provide good examples of the sort of functionality which fits comfortably into a class.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Intermediate Haskell|noexercises=1}}
{{BookCat}}
evu5lmrhx158y6ez7oy6d7vhmgt1alb
Haskell/Control structures
0
55093
4675949
4666169
2026-10-14T00:32:13Z
~2026-54868-50
3628373
4675949
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Elementary Haskell|noexercises=0}}
Haskell offers several ways of expressing a choice between different values. We explored some of them in the Haskell Basics chapters. This section will bring together what we have seen thus far, discuss some finer points, and introduce a new control structure.
== <code>if</code> and guards revisited ==
We have already met these constructs. The syntax for <code>if</code> expressions is:
<syntaxhighlight lang="haskell">
if <condition> then <true-value> else <false-value>
</syntaxhighlight>
<code><condition></code> is an expression which evaluates to a boolean. If the <code><condition></code> is <code>True</code> then the <code><true-value></code> is returned, otherwise the <code><false-value></code> is returned. Note that in Haskell <code>if</code> is an expression (which is converted to a value) and not a statement (which is executed) as in many imperative languages.<ref>If you have programmed in C or Java, you will recognize Haskell's if/then/else as an equivalent to the ternary conditional operator <code>?:</code> .</ref> As a consequence, the <code>else</code> is ''mandatory'' in Haskell. Since <code>if</code> is an expression, it must evaluate to a result whether the condition is true or false, and the <code>else</code> ensures this. Furthermore, <code><true-value></code> and <code><false-value></code> must evaluate to the same type, which will be the type of the whole if expression.
When <code>if</code> expressions are split across multiple lines, they are usually indented by aligning <code>else</code>s with <code>then</code>s, rather than with <code>if</code>s. A common style looks like this:
<syntaxhighlight lang="haskell">
describeLetter :: Char -> String
describeLetter c =
if c >= 'a' && c <= 'z'
then "Lower case"
else if c >= 'A' && c <= 'Z'
then "Upper case"
else "Not an ASCII letter"
</syntaxhighlight>
Guards and top-level <code>if</code> expressions are mostly interchangeable. With guards, the example above is a little neater:
<syntaxhighlight lang="haskell">
describeLetter :: Char -> String
describeLetter c
| c >= 'a' && c <= 'z' = "Lower case"
| c >= 'A' && c <= 'Z' = "Upper case"
| otherwise = "Not an ASCII letter"
</syntaxhighlight>
Remember that <code>otherwise</code> is just an alias to <code>True</code>, and thus the last guard is a catch-all, playing the role of the final <code>else</code> of the <code>if</code> expression.
Guards are evaluated in the order they appear. Consider a set up like the following:
<syntaxhighlight lang="haskell">
f (pattern1) | predicate1 = w
| predicate2 = x
f (pattern2) | predicate3 = y
| predicate4 = z
</syntaxhighlight>
Here, the argument of <code>f</code> will be pattern-matched against pattern1. If it succeeds, then we proceed to the first set of guards: if predicate1 evaluates to <code>True</code>, then <code>w</code> is returned. If not, then predicate2 is evaluated; and if it is true <code>x</code> is returned. Again, if not, then we proceed to the next case and try to match the argument against pattern2, repeating the guards procedure with predicate3 and predicate4. (Of course, if neither pattern matches or neither predicate is true for the matching pattern there will be a runtime error. Regardless of the chosen control structure, it is important to ensure all cases are covered.)
=== Embedding <code>if</code> expressions ===
A handy consequence of <code>if</code> constructs being ''expressions'' is that they can be placed anywhere a Haskell expression could be, allowing us to write code like this:
<syntaxhighlight lang="haskell">
g x y = (if x == 0 then 1 else sin x / x) * y
</syntaxhighlight>
Note that we wrote the <code>if</code> expression without line breaks for maximum terseness. Unlike <code>if</code> expressions, guard blocks are not expressions; and so a <code>let</code> or a <code>where</code> definition is the closest we can get to this style when using them. Needless to say, more complicated one-line <code>if</code> expressions would be hard to read, making <code>let</code> and <code>where</code> attractive options in such cases.
== Short-circuit operators ==
The <code>||</code> and <code>&&</code> operators mentioned [[Haskell/Truth values#Boolean operations|before]] are in fact control structures: they evaluate the first argument and then the second argument only if needed.
===Avoiding excessive effort===
For instance, suppose a large number n is to be checked to determine if it is a prime number and a function isPrime is available, but alas, it requires a lot of computation to evaluate. Using the function <syntaxhighlight lang="haskell" inline>\n -> n == 2 || (n `mod` 2 /= 0 && isPrime n)</syntaxhighlight> will help if there are to be many evaluations with even values of n.
===Avoidance of error conditions===
<code>&&</code> can be used to avoid signalling a run-time error, such as divide-by-zero or index-out-of-bounds, etc. For instance, the following locates the last non-zero element of a list:
<syntaxhighlight lang="haskell">
lastNonZero a = go a (length a-1)
where
go a l | l >= 0 && a !! l == 0 = go a (l-1)
| l < 0 = Nothing
| otherwise = Just (a !! l)
</syntaxhighlight>
Should all elements of the list be zero, the loop will work down to <code>l = -1</code>, and in this case the condition in the first guard will be evaluated without attempting to dereference element -1, which does not exist.
== <code>case</code> expressions ==
One control structure we haven't talked about yet is <code>case</code> expressions. They are to piece-wise function definitions what <code>if</code> expressions are to guards. Take this simple piece-wise definition:
<syntaxhighlight lang="haskell">
f 0 = 18
f 1 = 15
f 2 = 12
f x = 12 - x
</syntaxhighlight>
It is equivalent to - and, indeed, syntactic sugar for:
<syntaxhighlight lang="haskell">
f x =
case x of
0 -> 18
1 -> 15
2 -> 12
_ -> 12 - x
</syntaxhighlight>
Whatever definition we pick, the same happens when <code>f</code> is called: The argument <code>x</code> is matched against all of the patterns in order, and on the first match the expression on the right-hand side of the corresponding equal sign (in the piece-wise version) or arrow (in the <code>case</code> version) is evaluated. Note that in this <code>case</code> expression there is no need to write <code>x</code> in the pattern; the wildcard pattern <code>_</code> gives the same effect.<ref>To see why this is so, consider our discussion of matching and binding in the [[../Pattern matching/]] section</ref>
Indentation is important when using <code>case</code>. The cases must be indented further to the right than the beginning of the line containing the <code>of</code> keyword, and all cases must have the same indentation. For the sake of illustration, here are two other valid layouts for a <code>case</code> expression:
<syntaxhighlight lang="haskell">
f x = case x of
0 -> 18
1 -> 15
2 -> 12
_ -> 12 - x
</syntaxhighlight>
<br/>
<syntaxhighlight lang="haskell">
f x = case x of 0 -> 18
1 -> 15
2 -> 12
_ -> 12 - x
</syntaxhighlight>
Since the left hand side of any case branch is just a pattern, it can also be used for binding, exactly like in piece-wise function definitions:<ref>Thus, <code>case</code> expressions are a lot more versatile than most of the superficially similar switch/case statements in imperative languages which are typically restricted to equality tests on integral primitive types.</ref>
<syntaxhighlight lang="haskell">
describeString :: String -> String
describeString str =
case str of
(x:xs) -> "The first character of the string is: " ++ [x] ++ "; and " ++
"there are " ++ show (length xs) ++ " more characters in it."
[] -> "This is an empty string."
</syntaxhighlight>
This function describes some properties of <code>str</code> using a human-readable string. Using case syntax to bind variables to the head and tail of our list is convenient here, but you could also do this with an if-expression (with a condition of <code>null str</code> to pick the empty string case).
Finally, just like <code>if</code> expressions (and unlike piece-wise definitions), <code>case</code> expressions can be embedded anywhere another expression would fit:
<syntaxhighlight lang="haskell">
data Colour = Black | White | RGB Int Int Int
describeBlackOrWhite :: Colour -> String
describeBlackOrWhite c =
"This colour is"
++ case c of
Black -> " black"
White -> " white"
RGB 0 0 0 -> " black"
RGB 255 255 255 -> " white"
_ -> "... uh... something else"
++ ", yeah?"
</syntaxhighlight>
The case block above fits in as any string would. Writing <code>describeBlackOrWhite</code> this way makes <code>let</code>/<code>where</code> unnecessary (although the resulting definition is not as readable).
{{Exercises|1=
Use a <code>case</code> expression to implement a <code>fakeIf</code> function which could be used as a replacement to the familiar <code>if</code> expressions.
}}
== Controlling actions, revisited ==
In the final part of this chapter, we will introduce a few extra points about control structures while revisiting the discussions in the "Simple input and output" chapter. There, in the [[../Simple input and output#Controlling actions|Controlling actions]] section, we used the following function to show how to execute actions conditionally within a <code>do</code> block using <code>if</code> expressions:
<syntaxhighlight lang="haskell">
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
if (read guess) < num
then do putStrLn "Too low!"
doGuessing num
else if (read guess) > num
then do putStrLn "Too high!"
doGuessing num
else putStrLn "You Win!"
</syntaxhighlight>
We can write the same <code>doGuessing</code> function using a <code>'''case'''</code>
expression. To do this, we first introduce the Prelude function
<code>compare</code> which takes two values of the same type (in the <code>Ord</code>
class) and returns a value of type <code>Ordering</code> — namely one of
<code>GT</code>, <code>LT</code>, <code>EQ</code>, depending on
whether the first is greater than, less than, or equal to the second.
<syntaxhighlight lang="haskell">
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
case compare (read guess) num of
LT -> do putStrLn "Too low!"
doGuessing num
GT -> do putStrLn "Too high!"
doGuessing num
EQ -> putStrLn "You Win!"
</syntaxhighlight>
The <code>'''do'''</code>s after the <code>-></code>s are necessary on the
first two options, because we are sequencing actions within each case.
=== A note about <code>return</code> ===
Now, we are going to dispel a possible source of confusion. In a typical imperative
language (C, for example) an implementation of <code>doGuessing</code> might look like the following
(if you don't know C, don't worry with the details, just follow the if-else chain):
<syntaxhighlight lang="c">
void doGuessing(int num) {
printf("Enter your guess:");
int guess = atoi(readLine());
if (guess == num) {
printf("You win!\n");
return;
}
// we won't get here if guess == num
if (guess < num) {
printf("Too low!\n");
doGuessing(num);
} else {
printf("Too high!\n");
doGuessing(num);
}
}
</syntaxhighlight>
This <code>doGuessing</code> first tests the equality case, which does not lead to
a new call of <code>doGuessing</code>, and the <code>if</code> has no accompanying
<code>else</code>. If the guess was right, a <code>return</code> statement is used to
exit the function at once, skipping the other cases. Now, going back to Haskell, action
sequencing in <code>do</code> blocks looks a lot like imperative code, and furthermore
there actually ''is'' a <code>return</code> in Prelude. Then, knowing that <code>case</code>
expressions (unlike <code>if</code> expressions) do not force us to cover all cases, one
might be tempted to write a literal translation of the C code above (try running it if
you are curious)...
<syntaxhighlight lang="haskell">
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
case compare (read guess) num of
EQ -> do putStrLn "You win!"
return ()
-- we don't expect to get here if guess == num
if (read guess < num)
then do putStrLn "Too low!"
doGuessing num
else do putStrLn "Too high!"
doGuessing num
</syntaxhighlight>
... but it won't work! If you guess correctly, the function
will first print "You win!," but it ''will not exit'' at the <code>return ()</code>.
Instead, the program will continue to the <code>if</code> expression and check whether
<code>guess</code> is less than <code>num</code>. Of course it is
not, so the else branch is taken, and it will print "Too high!" and
then ask you to guess again. Things aren't any better with an incorrect guess:
it will try to evaluate the case expression and get either <code>LT</code> or
<code>GT</code> as the result of the <code>compare</code>. In either case,
it won't have a pattern that matches, and the program will fail immediately
with an exception (as usual, the incomplete <code>case</code> alone should be
enough to raise suspicion).
The problem here is that <code>return</code> is not at all equivalent to the
C (or Java etc.) statement with the same name. For our immediate purposes,
we can say that <code>return</code> is a ''function''.<ref>''Superfluous note'': somewhat
closer to a proper explanation, we might
say <code>return</code> is a function which takes a value and makes it into an
action which, when evaluated, gives the original value. A
<code>return "strawberry"</code> within one of the <code>do</code> blocks
we are dealing with would have type <code>IO String</code> - the same type as
<code>getLine</code>. Do not worry if that doesn't make sense for now; you will
understand what <code>return</code> really does when we ''actually'' start
discussing monads further ahead on the book.</ref>
The <code>return ()</code> in particular evaluates to an action which does nothing.
<code>return</code> ''does not affect the control flow at all''. In the correct guess
case, the case expression evaluates to <code>return ()</code>, an action of type
<code>IO ()</code>, and execution just follows along normally.
The bottom line is that while actions and <code>do</code> blocks resemble imperative
code, they must be dealt with on their own terms - Haskell terms.
{{Exercises|1=
# Redo the "Haskell greeting" exercise in [[../Simple input and output#Controlling actions|Simple input and output/Controlling actions]], this time using a <code>case</code> expression.
# What does the following program print out? And why?
<syntaxhighlight lang="haskell">
main =
do x <- getX
putStrLn x
getX =
do return "My Shangri-La"
return "beneath"
return "the summer moon"
return "I will"
return "return"
return "again"
</syntaxhighlight>
}}
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Elementary Haskell|noexercises=0}}
{{BookCat}}
3nxsx8lzz4um9f596o6jq80mqo35bsx
Haskell/Standalone programs
0
55891
4675958
4666185
2026-10-14T00:52:22Z
~2026-54868-50
3628373
4675958
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Intermediate Haskell|noexercises=1}}
Let's build a simple Haskell application, i.e. a piece of standalone software.
== The Main module ==
The basic requirement behind this is to have a module '''Main''' with an entry point called '''main''' and of type <code>IO ()</code>.
<syntaxhighlight lang="haskell">
-- thingamie.hs
module Main where
main = putStrLn "Bonjour, world!"
</syntaxhighlight>
We already know how to load this into GHCi, but here's how we compile it and then run it independently:
<pre>
$ ghc --make -o bonjourWorld thingamie.hs
$ ./bonjourWorld
Bonjour, world!
</pre>
Voilà! You now have a standalone application built in Haskell.
== Other modules ==
Most programs grow to be complicated enough to split across different files. Here is a toy example of an application which uses two modules.
<syntaxhighlight lang="haskell">
-- Hello.hs
module Hello where
hello = "Bonjour, world!"
</syntaxhighlight>
<syntaxhighlight lang="haskell">
-- thingamie.hs
module Main where
import Hello
main = putStrLn hello
</syntaxhighlight>
We can compile this fancy new program in the same way as before. The <code>--make</code> flag tells GHC to automatically detect dependencies in the files you are compiling. That is, since <code>thingamie.hs</code> imports a module <code>Hello</code>, GHC will search the Haskell files in the current directory for files that implement <code>Hello</code> and also compile them. If Hello depends on other modules, GHC will automatically detect those dependencies as well.
<pre>
$ ghc --make -o bonjourWorld thingamie.hs
$ ./bonjourWorld
Bonjour, world!
</pre>
You may have noticed that the file with the <code>Main</code> module, <code>thingamie.hs</code>, does not have a name matching the module name, which goes against what we said in the [[Haskell/Modules#Modules|Modules]] chapter. That is not a problem because the point of having matching module and file names is allowing GHC to find the files automatically. Since that process always begins from <code>Main</code>, whose file we specify in the command line when calling GHC, the file of the <code>Main</code> module need not follow the convention.
If you want to search in other places for source files (including a nested structure of files and directories), you can add the starting point for the dependency search with the <code>-i</code> flag. This flag takes multiple, colon-separated directory names as its argument.
As a contrived example, the following program has three files all stored in a <code>src/</code> directory. The directory structure looks like:
<pre>
HaskellProgram/
src/
Main.hs
GUI/
Interface.hs
Functions/
Mathematics.hs
</pre>
The Main module imports its dependencies by searching a path analogous to the module name — so that <code>import GUI.Interface</code> would search for <code>GUI/Interface</code> (with the appropriate file extension).
To compile this program from within the HaskellProgram directory, invoke GHC with:
<pre>
$ ghc --make -isrc -o sillyprog Main.hs
</pre>
{{Haskell/Navigation|chapter=Intermediate Haskell|noexercises=1}}
{{BookCat}}
fxyfe09mgsyfdqofizk5o7djviq30z0
Haskell/Modules
0
56392
4675957
4669136
2026-10-14T00:50:29Z
~2026-54868-50
3628373
4675957
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Intermediate Haskell|noexercises=1}}
Modules are the primary means of organizing Haskell code. We met them in passing when using <code>import</code> statements to put library functions into scope. Beyond allowing us to make better use of libraries, knowledge of modules will help us to shape our own programs and create standalone programs which can be executed independently of GHCi (incidentally, that is the topic of the very next chapter, [[../Standalone programs/]]).
== Modules ==
Haskell modules<ref>See the Haskell report for [http://www.haskell.org/onlinereport/modules.html more details on the module system].</ref> are a useful way to group a set of related functionalities into a single package and manage different functions that may have the same names. The module definition is the first thing that goes in your Haskell file.
A basic module definition looks like:
<syntaxhighlight lang="haskell">
module YourModule where
</syntaxhighlight>
Note that
# the name of the module begins with a capital letter;
# each file contains only one module.
The name of the file is the name of the module plus the <code>.hs</code> file extension. Any dots '<code>.</code>' in the module name are changed for directories.<ref>In Haskell98, the last standardised version of Haskell before Haskell 2010, the module system was fairly conservative, but recent common practice consists of employing a hierarchical module system, using periods to section off namespaces.</ref> So the module <code>YourModule</code> would be in the file <code>YourModule.hs</code> while a module <code>Foo.Bar</code> would be in the file <code>Foo/Bar.hs</code> or <code>Foo\Bar.hs</code>. Since the module name must begin with a capital letter, the file name must also start with a capital letter.
== Importing ==
Modules can themselves import functions from other modules. That is, in between the module declaration and the rest of your code, you may include some import declarations such as
<syntaxhighlight lang="haskell">
import Data.Char (toLower, toUpper) -- import only the functions toLower and toUpper from Data.Char
import Data.List -- import everything exported from Data.List
import MyModule -- import everything exported from MyModule
</syntaxhighlight>
Imported datatypes are specified by their name, followed by a list of imported constructors in parenthesis. For example:
<syntaxhighlight lang="haskell">
import Data.Tree (Tree(Node)) -- import only the Tree data type and its Node constructor from Data.Tree
</syntaxhighlight>
What if you import some modules that have overlapping definitions? Or if you import a module but want to overwrite a function yourself? There are three ways to handle these cases: Qualified imports, hiding definitions, and renaming imports.
=== Qualified imports ===
Say MyModule and MyOtherModule both have a definition for <code>remove_e</code>, which removes all instances of ''e'' from a string. However, MyModule only removes lower-case e's, and MyOtherModule removes both upper and lower case. In this case the following code is ambiguous:
<syntaxhighlight lang="haskell">
import MyModule
import MyOtherModule
-- someFunction puts a c in front of the text, and removes all e's from the rest
someFunction :: String -> String
someFunction text = 'c' : remove_e text
</syntaxhighlight>
It isn't clear which <code>remove_e</code> is meant! To avoid this, use the '''qualified''' keyword:
<syntaxhighlight lang="haskell">
import qualified MyModule
import qualified MyOtherModule
someFunction text = 'c' : MyModule.remove_e text -- Will work, removes lower case e's
someOtherFunction text = 'c' : MyOtherModule.remove_e text -- Will work, removes all e's
someIllegalFunction text = 'c' : remove_e text -- Won't work as there is no remove_e defined
</syntaxhighlight>
In the latter code snippet, no function named <code>remove_e</code> is available at all. When we do qualified imports, all the imported values include the module names as a prefix. Incidentally, you can also use the same prefixes even if you did a regular import (in our example, <code>MyModule.remove_e</code> works even if the "qualified" keyword isn't included).
{{body note|There is an ambiguity between a qualified name like <code>MyModule.remove_e</code> and the function composition operator <code>(.)</code>. Writing <code>reverse.MyModule.remove_e</code> is bound to confuse your Haskell compiler. One solution is stylistic: always use spaces for function composition, for example, <code>reverse . remove_e</code> or <code>Just . remove_e</code> or even <code>Just . MyModule.remove_e</code>}}
=== Hiding definitions ===
Now suppose we want to import both <code>MyModule</code> and <code>MyOtherModule</code>, but we know for sure we want to remove all e's, not just the lower cased ones. It will become really tedious to add <code>MyOtherModule</code> before every call to <code>remove_e</code>. Can't we just exclude the <code>remove_e</code> from <code>MyModule</code>?
<syntaxhighlight lang="haskell">
import MyModule hiding (remove_e)
import MyOtherModule
someFunction text = 'c' : remove_e text
</syntaxhighlight>
This works because of the word '''hiding''' on the import line. Whatever follows the "hiding" keyword will not be imported. Hide multiple items by listing them with parentheses and comma-separation:
<syntaxhighlight lang="haskell">
import MyModule hiding (remove_e, remove_f)
</syntaxhighlight>
=== Renaming imports ===
This is not really a technique to allow for overwriting, but it is often used along with the qualified flag. Imagine:
<syntaxhighlight lang="haskell">
import qualified MyModuleWithAVeryLongModuleName
someFunction text = 'c' : MyModuleWithAVeryLongModuleName.remove_e text
</syntaxhighlight>
Especially when using qualified, this gets irritating. We can improve things by using the '''as''' keyword:
<syntaxhighlight lang="haskell">
import qualified MyModuleWithAVeryLongModuleName as Shorty
someFunction text = 'c' : Shorty.remove_e text
</syntaxhighlight>
This allows us to use <code>Shorty</code> instead of <code>MyModuleWithAVeryLongModuleName</code> as prefix for the imported functions. This renaming works with both qualified and regular importing.
As long as there are no conflicting items, we can import multiple modules and rename them the same:
<syntaxhighlight lang="haskell">
import MyModule as My
import MyCompletelyDifferentModule as My
</syntaxhighlight>
In this case, both the functions in <code>MyModule</code> and the functions in <code>MyCompletelyDifferentModule</code> can be prefixed with My.
=== Combining renaming with limited import ===
Sometimes it is convenient to use the import directive twice for the same module. A typical scenario is as follows:
<syntaxhighlight lang="haskell">
import qualified Data.Set as Set
import Data.Set (Set, empty, insert)
</syntaxhighlight>
This give access to all of the Data.Set module via the alias "Set", and also lets you access a few selected functions (empty, insert, and the constructor) without using the "Set" prefix.
== Exporting ==
In the examples at the start of this article, the words "import ''everything exported'' from MyModule" were used.<ref>A module may export functions that it imports. Mutually recursive modules are possible but need [https://wiki.haskell.org/Mutually_recursive_modules some special treatment].</ref> This raises a question. How can we decide which functions are exported and which stay "internal"? Here's how:
<syntaxhighlight lang="haskell">
module MyModule (remove_e, add_two) where
add_one blah = blah + 1
remove_e text = filter (/= 'e') text
add_two blah = add_one . add_one $ blah
</syntaxhighlight>
In this case, only <code>remove_e</code> and <code>add_two</code> are exported. While <code>add_two</code> is allowed to make use of <code>add_one</code>, functions in modules that import <code>MyModule</code> cannot use <code>add_one</code> directly, as it isn't exported.
Datatype export specifications are written similarly to import. You name the type, and follow with the list of constructors in parenthesis:
<syntaxhighlight lang="haskell">
module MyModule2 (Tree(Branch, Leaf)) where
data Tree a = Branch {left, right :: Tree a}
| Leaf a
</syntaxhighlight>
In this case, the module declaration could be rewritten "MyModule2 (Tree(..))", declaring that all constructors are exported.
Maintaining an export list is good practice not only because it reduces namespace pollution but also because it enables certain [http://www.haskell.org/haskellwiki/Performance/GHC#Inlining compile-time optimizations] which are unavailable otherwise.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Intermediate Haskell|noexercises=1}}
{{BookCat}}
rzf3hopnmz2begxcyol2ujvtqjvibbf
Haskell/Understanding monads
0
56771
4676016
4446473
2026-10-14T11:08:47Z
Luciérnaga de conocimiento
3401314
4676016
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Monads|noexercises=1}}
There is a certain mystique about monads, and even about the word "monad" itself. While one of our goals of this set of chapters is removing the shroud of mystery that is often wrapped around them, it is not difficult to understand how it comes about. Monads are very useful in Haskell, but the concept is often difficult to grasp at first. Since monads have so many applications, people often explain them from a particular point of view, which can derail your efforts towards understanding them in their full glory.
Historically, monads were introduced into Haskell to perform input and output – that is, I/O operations of the sort we dealt with in the [[Haskell/Simple input and output|Simple input and output]] chapter and the [[Haskell/Applicative prologue|prologue to this unit]]. A predetermined execution order is crucial for things like reading and writing files, and monadic operations lend themselves naturally to sequencing. However, monads are by no means limited to input and output. They can be used to provide a whole range of features, such as exceptions, state, non-determinism, continuations, coroutines, and more. In fact, thanks to the versatility of monads, none of these constructs needed to be built into Haskell as a language; rather, they are defined by the standard libraries.
In the [[Haskell/Applicative prologue|Prologue]] chapter, we began with an example and used it to steadily introduce several new ideas. Here, we will do it the other way around, starting with a definition of monad and, from that, building connections with what we already know.
== Definition ==
A ''monad'' is defined by three things:
*a [[Haskell/More on datatypes#Parameterized Types | type constructor]] <code>m</code>;
*a function <code>return</code>;<ref>This <code>return</code> function has nothing to do with the <code>return</code> keyword found in imperative languages like C or Java; don't conflate these two.</ref>
*an operator <code>(>>=)</code> which is pronounced "bind".
The function and operator are methods of the <code>Monad</code> type class and have types
<syntaxhighlight lang="haskell">
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
</syntaxhighlight>
and are required to obey [[#Monad Laws|three laws]] that will be explained later on.
For a concrete example, take the <code>Maybe</code> monad. The type constructor is <code>m = Maybe</code>, while <code>return</code> and <code>(>>=)</code> are defined like this:
<syntaxhighlight lang="haskell">
return :: a -> Maybe a
return x = Just x
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
m >>= g = case m of
Nothing -> Nothing
Just x -> g x
</syntaxhighlight>
<code>Maybe</code> is the monad, and <code>return</code> brings a value into it by wrapping it with <code>Just</code>. As for <code>(>>=)</code>, it takes a <code>m :: Maybe a</code> value and a <code>g :: a -> Maybe b</code> function. If <code>m</code> is <code>Nothing</code>, there is nothing to do and the result is <code>Nothing</code>. Otherwise, in the <code>Just x</code> case, <code>g</code> is applied to <code>x</code>, the underlying value wrapped in <code>Just</code>, to give a <code>Maybe b</code> result. Note that this result may or may not be <code>Nothing</code>, depending on what <code>g</code> does to <code>x</code>. To sum it all up, if there is an ''underlying value'' of type <code>a</code> in <code>m</code>, we apply <code>g</code> to it, which brings the underlying value back into the <code>Maybe</code> monad.
The key first step to understand how <code>return</code> and <code>(>>=)</code> work is tracking which values and arguments are monadic and which ones aren't. As in so many other cases, type signatures are our guide to the process.
=== Motivation: Maybe ===
To see the usefulness of <code>(>>=)</code> and the <code>Maybe</code> monad, consider the following example: Imagine a family database that provides two functions:
<syntaxhighlight lang="haskell">
father :: Person -> Maybe Person
mother :: Person -> Maybe Person
</syntaxhighlight>
These look up the name of someone's father or mother. In case our database is missing some relevant information, <code>Maybe</code> allows us to return a <code>Nothing</code> value to indicate that the lookup failed, rather than crashing the program.
Let's combine our functions to query various grandparents. For instance, the following function looks up the maternal grandfather (the father of one's mother):
<syntaxhighlight lang="haskell">
maternalGrandfather :: Person -> Maybe Person
maternalGrandfather p =
case mother p of
Nothing -> Nothing
Just mom -> father mom
</syntaxhighlight>
Or consider a function that checks whether both grandfathers are in the database:
<syntaxhighlight lang="haskell">
bothGrandfathers :: Person -> Maybe (Person, Person)
bothGrandfathers p =
case father p of
Nothing -> Nothing
Just dad ->
case father dad of
Nothing -> Nothing
Just gf1 -> -- found first grandfather
case mother p of
Nothing -> Nothing
Just mom ->
case father mom of
Nothing -> Nothing
Just gf2 -> -- found second grandfather
Just (gf1, gf2)
</syntaxhighlight>
What a mouthful! Every single query might fail by returning <code>Nothing</code> and the whole function must fail with <code>Nothing</code> if that happens.
Clearly there has to be a better way to write that instead of repeating the case of <code>Nothing</code> again and again! Indeed, that's what the <code>Maybe</code> monad is set out to do. For instance, the function retrieving the maternal grandfather has exactly the same structure as the <code>(>>=)</code> operator, so we can rewrite it as:
<syntaxhighlight lang="haskell">
maternalGrandfather p = mother p >>= father
</syntaxhighlight>
With the help of lambda expressions and <code>return</code>, we can rewrite the two grandfathers function as well:
<syntaxhighlight lang="haskell">
bothGrandfathers p =
father p >>=
(\dad -> father dad >>=
(\gf1 -> mother p >>= -- gf1 is only used in the final return
(\mom -> father mom >>=
(\gf2 -> return (gf1,gf2) ))))
</syntaxhighlight>
While these nested lambda expressions may look confusing to you, the thing to take away here is that <code>(>>=)</code> releases us from listing all the <code>Nothing</code>s, shifting the focus back to the interesting part of the code.
To be a little more precise: The result of <code>father p</code> is a monadic value (in this case, either <code>Just dad</code> or <code>Nothing</code>, depending on whether <code>p</code>'s father is in the database). As the <code>father</code> function takes a regular (non-monadic) value, the <code>(>>=)</code> feeds <code>p</code>'s <code>dad</code> to it ''as a non-monadic'' value. The result of <code>father dad</code> is then monadic again, and the process continues.
So, <code>(>>=)</code> helps us pass non-monadic values to functions without actually leaving a monad. In the case of the <code>Maybe</code> monad, the monadic aspect is the uncertainty about whether a value will be found.
=== Type class ===
In Haskell, the <code>Monad</code> type class is used to implement monads. It is provided by the {{Haskell/Lib|v=latest|Control|Monad}} module and included in the Prelude. The class has the following methods:
<syntaxhighlight lang="haskell">
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
fail :: String -> m a
</syntaxhighlight>
Aside from return and bind, there are two additional methods, <code>(>>)</code> and <code>fail</code>. Both of them have default implementations, and so you don't need to provide them when writing an instance.
The operator <code>(>>)</code>, spelled "then", is a mere convenience and has the default implementation
<syntaxhighlight lang="haskell">
m >> n = m >>= \_ -> n
</syntaxhighlight>
<code>(>>)</code> sequences two monadic actions when the second action does not involve the result of the first, which is a common scenario for monads such as <code>IO</code>.
<syntaxhighlight lang="haskell">
printSomethingTwice :: String -> IO ()
printSomethingTwice str = putStrLn str >> putStrLn str
</syntaxhighlight>
The function <code>fail</code> handles pattern match failures in [[Haskell/do notation|<code>do</code> notation]]. It's an unfortunate technical necessity and doesn't really have anything to do with monads. You are advised not to call <code>fail</code> directly in your code.
=== <code>Monad</code> and <code>Applicative</code> ===
An important thing to note is that <code>Applicative</code> is a superclass of <code>Monad</code>.<ref>This important superclass relationship was, thanks to historic accidents, only implemented quite recently (early 2015) in GHC (version 7.10). If you are using a GHC version older than that, this class constraint will not exist, and so some of the practical considerations we will make next will not apply.</ref> That has a few consequences worth highlighting. First of all, every <code>Monad</code> is also a <code>Functor</code> and an <code>Applicative</code>, and so <code>fmap</code>, <code>pure</code>, <code>(<*>)</code> can all be used with monads. Secondly, actually writing a <code>Monad</code> instance also requires providing <code>Functor</code> and <code>Applicative</code> instances. We will discuss ways of doing that later in this chapter. Thirdly, if you have worked through the [[Haskell/Applicative prologue|Prologue]], the types and roles of <code>return</code> and <code>(>>)</code> should look familiar...
<syntaxhighlight lang="haskell">
(*>) :: Applicative f => f a -> f b -> f b
(>>) :: Monad m => m a -> m b -> m b
pure :: Applicative f => a -> f a
return :: Monad m => a -> m a
</syntaxhighlight>
The only difference between the types of <code>(*>)</code> and <code>(>>)</code> is that the constraint changes from <code>Applicative</code> to <code>Monad</code>. In fact, that is the only difference between the methods: if you are dealing with a <code>Monad</code> you can always replace <code>(*>)</code> and <code>(>>)</code>, and vice-versa. The same goes for <code>pure</code>/<code>return</code> – in fact, it is not even necessary to implement <code>return</code> if there is an independent definition of <code>pure</code> in the <code>Applicative</code> instance, as <code>return = pure</code> is provided as a default definition of <code>return</code>.
== Notions of Computation ==
We have seen how <code>(>>=)</code> and <code>return</code> are very handy for removing boilerplate code that crops up when using <code>Maybe</code>. That, however, is not enough to justify why monads matter so much. Our next step towards that will be rewriting the two-grandfathers function in a quite different-looking style: using <code>do</code> notation with [[Haskell/Indentation#Explicit characters in place of indentation|explicit braces and semicolons]]. Depending on your experience with other programming languages, you may find this very suggestive:
<syntaxhighlight lang="haskell">
bothGrandfathers p = do {
dad <- father p;
gf1 <- father dad;
mom <- mother p;
gf2 <- father mom;
return (gf1, gf2);
}
</syntaxhighlight>
If this looks like a code snippet in an imperative programming language to you, that's because it ''is''. In particular, this imperative language supports ''exceptions'' : <code>father</code> and <code>mother</code> are functions that might fail to produce results, raising an exception instead; when that happens, the whole <code>do</code>-block will ''fail'', i.e. terminate with an exception (meaning, evaluate to <code>Nothing</code>, here).
In other words, the expression <code>father p</code>, which has type <code>Maybe Person</code>, is interpreted as a statement in an imperative ''language'' that returns a <code>Person</code> as the result, or fails.
This is true for all monads: a value of type <code>M a</code> is interpreted as a ''statement'' in an imperative language <code>M</code> that returns a value of type <code>a</code> as its result; the semantics of this language are determined by the monad <code>M</code>.<ref>By "semantics" we mean ''what'' the language allows you to say. In the case of <code>Maybe</code>, the semantics allow us to express failure, as statements may fail to produce a result, leading to the statements that follow it being skipped.</ref>
Under this interpretation, the ''then'' operator <code>(>>)</code> is simply an implementation of the semicolon, and <code>(>>=)</code> of the semicolon and assignment (binding) of the result of a previous computational step. Just like a <code>let</code> expression can be written as a function application,
let x = foo in (x + 3) corresponds to foo & (\x -> id (x + 3)) -- v & f = f v
an assignment and semicolon can be written with the bind operator:
x <- foo; return (x + 3) corresponds to foo >>= (\x -> return (x + 3))
In case of functions, <code>&</code> and <code>id</code> are trivial; in case of a monad, <code>>>=</code> and <code>return</code> are substantial.
The <code>&</code> operator combines two pure ''calculations'', <code>foo</code> and <code>id (x + 3)</code>, while creating a new binding for the variable <code>x</code> to hold <code>foo</code>'s ''value'', making <code>x</code> available to the second calculational step, <code>id (x + 3)</code>.
The bind operator <code>>>=</code> combines two ''computational'' steps, <code>foo</code> and <code>return (x + 3)</code>, in a manner particular to the monad <code>M</code>, while creating a new binding for the variable <code>x</code> to hold <code>foo</code>'s ''result'', making <code>x</code> available to the next computational step, <code>return (x + 3)</code>. In the particular case of <code>Maybe</code>, if <code>foo</code> will fail to produce a result, the second step is skipped and the whole combined computation will fail right away as well.
The function <code>return</code> lifts a plain value <code>a</code> to <code>M a</code>, a statement in the imperative language <code>M</code>, which statement, when executed / run, will result in the value <code>a</code> without any additional effects particular to <code>M</code>. This is ensured by Monad Laws, <code>foo >>= return === foo</code> and <code>return x >>= k === k x</code>; see below.
{{body note|The fact that <code>(>>{{=}})</code>, and therefore <code>Monad</code>, lies behind the left arrows in <code>do</code>-blocks explains why we were not able to explain them in the [[Haskell/Applicative prologue#The end of the beginning|Prologue]], when we only knew about <code>Functor</code> and <code>Applicative</code>. <code>Applicative</code> would be enough to provide some, but not all, of the functionality of a <code>do</code>-block.}}
Different semantics of the imperative language correspond to different monads. The following table shows the classic selection that every Haskell programmer should know. If the idea behind monads is still unclear to you, studying each of the examples in the following chapters will not only give you a well-rounded toolbox but also help you understand the common abstraction behind them.
{|class="wikitable" style="margin:auto"
|-
!Monad
!Imperative Semantics
!Wikibook chapter
|-
| <code>Maybe</code> || Exception (anonymous) || [[Haskell/Understanding monads/Maybe]]
|-
| <code>Error</code> || Exception (with error description) || [[Haskell/Understanding monads/Error]]
|-
| <code>IO</code> || Input/Output || [[Haskell/Understanding monads/IO]]
|-
| <code>[]</code> (lists) || Nondeterminism || [[Haskell/Understanding monads/List]]
|-
| <code>Reader</code> || Environment || [[Haskell/Understanding monads/Reader]]
|-
| <code>Writer</code> || Logger || [[Haskell/Understanding monads/Writer]]
|-
| <code>State</code> || Global state || [[Haskell/Understanding monads/State]]
|}
Furthermore, these different semantics need not occur in isolation. As we will see in a few chapters, it is possible to mix and match them by using [[Haskell/Monad transformers|monad transformers]] to combine the semantics of multiple monads in a single monad.
== Monad Laws ==
In Haskell, every instance of the <code>Monad</code> type class (and thus all implementations of bind <code>(>>=)</code> and <code>return</code>) must obey the following three laws:
<syntaxhighlight lang="haskell">
m >>= return = m -- right unit
return x >>= f = f x -- left unit
(m >>= f) >>= g = m >>= (\x -> f x >>= g) -- associativity
</syntaxhighlight>
=== Return as neutral element ===
The behavior of <code>return</code> is specified by the left and right unit laws. They state that <code>return</code> doesn't perform any computation, it just collects values. For instance,
<syntaxhighlight lang="haskell">
maternalGrandfather p = do
mom <- mother p
gf <- father mom
return gf
</syntaxhighlight>
is exactly the same as
<syntaxhighlight lang="haskell">
maternalGrandfather p = do
mom <- mother p
father mom
</syntaxhighlight>
by virtue of the right unit law.
=== Associativity of bind ===
The law of associativity makes sure that (like the semicolon) the bind operator <code>(>>=)</code> only cares about the order of computations, not about their nesting; e.g. we could have written <code>bothGrandfathers</code> like this (compare with our earliest version without <code>do</code>):
<syntaxhighlight lang="haskell">
bothGrandfathers p =
(father p >>= father) >>=
(\gf1 -> (mother p >>= father) >>=
(\gf2 -> return (gf1,gf2) ))
</syntaxhighlight>
The associativity of the ''then'' operator <code>(>>)</code> is a special case:
<syntaxhighlight lang="haskell">
(m >> n) >> o = m >> (n >> o)
</syntaxhighlight>
==== Monadic composition ====
It is easier to picture the associativity of bind by recasting the law as
<syntaxhighlight lang="haskell">
(f >=> g) >=> h = f >=> (g >=> h)
</syntaxhighlight>
where <code>(>=>)</code> is the ''monad composition operator'', a close analogue of the function composition operator <code>(.)</code>, only with flipped arguments. It is defined as:
<syntaxhighlight lang="haskell">
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
f >=> g = \x -> f x >>= g
</syntaxhighlight>
There is also <code>(<=<)</code>, which is flipped version of <code>(>=>)</code>. When using it, the order of composition matches that of <code>(.)</code>, so that in <code>(f <=< g)</code> <code>g</code> comes first.<ref>Of course, the functions in regular function composition are non-monadic functions whereas monadic composition takes only monadic functions.</ref>
== Monads and Category Theory ==
Monads originally come from a branch of mathematics called Category Theory. Fortunately, it is entirely unnecessary to understand category theory in order to understand and use monads in Haskell. The definition of monads in Category Theory actually uses a slightly different presentation. Translated into Haskell, this presentation gives an alternative yet equivalent definition of a monad, which can give us some additional insight on the <code>Monad</code> class.<ref>Deep into the Advanced Track, we will cover the theoretical side of the story in the [[Haskell/Category theory#Monads|chapter on Category Theory]].</ref>
So far, we have defined monads in terms of <code>(>>=)</code> and <code>return</code>. The alternative definition, instead, treats monads as functors with two additional combinators:
<syntaxhighlight lang="haskell">
fmap :: (a -> b) -> M a -> M b -- functor
return :: a -> M a
join :: M (M a) -> M a
</syntaxhighlight>
For the purposes of this discussion, we will use the functors-as-containers metaphor discussed in the [[Haskell/The Functor class|chapter on the functor class]]. According to it, a functor <code>M</code> can be thought of as container, so that <code>M a</code> "contains" values of type <code>a</code>, with a corresponding mapping function, i.e. <code>fmap</code>, that allows functions to be applied to values inside it.
Under this interpretation, the functions behave as follows:
* <code>fmap</code> applies a given function to every element in a container
* <code>return</code> packages an element into a container,
* <code>join</code> takes a container of containers and flattens it into a single container.
With these functions, the bind combinator can be defined as follows:
<syntaxhighlight lang="haskell">
m >>= g = join (fmap g m)
</syntaxhighlight>
Likewise, we could give a definition of <code>fmap</code> and <code>join</code> in terms of <code>(>>=)</code> and <code>return</code>:
<syntaxhighlight lang="haskell">
fmap f x = x >>= (return . f)
join x = x >>= id
</syntaxhighlight>
== <code>liftM</code> and Friends == <!-- TODO: There must be a better title for this section. -->
Earlier, we pointed out that every <code>Monad</code> is an <code>Applicative</code>, and therefore also a <code>Functor</code>. One of the consequences of that was <code>return</code> and <code>(>>)</code> being monad-only versions of <code>pure</code> and <code>(*>)</code> respectively. It doesn't stop there, though. For one, <code>Control.Monad</code> defines <code>liftM</code>, a function with a strangely familiar type signature...
<syntaxhighlight lang="haskell">
liftM :: (Monad m) => (a -> b) -> m a -> m b
</syntaxhighlight>
As you might suspect, <code>liftM</code> is merely <code>fmap</code> implemented with <code>(>>=)</code> and <code>return</code>, just as we have done in the previous section. <code>liftM</code> and <code>fmap</code> are therefore interchangeable.
Another <code>Control.Monad</code> function with an uncanny type is <code>ap</code>:
<syntaxhighlight lang="haskell">
ap :: Monad m => m (a -> b) -> m a -> m b
</syntaxhighlight>
Analogously to the other cases, <code>ap</code> is a monad-only version of <code>(<*>)</code>.
There are quite a few more examples of <code>Applicative</code> functions that have versions ''specialised'' to <code>Monad</code> in <code>Control.Monad</code> and other base library modules. Their existence is primarily due to historical reasons: several years went by between the introductions of <code>Monad</code> and <code>Applicative</code> in Haskell, and it took an even longer time for <code>Applicative</code> to become a superclass of <code>Monad</code>, thus making usage of the specialised variants optional. While in principle there is little need for using the monad-only versions nowadays, in practice you will see <code>return</code> and <code>(>>)</code> all the time in other people's code – at this point, their usage is well established thanks to more than two decades of Haskell praxis without <code>Applicative</code> being a superclass of <code>Monad</code>.
{{body note|1=
Given that <code>Applicative</code> is a superclass of <code>Monad</code>, the most obvious way of implementing <code>Monad</code> begins by writing the <code>Functor</code> instance and then moving down the class hierarchy:
<syntaxhighlight lang="haskell">
instance Functor Foo where
fmap = -- etc.
instance Applicative Foo where
pure = -- etc.
(<*>) = -- etc.
instance Monad Foo where
(>>=) = -- etc.
</syntaxhighlight>
While following the next few chapters, you will likely want to write instances of <code>Monad</code> and try them out, be it to run the examples in the book or to do other experiments you might think of. However, writing the instances in the manner shown above requires implementing <code>pure</code> and <code>(<*>)</code>, which is not a comfortable task at this point of the book as we haven't covered the <code>Applicative</code> laws yet (we will only do so at the [[Haskell/Applicative functors|applicative functors chapter]]). Fortunately, there is a workaround: implementing just <code>(>>=)</code> and <code>return</code>, thus providing a self-sufficient <code>Monad</code> instance, and then using <code>liftM</code>, <code>ap</code> and <code>return</code> to fill in the other instances:
<syntaxhighlight lang="haskell">
instance Monad Foo where
return = -- etc.
(>>=) = -- etc.
instance Applicative Foo where
pure = return
(<*>) = ap
instance Functor Foo where
fmap = liftM
</syntaxhighlight>
The examples and exercises in this initial series of chapters about monads will not demand writing <code>Applicative</code> instances, and so you can use this workaround until we discuss <code>Applicative</code> in detail.
}}
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Monads}}
{{BookCat}}
he2sixvykwyd50aeni24bi9qfxtbxiz
Haskell/Monad transformers
0
58776
4676023
4637811
2026-10-14T11:15:53Z
Luciérnaga de conocimiento
3401314
4676023
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Monads}}
We have seen how monads can help handling <code>IO</code> actions, <code>Maybe</code>, lists, and state.
With monads providing a common way to use such useful general-purpose tools, a natural thing we might want to do is using the capabilities of ''several'' monads at once. For instance, a function could use both I/O and <code>Maybe</code> exception handling. While a type like <code>IO (Maybe a)</code> would work just fine, it would force us to do pattern matching within <code>IO</code> do-blocks to extract values, something that the <code>Maybe</code> monad was meant to spare us from.
Enter '''monad transformers''': special types that allow us to roll two monads into a single one that shares the behavior of both.
== Passphrase validation ==
Consider a real-life problem for IT staff worldwide: getting users to create strong passphrases.
One approach: force the user to enter a minimum length with various irritating requirements (such as at least one capital letter, one number, one non-alphanumeric character, etc.)
Here's a Haskell function to acquire a passphrase from a user:
<syntaxhighlight lang="haskell">
getPassphrase :: IO (Maybe String)
getPassphrase = do s <- getLine
if isValid s then return $ Just s
else return Nothing
-- The validation test could be anything we want it to be.
isValid :: String -> Bool
isValid s = length s >= 8
&& any isAlpha s
&& any isNumber s
&& any isPunctuation s
</syntaxhighlight>
First and foremost, <code>getPassphrase</code> is an <code>IO</code> action, as it needs to get input from the user. We also use <code>Maybe</code>, as we intend to return <code>Nothing</code> in case the password does not pass the <code>isValid</code>. Note, however, that we aren't actually using <code>Maybe</code> as a monad here: the <code>do</code> block is in the <code>IO</code> monad, and we just happen to <code>return</code> a <code>Maybe</code> value inside it.
Monad transformers not only make it easier to write <code>getPassphrase</code> but also simplify all the code instances. Our passphrase acquisition program could continue like this:
<syntaxhighlight lang="haskell">
askPassphrase :: IO ()
askPassphrase = do putStrLn "Insert your new passphrase:"
maybe_value <- getPassphrase
case maybe_value of
Just value -> do putStrLn "Storing in database..." -- do stuff
Nothing -> putStrLn "Passphrase invalid."
</syntaxhighlight>
The code uses one line to generate the <code>maybe_value</code> variable followed by further validation of the passphrase.
With monad transformers, we will be able to extract the passphrase in one go — without any pattern matching (or equivalent bureaucracy like <code>isJust</code>). The gains for our simple example might seem small but will scale up for more complex situations.
== A simple monad transformer: <code>MaybeT</code> ==
To simplify <code>getPassphrase</code> and the code that uses it, we will define a ''monad transformer'' that gives the <code>IO</code> monad some characteristics of the <code>Maybe</code> monad; we will call it <code>MaybeT</code>. That follows a convention where monad transformers have a "<code>T</code>" appended to the name of the monad whose characteristics they provide.
<code>MaybeT</code> is a wrapper around <code>m (Maybe a)</code>, where <code>m</code> can be any monad (<code>IO</code> in our example):
<syntaxhighlight lang="haskell">
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
</syntaxhighlight>
This data type definition specifies a <code>MaybeT</code> type constructor, parameterized over <code>m</code>, with a data constructor, also called <code>MaybeT</code>, and a convenient accessor function <code>runMaybeT</code>, with which we can access the underlying representation.
The whole point of monad transformers is that ''they transform monads into monads''; and so we need to make <code>MaybeT m</code> an instance of the <code>Monad</code> class:
<syntaxhighlight lang="haskell">
instance Monad m => Monad (MaybeT m) where
return = MaybeT . return . Just
-- The signature of (>>=), specialized to MaybeT m:
-- (>>=) :: MaybeT m a -> (a -> MaybeT m b) -> MaybeT m b
x >>= f = MaybeT $ do maybe_value <- runMaybeT x
case maybe_value of
Nothing -> return Nothing
Just value -> runMaybeT $ f value
</syntaxhighlight>
<!-- there had been here a horribly written run-on sentence trying to explain the code above, but I couldn't make parse it nor figure out how to write a better replacement. Better to just let the code stand on its own. If someone else can write a new explanation, maybe that will be good. -->
It would also have been possible (though arguably less readable) to write the return function as: <code>return = MaybeT . return . return</code>.
Starting from the first line of the <code>do</code> block:
* First, the <code>runMaybeT</code> accessor unwraps <code>x</code> into an <code>m (Maybe a)</code> computation. That shows us that the whole <code>do</code> block is in <code>m</code>.
* Still in the first line, <code><-</code> extracts a <code>Maybe a</code> value from the unwrapped computation.
* The <code>case</code> statement tests <code>maybe_value</code>:
** With <code>Nothing</code>, we return <code>Nothing</code> into <code>m</code>;
** With <code>Just</code>, we apply <code>f</code> to the <code>value</code> from the <code>Just</code>. Since <code>f</code> has <code>MaybeT m b</code> as result type, we need an extra <code>runMaybeT</code> to put the result back into the <code>m</code> monad.
* Finally, the <code>do</code> block as a whole has <code>m (Maybe b)</code> type; so it is wrapped with the <code>MaybeT</code> constructor.
It may look a bit complicated, but aside from the copious amounts of wrapping and unwrapping, the implementation of <code>MaybeT</code>'s bind works the same way as the implementation of <code>Maybe</code>'s familiar bind operator:
<syntaxhighlight lang="haskell">
-- (>>=) for the Maybe monad
maybe_value >>= f = case maybe_value of
Nothing -> Nothing
Just value -> f value
</syntaxhighlight>
Why use the <code>MaybeT</code> constructor before the <code>do</code> block while we have the accessor <code>runMaybeT</code> within <code>do</code>? Well, the <code>do</code> block must be in the <code>m</code> monad, not in <code>MaybeT m</code> (which lacks a defined bind operator at this point).
As usual, we also have to provide instances for the superclasses of <code>Monad</code>, <code>Applicative</code> and <code>Functor</code>:
<syntaxhighlight lang="haskell">
instance Monad m => Applicative (MaybeT m) where
pure = return
(<*>) = ap
instance Monad m => Functor (MaybeT m) where
fmap = liftM
</syntaxhighlight>
In addition, it is convenient to make <code>MaybeT m</code> an instance of a few other classes:
<syntaxhighlight lang="haskell">
instance Monad m => Alternative (MaybeT m) where
empty = MaybeT $ return Nothing
x <|> y = MaybeT $ do maybe_value <- runMaybeT x
case maybe_value of
Nothing -> runMaybeT y
Just _ -> return maybe_value
instance Monad m => MonadPlus (MaybeT m) where
mzero = empty
mplus = (<|>)
instance MonadTrans MaybeT where
lift = MaybeT . (liftM Just)
</syntaxhighlight>
<code>MonadTrans</code> implements the <code>lift</code> function, so we can take functions from the <code>m</code> monad and bring them into the <code>MaybeT m</code> monad in order to use them in <code>do</code> blocks. As for <code>Alternative</code> and <code>MonadPlus</code>, since <code>Maybe</code> is an instance of those classes it makes sense to make the <code>MaybeT m</code> an instance too.
=== Passphrase validation, simplified ===
The above passphrase validation example can now be simplified using the <code>MaybeT</code> monad transformer as follows:
<syntaxhighlight lang="haskell">
getPassphrase :: MaybeT IO String
getPassphrase = do s <- lift getLine
guard (isValid s) -- Alternative provides guard.
return s
askPassphrase :: MaybeT IO ()
askPassphrase = do lift $ putStrLn "Insert your new passphrase:"
value <- getPassphrase
lift $ putStrLn "Storing in database..."
</syntaxhighlight>
The code is now simpler, especially in the user function <code>askPassphrase</code>. Most importantly, we do not have to manually check whether the result is <code>Nothing</code> or <code>Just</code>: the bind operator takes care of that for us.
Note how we use <code>lift</code> to bring the functions <code>getLine</code> and <code>putStrLn</code> into the <code>MaybeT IO</code> monad. Also, since <code>MaybeT IO</code> is an instance of <code>Alternative</code>, checking for passphrase validity can be taken care of by a <code>guard</code> statement, which will return <code>empty</code> (i.e. <code>IO Nothing</code>) in case of a bad passphrase.
Incidentally, with the help of <code>MonadPlus</code> it also becomes very easy to ask the user ''ad infinitum'' for a valid passphrase:
<syntaxhighlight lang="haskell">
askPassphrase :: MaybeT IO ()
askPassphrase = do lift $ putStrLn "Insert your new passphrase:"
value <- msum $ repeat getPassphrase
lift $ putStrLn "Storing in database..."
</syntaxhighlight>
Running your new version of askPassphrase on ghci is easy:
<syntaxhighlight lang="haskell">
runMaybeT askPassphrase
</syntaxhighlight>
== A plethora of transformers ==
The <code>transformers</code> package provides modules with transformers for many common monads (<code>MaybeT</code>, for instance, can be found in {{Haskell/Lib|p=transformers|v=latest|Control|Monad|Trans|Maybe}}). These are defined consistently with their non-transformer versions; that is, the implementation is basically the same except with the extra wrapping and unwrapping needed to thread the other monad. From this point on, we will use '''precursor monad''' to refer to the non-transformer monad (e.g. Maybe in MaybeT) on which a transformer is based and '''base monad''' to refer to the other monad (e.g. IO in MaybeT IO) on which the transformer is applied.
To pick an arbitrary example, <code>ReaderT Env IO String</code> is a computation which involves reading values from some environment of type <code>Env</code> (the semantics of <code>Reader</code>, the precursor monad) and performing some <code>IO</code> in order to give a value of type <code>String</code>. Since the bind operator and <code>return</code> for the transformer mirror the semantics of the precursor monad, a <code>do</code> block of type <code>ReaderT Env IO String</code> will, from the outside, look a lot like a <code>do</code> block of the <code>Reader</code> monad, except that <code>IO</code> actions become trivial to embed by using <code>lift</code>.
=== Type juggling ===
We have seen that the type constructor for <code>MaybeT</code> is a wrapper for a <code>Maybe</code> value in the base monad. So, the corresponding accessor <code>runMaybeT</code> gives us a value of type <code>m (Maybe a)</code> - i.e. a value of the precursor monad returned in the base monad. Similarly, for the <code>ListT</code> and <code>ExceptT</code> transformers, which are built around lists and <code>Either</code> respectively:
<syntaxhighlight lang = "haskell">
runListT :: ListT m a -> m [a]
</syntaxhighlight>
and
<syntaxhighlight lang = "haskell">
runExceptT :: ExceptT e m a -> m (Either e a)
</syntaxhighlight>
Not all transformers are related to their precursor monads in this way, however. Unlike the precursor monads in the two examples above, the <code>Writer</code>, <code>Reader</code>, <code>State</code>, and <code>Cont</code> monads have neither multiple constructors nor constructors with multiple arguments. For that reason, they have <code>run...</code> functions which act as simple unwrappers, analogous to the <code>run...T</code> of the transformer versions. The table below shows the result types of the <code>run...</code> and <code>run...T</code> functions in each case, which may be thought of as the types wrapped by the base and transformed monads respectively.<ref>The wrapping interpretation is only literally true for versions of the <code>mtl</code> package older than 2.0.0.0 .</ref>
{|align="center" border="1" cellpadding="3"
|- bgcolor="#cc9999" rowspan="2"
!|Precursor
!|Transformer
!|Original Type<br/><small>("wrapped" by precursor)</small>
!|Combined Type<br/><small>("wrapped" by transformer)</small>
|-
||Writer ||WriterT || <code>(a, w)</code> || <code>m (a, w)</code>
|-
||Reader || ReaderT || <code>r -> a</code> ||<code>r -> m a</code>
|-
||State || StateT || <code>s -> (a, s)</code> || <code>s -> m (a, s)</code>
|-
||Cont || ContT ||<code>(a -> r) -> r</code> ||<code>(a -> m r) -> m r</code>
|}
Notice that the precursor monad type constructor is absent in the combined types. Without interesting data constructors (of the sort that <code>Maybe</code> and lists have), there is no reason to retain the precursor monad type after unwrapping the transformed monad. It is also worth noting that in the latter three cases we have function types being wrapped. <code>StateT</code>, for instance, turns state-transforming functions of the form <code>s -> (a, s)</code> into state-transforming functions of the form <code>s -> m (a, s)</code>; only the result type of the wrapped function goes into the base monad. <code>ReaderT</code> is analogous.<code>ContT</code> is different because of the semantics of <code>Cont</code> (the ''continuation'' monad): the result types of both the wrapped function and its function argument must be the same, and so the transformer puts both into the base monad. In general, there is no magic formula to create a transformer version of a monad; the form of each transformer depends on what makes sense in the context of its non-transformer type.
== Lifting ==
We will now have a more detailed look at the <code>lift</code> function, which is critical in day-to-day use of monad transformers. The first thing to clarify is the name "lift". One function with a similar name that we already know is <code>liftM</code>. As we have seen in [[Haskell/Understanding monads#Is my Monad a Functor?|Understanding monads]], it is a monad-specific version of <code>fmap</code>:
<syntaxhighlight lang="haskell">
liftM :: Monad m => (a -> b) -> m a -> m b
</syntaxhighlight>
<code>liftM</code> applies a function <code>(a -> b)</code> to a value within a monad <code>m</code>. We can also look at it as a function of just one argument:
<syntaxhighlight lang="haskell">
liftM :: Monad m => (a -> b) -> (m a -> m b)
</syntaxhighlight>
<code>liftM</code> converts a plain function into one that acts within <code>m</code>. By "lifting", we refer to bringing something into something else — in this case, a function into a monad.
<code>liftM</code> allows us to apply a plain function to a monadic value without needing do-blocks or other such tricks:
{|align="center" border="1"
!|bind notation
!|do notation
!|liftM
|-
|valign="top"|
<syntaxhighlight lang="haskell">
monadicValue >>=
\x -> return (f x)
</syntaxhighlight>
|valign="top"|
<syntaxhighlight lang="haskell">
do x <- monadicValue
return (f x)
</syntaxhighlight>
|valign="top"|
<syntaxhighlight lang="haskell">
liftM f monadicValue
</syntaxhighlight>
|}
The <code>lift</code> function plays an analogous role when working with monad transformers. It brings (or, to use another common word for that, ''promotes'') base monad computations to the combined monad. By doing so, it allows us to easily insert base monad computations as part of a larger computation in the combined monad.
<code>lift</code> is the single method of the <code>MonadTrans</code> class, found in {{Haskell/Lib|p=transformers|v=latest|Control|Monad|Trans|Class}}. All monad transformers are instances of <code>MonadTrans</code>, and so <code>lift</code> is available for them all.
<syntaxhighlight lang="haskell">
class MonadTrans t where
lift :: (Monad m) => m a -> t m a
</syntaxhighlight>
There is a variant of <code>lift</code> specific to <code>IO</code> operations, called <code>liftIO</code>, which is the single method of the <code>MonadIO</code> class in {{Haskell/Lib|p=base|v=latest|Control|Monad|IO|Class}}.
<syntaxhighlight lang="haskell">
class (Monad m) => MonadIO m where
liftIO :: IO a -> m a
</syntaxhighlight>
<code>liftIO</code> can be convenient when multiple transformers are stacked into a single combined monad. In such cases, <code>IO</code> is always the innermost monad, and so we typically need more than one lift to bring <code>IO</code> values to the top of the stack. <code>liftIO</code> is defined for the instances in a way that allows us to bring an <code>IO</code> value from any depth while writing the function a single time.
=== Implementing <code>lift</code> ===
Implementing <code>lift</code> is usually pretty straightforward. Consider the <code>MaybeT</code> transformer:
<syntaxhighlight lang="haskell">
instance MonadTrans MaybeT where
lift m = MaybeT (liftM Just m)
</syntaxhighlight>
We begin with a monadic value of the base monad. With <code>liftM</code> (<code>fmap</code> would have worked just as fine), we slip the precursor monad (through the <code>Just</code> constructor) underneath, so that we go from <code>m a</code> to <code>m (Maybe a)</code>. Finally, we wrap things up with the <code>MaybeT</code> constructor. Note that the <code>liftM</code> here works in the base monad, just like the do-block wrapped by <code>MaybeT</code> in the implementation of <code>(>>=)</code> we saw early on was in the base monad.
{{Exercises|1=
<ol>
<li>Why is it that the <code>lift</code> function has to be defined separately for each monad, where as <code>liftM</code> can be defined in a universal way?</li>
<li><code>Identity</code> is a trivial functor, defined in <code>Data.Functor.Identity</code> as:<pre>newtype Identity a = Identity { runIdentity :: a }</pre>It has the following <code>Monad</code> instance:
<pre>
instance Monad Identity where
return a = Identity a
m >>= k = k (runIdentity m)
</pre>Implement a monad transformer <code>IdentityT</code>, analogous to <code>Identity</code> but wrapping values of type <code>m a</code> rather than <code>a</code>. Write at least its <code>Monad</code> and <code>MonadTrans</code> instances.</li>
</ol>
}}
== Implementing transformers ==
===The State transformer===
As an additional example, we will now have a detailed look at the implementation of <code>StateT</code>. You might want to review the section on the [[Haskell/Understanding monads/State|State monad]] before continuing.
Just as the State monad might have been built upon the definition <code>newtype State s a = State { runState :: (s -> (a,s)) }</code>, the StateT transformer is built upon the definition:
<syntaxhighlight lang="haskell">
newtype StateT s m a = StateT { runStateT :: (s -> m (a,s)) }</syntaxhighlight>
<code>StateT s m</code> will have the following <code>Monad</code> instance, here shown alongside the one for the precursor state monad:
{|border="1"
!|State
!|StateT
|-valign="top"
||<syntaxhighlight lang="haskell">
newtype State s a =
State { runState :: (s -> (a,s)) }
instance Monad (State s) where
return a = State $ \s -> (a,s)
(State x) >>= f = State $ \s ->
let (v,s') = x s
in runState (f v) s'
</syntaxhighlight>
||<syntaxhighlight lang="haskell">
newtype StateT s m a =
StateT { runStateT :: (s -> m (a,s)) }
instance (Monad m) => Monad (StateT s m) where
return a = StateT $ \s -> return (a,s)
(StateT x) >>= f = StateT $ \s -> do
(v,s') <- x s -- get new value and state
runStateT (f v) s' -- pass them to f
</syntaxhighlight>
|}
Our definition of <code>return</code> makes use of the <code>return</code> function of the base monad. <code>(>>=)</code> uses a do-block to perform a computation in the base monad.
{{body note|1=
Incidentally, we can now finally explain why, [[Haskell/Understanding monads/State#Where did the State constructor go?|back in the chapter about <code>State</code>]], there was a <code>state</code> function instead of a <code>State</code> constructor. In the <code>transformers</code> and <code>mtl</code> packages, <code>State s</code> is implemented as a type synonym for <code>StateT s Identity</code>, with <code>Identity</code> being the dummy monad introduced in an exercise of the previous section. The resulting monad is equivalent to the one defined using <code>newtype</code> that we have used up to now.
}}
If the combined monads <code>StateT s m</code> are to be used as state monads, we will certainly want the all-important <code>get</code> and <code>put</code> operations. Here, we will show definitions in the style of the <code>mtl</code> package. In addition to the monad transformers themselves, <code>mtl</code> provides type classes for the essential operations of common monads. For instance, the <code>MonadState</code> class, found in {{Haskell/Lib|p=mtl|v=latest|Control|Monad|State}}, has <code>get</code> and <code>put</code> as methods:
<syntaxhighlight lang="haskell">
instance (Monad m) => MonadState s (StateT s m) where
get = StateT $ \s -> return (s,s)
put s = StateT $ \_ -> return ((),s)
</syntaxhighlight>
{{body note|1=
<code>instance (Monad m) => MonadState s (StateT s m)</code> should be read as: "For any type <code>s</code> and any instance of <code>Monad</code> <code>m</code>, <code>s</code> and <code>StateT s m</code> together form an instance of <code>MonadState</code>". <code>s</code> and <code>m</code> correspond to the state and the base monad, respectively. <code>s</code> is an independent part of the instance specification so that the methods can refer to it − for instance, the type of <code>put</code> is <code>s -> StateT s m ()</code>.
}}
There are <code>MonadState</code> instances for state monads wrapped by other transformers, such as <code>MonadState s m => MonadState s (MaybeT m)</code>. They bring us extra convenience by making it unnecessary to lift uses of <code>get</code> and <code>put</code> explicitly, as the <code>MonadState</code> instance for the combined monads handles the lifting for us.
It can also be useful to lift instances that might be available for the base monad to the combined monad. For instance, all combined monads in which <code>StateT</code> is used with an instance of <code>MonadPlus</code> can be made instances of <code>MonadPlus</code>:
<syntaxhighlight lang="haskell">
instance (MonadPlus m) => MonadPlus (StateT s m) where
mzero = StateT $ \_ -> mzero
(StateT x1) `mplus` (StateT x2) = StateT $ \s -> (x1 s) `mplus` (x2 s)
</syntaxhighlight>
The implementations of <code>mzero</code> and <code>mplus</code> do the obvious thing; that is, delegating the actual work to the instance of the base monad.
Lest we forget, the monad transformer must have a <code>MonadTrans</code>, so that we can use <code>lift</code>:
<syntaxhighlight lang="haskell">
instance MonadTrans (StateT s) where
lift c = StateT $ \s -> c >>= (\x -> return (x,s))
</syntaxhighlight>
The <code>lift</code> function creates a <code>StateT</code> state transformation function that binds the computation in the base monad to a function that packages the result with the input state. If, for instance, we apply StateT to the List monad, a function that returns a list (i.e., a computation in the List monad) can be lifted
into <code>StateT s []</code> where it becomes a function that returns a <code>StateT (s -> [(a,s)])</code>. I.e. the lifted computation produces ''multiple'' (value,state) pairs from its input state. This "forks" the computation in StateT, creating a different branch of the computation for each value in the list returned by the lifted function. Of course, applying <code>StateT</code> to a different monad will produce different semantics for the <code>lift</code> function.
{{Exercises|1=
<ol>
<li>Implement <code>state :: MonadState s m => (s -> (a, s)) -> m a</code> in terms of <code>get</code> and <code>put</code>.</li>
<li>Are <code>MaybeT (State s)</code> and <code>StateT s Maybe</code> equivalent? (Hint: one approach is comparing what the <code>run...T</code> unwrappers produce in each case.)</li>
</ol>
}}
==Acknowledgements==
This module uses a number of excerpts from [http://www.haskell.org/haskellwiki/All_About_Monads All About Monads], with permission from its author Jeff Newbern.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Monads}}
{{BookCat}}
90l7y1zntmd4657hgsy6ptsi4g98h2t
Haskell/Indentation
0
66025
4676004
4445262
2026-10-14T10:24:06Z
~2026-54868-50
3628373
4676004
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Intermediate Haskell}}
Haskell relies on indentation to reduce the verbosity of your code. Despite some complexity in practice, there are really only a couple fundamental layout rules.<ref>See section 2.7 of [http://www.haskell.org/onlinereport/lexemes.html#sect2.7 The Haskell Report (lexemes)] on layout.</ref>
== The golden rule of indentation ==
'''Code which is part of some expression should be indented further in than the beginning of that expression''' (even if the expression is not the leftmost element of the line).
The easiest example is a 'let' binding group. The equations binding the variables are part of the 'let' expression, and so should be indented further in than the beginning of the binding group: the 'let' keyword. When you start the expression on a separate line, you only need to indent by one space (although more than one space is also acceptable and may be clearer).
<syntaxhighlight lang="haskell">
let
x = a
y = b
</syntaxhighlight>
You may also place the first clause alongside the 'let' as long as you indent the rest to line up:
{|border="0"
!|wrong
!|wrong
!|right
|-
||<syntaxhighlight lang="haskell">
let x = a
y = b</syntaxhighlight>
||<syntaxhighlight lang="haskell">
let x = a
y = b</syntaxhighlight>
||<syntaxhighlight lang="haskell">
let x = a
y = b</syntaxhighlight>
|}
This tends to trip up a lot of beginners: All ''grouped'' expressions must be exactly aligned. On the first line, Haskell counts everything to the left of the expression as indent, even though it is not whitespace.
Here are some more examples:
<syntaxhighlight lang="haskell">
do
foo
bar
baz
do foo
bar
baz
where x = a
y = b
case x of
p -> foo
p' -> baz
</syntaxhighlight>
Note that with 'case' it is less common to place the first subsidiary expression on the same line as the 'case' keyword (although it would still be valid code). Hence, the subsidiary expressions in a case expression tend to be indented only one step further than the 'case' line. Also note how we lined up the arrows here: this is purely aesthetic and is not counted as different layout; only ''indentation'' (i.e. whitespace beginning on the far-left edge) makes a difference to the interpretation of the layout.
Things get more complicated when the beginning of an expression is not at the start of a line. In this case, it's safe to just indent further than the line containing the expression's beginning. In the following example, <code>do</code> comes at the end of a line, so the subsequent parts of the expression simply need to be indented relative to the line that contains the <code>do</code>, not relative to the <code>do</code> itself.
<syntaxhighlight lang="haskell">
myFunction firstArgument secondArgument = do
foo
bar
baz
</syntaxhighlight>
Here are some alternative layouts which all work:
<syntaxhighlight lang="haskell">
myFunction firstArgument secondArgument =
do foo
bar
baz
myFunction firstArgument secondArgument = do foo
bar
baz
myFunction firstArgument secondArgument =
do
foo
bar
baz
</syntaxhighlight>
== Explicit characters in place of indentation ==
Indentation is actually optional if you instead use semicolons and curly braces for grouping and separation, as in "one-dimensional" languages like C. Even though the consensus among Haskell programmers is that meaningful indentation leads to better-looking code, understanding how to convert from one style to the other can help understand the indentation rules. The entire layout process can be summed up in three translation rules (plus a fourth one that doesn't come up very often):
# If you see one of the layout keywords, (<code>let</code>, <code>where</code>, <code>of</code>, <code>do</code>), insert an open curly brace (right before the stuff that follows it)
# If you see something indented to the SAME level, insert a semicolon
# If you see something indented LESS, insert a closing curly brace
# If you see something unexpected in a list, like <code>where</code>, insert a closing brace before instead of a semicolon.
For instance, this definition...
<syntaxhighlight lang="haskell">
foo :: Double -> Double
foo x =
let s = sin x
c = cos x
in 2 * s * c
</syntaxhighlight>
...can be rewritten without caring about the indentation rules as:
<syntaxhighlight lang="haskell">
foo :: Double -> Double;
foo x = let {
s = sin x;
c = cos x;
} in 2 * s * c
</syntaxhighlight>
One circumstance in which explicit braces and semicolons can be convenient is when writing one-liners in GHCi:
<syntaxhighlight lang="haskell">
Prelude> let foo :: Double -> Double; foo x = let { s = sin x; c = cos x } in 2 * s * c
</syntaxhighlight>
{{Exercises|1=
Rewrite this snippet from the Control Structures chapter using explicit braces and semicolons:
<syntaxhighlight lang="haskell">
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
case compare (read guess) num of
LT -> do putStrLn "Too low!"
doGuessing num
GT -> do putStrLn "Too high!"
doGuessing num
EQ -> putStrLn "You Win!"
</syntaxhighlight>
}}
== Layout in action ==
{|border="1"
!|wrong
!|wrong
!|right
!|right
|-
||
<syntaxhighlight lang="haskell">
do first thing
second thing
third thing
</syntaxhighlight>
||
<syntaxhighlight lang="haskell">
do first thing
second thing
third thing
</syntaxhighlight>
||
<syntaxhighlight lang="haskell">
do first thing
second thing
third thing
</syntaxhighlight>
||
<syntaxhighlight lang="haskell">
do
first thing
second thing
third thing
</syntaxhighlight>
|}
=== Indent to the first ===
Due to the "golden rule of indentation" described above, a curly brace within a <code>do</code> block depends not on the <code>do</code> itself but the thing that immediately follows it. For example, this weird-looking block of code is totally acceptable:
<syntaxhighlight lang="haskell">
do
first thing
second thing
third thing
</syntaxhighlight>
As a result, you could also write combined if/do combination like this:
{|border="1"
!|Wrong
!|Right
!|Right
|-
||
<syntaxhighlight lang="haskell">
if foo
then do first thing
second thing
third thing
else do something_else
</syntaxhighlight>
||
<syntaxhighlight lang="haskell">
if foo
then do first thing
second thing
third thing
else do something_else
</syntaxhighlight>
||
<syntaxhighlight lang="haskell">
if foo
then do
first thing
second thing
third thing
else do
something_else
</syntaxhighlight>
|}
It isn't about the <code>do</code>, it's about lining up all the items that are at the same level within the <code>do</code>.
Thus, all of the following are acceptable:
<syntaxhighlight lang="haskell">
main = do
first thing
second thing
</syntaxhighlight>
or
<syntaxhighlight lang="haskell">
main =
do
first thing
second thing
</syntaxhighlight>
or
<syntaxhighlight lang="haskell">
main =
do first thing
second thing
</syntaxhighlight>
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Intermediate Haskell}}
{{BookCat}}
afkmp7efista7mvyvpzw8uup3f0fbsq
Radiation Oncology/Radioimmunotherapy
0
70333
4675983
4585785
2026-10-14T06:04:09Z
Jcb
90773
4675983
wikitext
text/x-wiki
{{:Radiation Oncology/NHL:TOC}}
==Forms of RIT==
*'''Zevalin''' - ibritumomab, Y-90 labeled murine antibody. Pure beta emitter, 64 hr half life.
*'''Bexxar''' - tositumomab, I-131 labeled murine antibody, beta and gamma, 8 day half life. Dose is based on individual patient dosimetry (pharmacokinetics).
'''Rituxan''' - rituxumab, unlabeled ''chimeric'' anti-CD20 antibody.
==Administration==
===Bexxar===
'''''Steps:'''''
*'''Dosimetric step''' - infusion of unlabled antibody (tositumomab, not rituxumab, 450 mg) followed by 5 mCi dose of I-131-tositumomab.
*Whole body imaging on Day 0 (day of dosimetric step), day 2-4, and day 6 or 7. If biodistribution is acceptable, then calculate patient specific dose to deliver 75 cGy (or 65 cGy if plts 100,000-150,000).
*<br>'''Therapeutic step''' - 7-14 days after dosimetric step. 2nd infusion of unlabeled antibody followed by patient-specific dose of I-131-tositumomab to deliver 65-75 cGy total body dose.
'''''Patient selection:'''''
*Should not be administered to patients with >25% bone marrow involvement and/or impaired bone marrow reserve.
*Caution should be exercised in patients with impaired renal function.
*Do not administer if there is altered biodistribution (see below).
'''''Thyroid protection:'''''
<br>Begin the day prior to dosimetric step. Continue through 14 days after therapeutic dose.
'''''Dosimetry:'''''
<br>Whole body images obtained with gamma camera every 3 days to determine total body residence time (TBRT), reflecting clearance of the radioisotope. Count 1 is within an hour of the infusion of the dosimetric dose; Count 2 is 2-4 days after dosimetric dose.
<br>Assess whole body images for Counts 1 and 2 (and optionally Count 3) to see if there is altered biodistribution. If there is altered biodistribution based on the images or the TBRT, then Bexxar should not be administered.
<br>'''Expected biodistribution:''' 1st Image: most of the activity is in the blood pool (heart and major vessels), and uptake in the normal liver and spleen is less than the heart. On 2nd and 3rd images, blood pool activity and liver activity decreases. Uptake by thyroid, kidney, urinary bladder, and minimal lung uptake.
<br>'''Altered biodistribution: '''
*''1st image:'' if blood pool is not visualized or if there is diffuse, intense uptake in the liver and/or spleen or if there is a suggestion of urinary obstruction. If there is diffuse lung uptake greater than that of the blood pool.
*''2nd and 3rd images:'' urinary obstruction or diffuse lung uptake greater than that of blood pool.
*TBRT <50 hrs or >150 hrs
'''''Dose adjustments:'''''
<br>For platelet count >= 150,000, total body dose is 75 cGy. For platelets 100,000-150,000, total body dose is 65 cGy.
<br>For obese patients (weight > 137% of ideal body weight), dose should be based on 137% of their lean body weight.
===Treatment===
''See also specific treatment information at:''
*[[Radiation Oncology/NHL/Follicular]]
'''''For recurrence:'''''
*'''U. Washington''' - {{PMID|17312330}}, '''2007''' — "High-Dose [131I]Tositumomab (anti-CD20) Radioimmunotherapy and Autologous Hematopoietic Stem-Cell Transplantation for Adults ≥ 60 Years Old With Relapsed or Refractory B-Cell Lymphoma." Gopal AK et al. J Clin Oncol. 2007 Apr 10;25(11):1396-402.
**24 pts. Pts older > 60 yrs, relapsed B-cell NHL (s/p median of 4 prior regimens). Rituxan + Bexxar followed by ASCT.
**Median f/u 2.9 yrs. 3-yr OS and PFS 59% and 51%. 2 pts with grade 4 hematologic toxicity.
**Conclusion: safe and effective treatment for older adults
==Lutetium-177==
'''''<sup>177</sup>Lu-octeotrate'''''
*'''Erasmus; 2008''' (Netherlands)(2000-2006) {{PMID|18445841}} -- "Treatment with the radiolabeled somatostatin analog [177 Lu-DOTA 0,Tyr3]octreotate: toxicity, efficacy, and survival." (Kwekkeboom DJ, J Clin Oncol. 2008 May 1;26(13):2124-30.)
**Retrospective. 504 patients with gastroenteropancreatic neuroendocrine tumors (GEPNETs). Up to cumulative dose 750-800 mCi (27.8-29.6 GBq), usually in 4 cycles with intervals 6-10 weeks
**Outcome: CR 2%, PR 38%. Median TTP
**Toxicity: Grade 3+ hematologic in 4%, MDS in 3 patients 3.3 years, median OS 3.8 years (compared to historical controls, survival benefit of 3.3-6 years from diagnosis)
**Conclusion: Few adverse effects, response rate and PFS compare favorably to historical controls
7s9da4svter2yb8pwb2uortp8gvu0le
Haskell/More on datatypes
0
74659
4676011
4421938
2026-10-14T11:02:32Z
Luciérnaga de conocimiento
3401314
4676011
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Intermediate Haskell|noexercises=1}}
== Enumerations ==
One special case of the <code>data</code> declaration is the ''enumeration'' — a data type where none of the constructor functions have any arguments:
<syntaxhighlight lang="haskell">
data Month = January | February | March | April | May | June | July
| August | September | October | November | December
</syntaxhighlight>
You can mix constructors that do and do not have arguments, but then the result is not called an enumeration. The following example is ''not'' an enumeration because the last constructor takes three arguments:
<syntaxhighlight lang="haskell">
data Colour = Black | Red | Green | Blue | Cyan
| Yellow | Magenta | White | RGB Int Int Int
</syntaxhighlight>
As you will see further on when we discuss classes and derivation, there are practical reasons to distinguish between what is and isn't an enumeration.
Incidentally, the <code>Bool</code> datatype is an enumeration:
<syntaxhighlight lang="haskell">
data Bool = False | True
deriving (Bounded, Enum, Eq, Ord, Read, Show)
</syntaxhighlight>
== Named Fields (Record Syntax) ==
Consider a datatype whose purpose is to hold configuration settings.
Usually, when you extract members from this type, you really only care
about one or two of the many settings. Moreover, if many of
the settings have the same type, you might often find yourself
wondering "wait, was this the fourth or ''fifth'' element?" One
way to clarify is to write accessor functions. Consider the
following made-up configuration type for a terminal program:
<syntaxhighlight lang="haskell">
data Configuration = Configuration
String -- User name
String -- Local host
String -- Remote host
Bool -- Is guest?
Bool -- Is superuser?
String -- Current directory
String -- Home directory
Integer -- Time connected
deriving (Eq, Show)
</syntaxhighlight>
You could then write accessor functions, such as:
<syntaxhighlight lang="haskell">
getUserName (Configuration un _ _ _ _ _ _ _) = un
getLocalHost (Configuration _ lh _ _ _ _ _ _) = lh
getRemoteHost (Configuration _ _ rh _ _ _ _ _) = rh
getIsGuest (Configuration _ _ _ ig _ _ _ _) = ig
-- And so on...
</syntaxhighlight>
You could also write update functions to update a single element.
Of course, if you add or remove an element in the configuration later,
all of these functions now have to take a different number of
arguments. This is quite annoying and is an easy place for bugs to
slip in. Thankfully, there's a solution: we simply give names to the
fields in the datatype declaration, as follows:
<syntaxhighlight lang="haskell">
data Configuration = Configuration
{ username :: String
, localHost :: String
, remoteHost :: String
, isGuest :: Bool
, isSuperuser :: Bool
, currentDir :: String
, homeDir :: String
, timeConnected :: Integer
}
</syntaxhighlight>
This will automatically generate the following accessor functions for
us:
<syntaxhighlight lang="haskell">
username :: Configuration -> String
localHost :: Configuration -> String
-- etc.
</syntaxhighlight>
This also gives us a convenient update method. Here is a short
example for a "post working directory" and "change directory"
functions that work on <code>Configuration</code>s:
<syntaxhighlight lang="haskell">
changeDir :: Configuration -> String -> Configuration
changeDir cfg newDir =
if directoryExists newDir -- make sure the directory exists
then cfg { currentDir = newDir }
else error "Directory does not exist"
postWorkingDir :: Configuration -> String
postWorkingDir cfg = currentDir cfg
</syntaxhighlight>
So, in general, to update the field <code>x</code> in a value <code>y</code> to
<code>z</code>, you write <code>y { x = z }</code>. You can change more than one; each
should be separated by commas, for instance, <code>y {x = z, a = b, c = d }</code>.
{{body note|1=
Those of you familiar with object-oriented languages might be tempted, after all of this talk about "accessor functions" and "update methods", to think of the <code>y{x=z}</code> construct as a setter method, which modifies the value of x in a pre-existing y. It is '''not''' like that – remember that in Haskell [[Haskell/Variables and functions#Variables in imperative languages|variables are immutable]]. Therefore, using the example above, if you do something like
<code>conf2 = changeDir conf1 "/opt/foo/bar"</code>
<code>conf2</code> will be defined as a <code>Configuration</code> which is just like <code>conf1</code> except for having <code>"/opt/foo/bar"</code> as its <code>currentDir</code>, but <code>conf1</code> will remain unchanged.
}}
=== It's only sugar ===
You can, of course, continue to pattern match against
<code>Configuration</code>s as you did before. The named fields are simply
syntactic sugar; you can still write something like:
<syntaxhighlight lang="haskell">
getUserName (Configuration un _ _ _ _ _ _ _) = un
</syntaxhighlight>
But there is no need to do this.
Finally, you can pattern match against named fields as in:
<syntaxhighlight lang="haskell">
getHostData (Configuration { localHost = lh, remoteHost = rh }) = (lh, rh)
</syntaxhighlight>
This matches the variable <code>lh</code> against the <code>localHost</code> field in
the <code>Configuration</code> and the variable <code>rh</code> against the
<code>remoteHost</code> field. These matches will succeed, of course.
You could also constrain the matches by putting values instead of
variable names in these positions, as you would for standard datatypes.
If you are using GHC, then, with the language extension <code>NamedFieldPuns</code>, it is also possible to use this form:
<syntaxhighlight lang="haskell">
getHostData (Configuration { localHost, remoteHost }) = (localHost, remoteHost)
</syntaxhighlight>
It can be mixed with the normal form like this:
<syntaxhighlight lang="haskell">
getHostData (Configuration { localHost, remoteHost = rh }) = (localHost, rh)
</syntaxhighlight>
(To use this language extension, enter <code>:set -XNamedFieldPuns</code> in the interpreter, or use the <code>{-# LANGUAGE NamedFieldPuns #-}</code> pragma at the beginning of a source file, or pass the <code>-XNamedFieldPuns</code> command-line flag to the compiler.)
You can create values of <code>Configuration</code> in the old way as shown in
the first definition below, or in the named field's type, as shown in
the second definition:
<syntaxhighlight lang="haskell">
initCFG = Configuration "nobody" "nowhere" "nowhere" False False "/" "/" 0
initCFG' = Configuration
{ username = "nobody"
, localHost = "nowhere"
, remoteHost = "nowhere"
, isGuest = False
, isSuperuser = False
, currentDir = "/"
, homeDir = "/"
, timeConnected = 0
}
</syntaxhighlight>
The first way is much shorter, but the second is much clearer.
WARNING: The second style will allow you to write code that omits fields but will still compile, such as:
<syntaxhighlight lang="haskell">
cfgFoo = Configuration { username = "Foo" }
cfgBar = Configuration { localHost = "Bar", remoteHost = "Baz" }
cfgUndef = Configuration {}
</syntaxhighlight>
Trying to evaluate the unspecified fields will then result in a runtime error!
== Parameterized Types ==
Parameterized types are similar to "generic" or "template" types in other languages. A parameterized type takes one or more type parameters. For example, the Standard Prelude type <code>Maybe</code> is defined as follows:
<syntaxhighlight lang="haskell">
data Maybe a = Nothing | Just a
</syntaxhighlight>
This says that the type <code>Maybe</code> takes a type parameter <code>a</code>. You can use this to declare, for example:
<syntaxhighlight lang="haskell">
lookupBirthday :: [Anniversary] -> String -> Maybe Anniversary
</syntaxhighlight>
The <code>lookupBirthday</code> function takes a list of birthday records and a string and returns a <code>Maybe Anniversary</code>. The usual interpretation of such a type is that if the name given through the string is found in the list of anniversaries the result will be <code>Just</code> the corresponding record; otherwise, it will be <code>Nothing</code>. <code>Maybe</code> is the simplest and most common way of indicating failure in Haskell. It is also sometimes seen in the types of function arguments, as a way to make them optional (the intent being that passing <code>Nothing</code> amounts to omitting the argument).
You can parameterize <code>type</code> and <code>newtype</code> declarations in exactly the same way. Furthermore you can combine parameterized types in arbitrary ways to construct new types.
=== More than one type parameter ===
We can also have more than one type parameter. An example of this is the <code>Either</code> type:
<syntaxhighlight lang="haskell">
data Either a b = Left a | Right b
</syntaxhighlight>
For example:
<syntaxhighlight lang="haskell">
pairOff :: Int -> Either String Int
pairOff people
| people < 0 = Left "Can't pair off negative number of people."
| people > 30 = Left "Too many people for this activity."
| even people = Right (people `div` 2)
| otherwise = Left "Can't pair off an odd number of people."
groupPeople :: Int -> String
groupPeople people =
case pairOff people of
Right groups -> "We have " ++ show groups ++ " group(s)."
Left problem -> "Problem! " ++ problem
</syntaxhighlight>
In this example <code>pairOff</code> indicates how many groups you would have if you paired off a certain number of people for your activity. It can also let you know if you have too many people for your activity or if somebody will be left out. So <code>pairOff</code> will return either an Int representing the number of groups you will have, or a String describing the reason why you can't create your groups.
=== Kind Errors ===
The flexibility of Haskell parameterized types can lead to errors in type declarations that are somewhat like type errors, except that they occur in the type declarations rather than in the program proper. Errors in these "types of types" are known as "kind" errors. You don't program with kinds: the compiler infers them for itself. But if you get parameterized types wrong then the compiler will report a kind error.
{{Haskell/Navigation|chapter=Intermediate Haskell|noexercises=1}}
{{BookCat}}
fcxtb2i4ymnbtrqg1e2fubzro26tqx0
Haskell/Variables and functions
0
80256
4675909
4675766
2026-10-13T19:05:58Z
Luciérnaga de conocimiento
3401314
4675909
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Haskell Basics}}
''All the examples in this chapter can be saved into a Haskell source file and then evaluated by loading that file into GHCi. Do not include the "Prelude>" prompts part of any example. When that prompt is shown, it means you can type the following code into an environment like GHCi. Otherwise, you should put the code in a file and run it.''
== Variables ==
In the last chapter, we used GHCi as a calculator. Of course, that's only practical for short calculations. For longer calculations and for writing Haskell programs, we want to keep track of intermediate results.
We can store intermediate results by assigning them names. These names are called ''variables''. When a program runs, each variable is substituted for the ''value'' to which it refers. For instance, consider the following calculation:
{{Haskell/GHCi|1=
Prelude> 3.141592653 * 5^2
78.539816325
}}
That is the approximate area of a circle with radius <code>5</code>, according to the formula <math>A = \pi r^2</math>. Of course, it is cumbersome to type in the digits of <math>\pi \approx 3.141592653</math>, or even to remember more than the first few. Programming helps us avoid mindless repetition and rote memorization by delegating these tasks to a machine. That way, our minds stay free to deal with more interesting ideas. For the present case, Haskell already includes a variable named <code>pi</code> that stores over a dozen digits of <math>\pi</math> for us. This allows for not just clearer code, but also greater precision:
{{Haskell/GHCi|1=
Prelude> pi
3.141592653589793
Prelude> pi * 5^2
78.53981633974483
}}
Note that the variable <code>pi</code> and its value, <code>3.141592653589793</code>, can be used interchangeably in calculations.
== Haskell source files ==
Beyond momentary operations in GHCi, you will save your code in Haskell source files (basically plain text) with the extension <code>.hs</code>. Work with these files using a text editor appropriate for coding (see the [[w:text editor|Wikipedia article on text editors]]). Proper source code editors will provide ''syntax highlighting'', which colors the code in relevant ways to make reading and understanding easier. Vim and Emacs are popular choices among Haskell programmers, but have a bit of a learning curve to be able to fully benefit from their features. Visual Studio Code is also popular among Haskell programmers and is easier for beginners to use.
To keep things tidy, create a directory (i.e. a folder) in your computer to save the Haskell files you will create while doing the exercises in this book. Call the directory something like <code>HaskellWikibook</code>. Then, create a new file in that directory called <code>Varfun.hs</code> with the following code:
<syntaxhighlight lang = "haskell">
r = 5.0
</syntaxhighlight>
That code defines the variable <code>r</code> as the value <code>5.0</code>.
Note: make sure that there are no spaces at the beginning of the line because Haskell is sensitive to whitespace.
Next, with your terminal at the <code>HaskellWikibook</code> directory, start GHCi and load the <code>Varfun.hs</code> file using the <code>:load</code> command:
{{Haskell/GHCi|1=
Prelude> :load Varfun.hs
[1 of 1] Compiling Main ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
}}
Note that <code>:load</code> can be abbreviated as <code>:l</code> (as in <code>:l Varfun.hs</code>).
If GHCi gives an error like <code>Could not find module 'Varfun.hs'</code>, you are probably running GHCi in the wrong directory or saved your file in the wrong directory. You can use the <code>:cd</code> command to change directories within GHCi (for instance, <code>:cd HaskellWikibook</code>).
With the file loaded, GHCi's prompt changes from "Prelude" to "*Main". You can now use the newly defined variable <code>r</code> in your calculations:
{{Haskell/GHCi|1=
*Main> r
5.0
*Main> pi * r^2
78.53981633974483
}}
So, we calculated the area of a circle with radius of 5.0 using the well-known formula <math>\pi r^2</math>. This worked because we defined <code>r</code> in our Varfun.hs file and <code>pi</code> comes from the standard Haskell libraries.
Next, we'll make the area formula easier to quickly access by defining a variable name for it. Change the contents of the source file to:
<syntaxhighlight lang = "haskell">
r = 5.0
area = pi * r ^ 2
</syntaxhighlight>
Save the file. Then, assuming you kept GHCi running with the file still loaded, type <code>:reload</code> (or abbreviate version <code>:r</code>):
{{Haskell/GHCi|1=
*Main> :reload
Compiling Main ( Varfun.hs, interpreted )
Ok, modules loaded: Main.
*Main>
}}
Now we have two variables <code>r</code> and <code>area</code>:
{{Haskell/GHCi|1=
*Main> area
78.53981633974483
*Main> area / r
15.707963267948966
}}
{{body note|The <code>let</code> ''keyword'' (a word with a special meaning) lets us define variables directly at the GHCi prompt without a source file. This looks like:
<nowiki>Prelude> let area = pi * 5 ^ 2</nowiki>
Although sometimes convenient, assigning variables entirely in GHCi this way is impractical for any complex tasks. We will usually want to use saved source files.
}}
== Comments ==
Besides the working code itself, source files may contain text ''comments''. In Haskell there are two types of comment. The first starts with <code>--</code> and continues until the end of the line:
<syntaxhighlight lang = "haskell">
x = 5 -- x is 5.
y = 6 -- y is 6.
-- z = 7 -- z is not defined.
</syntaxhighlight>
In this case, <code>x</code> and <code>y</code> are defined in actual Haskell code, but <code>z</code> is not.
The second type of comment is denoted by an enclosing <code>{- ... -}</code> and can span multiple lines:
<syntaxhighlight lang = "haskell">
answer = 2 * {-
block comment, crossing lines and...
-} 3 {- inline comment. -} * 7
</syntaxhighlight>
By combining single- and multi-line commenting, it is possible to toggle between executed and commented-out code by adding or removing a single <code>}</code> character, respectively:
<syntaxhighlight lang = "haskell">
{--
foo :: String
foo = "bar"
--}
</syntaxhighlight>
vs.
<syntaxhighlight lang = "haskell">
{--}
foo :: String
foo = "bar"
--}
</syntaxhighlight>
We use comments for explaining parts of a program or making other notes in context. Beware of comment overuse as too many comments can make programs harder to read. Also, we must carefully update comments whenever we change the corresponding code. Outdated comments can cause significant confusion.
== Variables in imperative languages ==
Readers familiar with imperative programming will notice that variables in Haskell seem quite different from variables in languages like C.
If you have no programming experience, you could skip this section, but it will help you understand the general situation when encountering the many cases (most Haskell textbooks, for example) where people discuss Haskell in reference to other programming languages.
''Imperative programming'' treats variables as changeable locations in a computer's memory. That approach connects to the basic operating principles of computers. Imperative programs explicitly tell the computer what to do. Higher-level imperative languages are quite removed from direct computer assembly code instructions, but they retain the same step-by-step way of thinking. In contrast, ''functional programming'' offers a way to think in higher-level mathematical terms, defining how variables relate to one another, leaving the compiler to translate these to the step-by-step instructions that the computer can process.
Let's look at an example. The following code does not work in Haskell:
<syntaxhighlight lang = "haskell">
r = 5
r = 2
</syntaxhighlight>
An imperative programmer may read this as first setting <code>r = 5</code> and then changing it to <code>r = 2</code>. In Haskell, however, the compiler will respond to the code above with an error: "multiple declarations of <code>r</code>". Within a given scope, a variable in Haskell gets defined only once and cannot change.
The variables in Haskell seem almost ''invariable'', but they work like variables in mathematics. In a math classroom, you never see a variable change its value within a single problem.
In precise terms, Haskell variables are ''immutable''. They vary only based on the data we enter into a program. We can't define <code>r</code> two ways in the same code, but we could change the value by changing the file. Let's update our code from above:
<syntaxhighlight lang = "haskell">
r = 2.0
area = pi * r ^ 2
</syntaxhighlight>
Of course, that works just fine. We can change <code>r</code> in the one place where it is defined, and that will automatically update the value of all the rest of the code that uses the <code>r</code> variable.
Real-world Haskell programs work by leaving ''some'' variables unspecified in the code. The values then get defined when the program gets data from an external file, a database, or user input. For now, however, we will stick to defining variables internally. We will cover interaction with external data in later chapters.
Here's one more example of a major difference from imperative languages:
<syntaxhighlight lang = "haskell">
r = r + 1
</syntaxhighlight>
Instead of "incrementing the variable <code>r</code>" (i.e. updating the value in memory), this Haskell code is a recursive definition of <code>r</code> (i.e. defining it in terms of itself). We will explain [[Haskell/Recursion|recursion]] in detail later on. For this specific case, if <code>r</code> had been defined with any value beforehand, then <code> r = r + 1 </code> in Haskell would bring an error message. <code> r = r + 1 </code> is akin to saying, in a mathematical context, that <math>5 = 5 + 1</math>, which is plainly wrong.
Because their values do not change within a program, variables can be defined in any order. For example, the following fragments of code do exactly the same thing:
{|border="0"
|-
||<syntaxhighlight lang = "haskell">
y = x * 2
x = 3
</syntaxhighlight>
||<syntaxhighlight lang = "haskell">
x = 3
y = x * 2
</syntaxhighlight>
|}
In Haskell, there is no notion of "<code>x</code> being declared before <code>y</code>" or the other way around. Of course, using <code>y</code> will still require a value for <code>x</code>, but this is unimportant until you need a specific numeric value.
== Functions ==
Changing our program every time we want to calculate the area of new circle is both tedious and limited to one circle at a time. We could calculate two circles by duplicating all the code using new variables <code>r2</code> and <code>area2</code> for the second circle:<ref>As this example shows, the names of variables may contain numbers as well as letters. Variables in Haskell ''must'' begin with a lowercase letter but may then have any string consisting of letter, numbers, underscore (_) or tick (').</ref>
<syntaxhighlight lang = "haskell">
r = 5
area = pi * r ^ 2
r2 = 3
area2 = pi * r2 ^ 2
</syntaxhighlight>
Of course, to eliminate this mindless repetition, we would prefer to have simply one ''function'' for area and then apply it to different radii.
A ''function'' takes an ''argument'' value (or ''parameter'') and gives a result value (essentially the same as in mathematical functions). Defining functions in Haskell is like defining a variable, except that we take note of the function argument that we put on the left hand side of the equals sign. For instance, the following defines a function <code>area</code> which depends on an argument named <code>r</code>:
<syntaxhighlight lang = "haskell">
area r = pi * r ^ 2
</syntaxhighlight>
Look closely at the syntax: the function name comes first (<code>area</code> in our example), followed by a space and then the argument (<code>r</code> in the example). Following the <code>=</code> sign, the ''function definition'' is a formula that uses the argument in context with other already defined terms.
Now, we can plug in different values for the argument in a ''call'' to the function. Save the code above in a file, load it into GHCi, and try the following:
{{Haskell/GHCi|1=
*Main> area 5
78.53981633974483
*Main> area 3
28.274333882308138
*Main> area 17
907.9202768874502
}}
Thus, we can ''call'' this function with different radii to calculate the area of any circle.
Our function here is defined mathematically as
:<math>A(r) = \pi \cdot r^2</math>
In mathematics, the argument is enclosed between parentheses, as in <math>A(5) = 78.54</math> or <math>A(3) = 28.27</math>. Many programming languages likewise surround arguments with parentheses, as in <code>max(2, 3)</code>. But Haskell omits parentheses around a list of arguments (as well as commas between them): <code>max 2 3</code>.
We still use parentheses for grouping ''expressions'' (any code that gives a value) that must be evaluated together. Note how the following expressions are parsed differently:
<syntaxhighlight lang = "haskell">
5 * 3 + 2 -- 15 + 2 = 17 (multiplication is done before addition)
5 * (3 + 2) -- 5 * 5 = 25 (thanks to the parentheses)
area 5 * 3 -- (area 5) * 3
area (5 * 3) -- area 15
</syntaxhighlight>
Note that Haskell functions take ''precedence'' over all other operators such as <code>+</code> and <code>*</code>, in the same way that, for instance, multiplication is done before addition in mathematics.
=== Evaluation ===
What exactly happens when you enter an expression into GHCi? After you press the enter key, GHCi will ''evaluate'' the expression you have given. That means it will replace each function with its definition and calculate the results until a single value remains. For example, the evaluation of <code>area 5</code> proceeds as follows:
area 5
=> { replace the left-hand side area r = ... by the right-hand side ... = pi * r^2 }
pi * 5 ^ 2
=> { replace pi by its numerical value }
3.141592653589793 * 5 ^ 2
=> { apply exponentiation (^) }
3.141592653589793 * 25
=> { apply multiplication (*) }
78.53981633974483
As this shows, to ''apply'' or ''call'' a function means to replace the left-hand side of its definition by its right-hand side. When using GHCi, the results of a function call will then show on the screen.
Some more functions:
<syntaxhighlight lang = "haskell">
double x = 2 * x
quadruple x = double (double x)
square x = x * x
half x = x / 2
</syntaxhighlight>
{{Exercises|1=
* Explain how GHCi evaluates <code>quadruple 5</code>.
* Define a function that subtracts 12 from half its argument.}}
=== Multiple parameters ===
Functions can also take more than one argument. For example, a function for calculating the area of a rectangle given its length and width:
<syntaxhighlight lang = "haskell">
areaRect l w = l * w
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaRect 5 10
50
}}
Another example that calculates the area of a triangle <math>\left(A = \frac{bh}{2}\right)</math>:
<syntaxhighlight lang="haskell">
areaTriangle b h = (b * h) / 2
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaTriangle 3 9
13.5
}}
As you can see, multiple arguments are separated by spaces. That's also why you sometimes have to use parentheses to group expressions. For instance, to quadruple a value <code>x</code>, you can't write:
<syntaxhighlight lang = "haskell">
quadruple x = double double x -- error
</syntaxhighlight>
That would apply a function named <code>double</code> to the two arguments <code>double</code> and <code>x</code>. Note that ''functions can be arguments to other functions'' (you will see why later). To make this example work, we need to put parentheses around the argument:
<syntaxhighlight lang = "haskell">
quadruple x = double (double x)
</syntaxhighlight>
Arguments are always passed in the order given. For example:
<syntaxhighlight lang = "haskell">
minus x y = x - y
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> minus 10 5
5
*Main> minus 5 10
-5
}}
Here, <code>minus 10 5</code> evaluates to <code>10 - 5</code>, but <code>minus 5 10</code> evaluates to <code>5 - 10</code> because the order changes.
{{Exercises|1=
* Write a function to calculate the volume of a box.
* Approximately how many stones are the famous pyramids at Giza made up of? Hint: you will need estimates for the volume of the pyramids and the volume of each block.
}}
=== On combining functions ===
Of course, you can use functions that you have already defined to define new functions, just like you can use the predefined functions like addition <code>(+)</code> or multiplication <code>(*)</code> (operators are defined as functions in Haskell). For example, to calculate the area of a square, we can reuse our function that calculates the area of a rectangle:
<syntaxhighlight lang = "haskell">
areaRect l w = l * w
areaSquare s = areaRect s s
</syntaxhighlight>
{{Haskell/GHCi|1=
*Main> areaSquare 5
25
}}
After all, a square is just a rectangle with equal sides.
{{Exercises|1=
* Write a function to calculate the volume of a cylinder. The volume of a cylinder is the area of the base, which is a circle (you already programmed this function in this chapter, so reuse it) multiplied by the height.
}}
== Local definitions ==
=== <code>where</code> clauses ===
When defining a function, we sometimes want to define intermediate results that are ''local'' to the function. For instance, consider [[w:Heron's formula|Heron's formula]] <math>A = \sqrt{s(s-a)(s-b)(s-c)}</math> for calculating the area of a triangle with sides <code>a</code>, <code>b</code>, and <code>c</code>:
<syntaxhighlight lang = "haskell">
heron a b c = sqrt (s * (s - a) * (s - b) * (s - c))
where
s = (a + b + c) / 2
</syntaxhighlight>
The variable <code>s</code> is half the perimeter of the triangle and it would be tedious to write it out four times in the argument of the square root function <code>sqrt</code>.
Simply writing the definitions in sequence does not work...
<syntaxhighlight lang = "haskell">
heron a b c = sqrt (s * (s - a) * (s - b) * (s - c))
s = (a + b + c) / 2 -- a, b, and c are not defined here
</syntaxhighlight>
... because the variables <code>a</code>, <code>b</code>, <code>c</code> are only available in the right-hand side of the function <code>heron</code>, but the definition of <code>s</code> as written here is not part of the right-hand side of <code>heron</code>. To make it part of the right-hand side, we use the <code>where</code> keyword.
Note that both the <code>where</code> and the local definitions are ''indented'' by 4 spaces, to distinguish them from subsequent definitions. Here is another example that shows a mix of local and top-level definitions:
<syntaxhighlight lang = "haskell">
areaTriangleTrig a b c = c * height / 2 -- use trigonometry
where
cosAlfa = (b ^ 2 + c ^ 2 - a ^ 2) / (2 * b * c)
sinAlfa = sqrt (1 - cosAlfa ^ 2)
height = b * sinAlfa
areaTriangleHeron a b c = result -- use Heron's formula
where
result = sqrt (s * (s - a) * (s - b) * (s - c))
s = (a + b + c) / 2
</syntaxhighlight>
=== Scope ===
If you look closely at the previous example, you'll notice that we have used the variable names <code>a</code>, <code>b</code>, <code>c</code> twice, once for each of the two area functions. How does that work?
Consider the following GHCi sequence:
{{Haskell/GHCi|1=
Prelude> let r = 0
Prelude> let area r = pi * r ^ 2
Prelude> area 5
78.53981633974483
}}
It would have been an unpleasant surprise to return <code>0</code> for the area because of the earlier <code>let r = 0</code> definition getting in the way. That does not happen because when you defined <code>r</code> the second time you are talking about a ''different'' <code>r</code>. This may seem confusing, but consider how many people have the name John, and yet for any context with only one John, we can talk about "John" with no confusion. Programming has a notion similar to context, called ''[[Wikipedia:Scope (programming)|scope]]''.
We will not explain the technicalities behind scope right now. Just keep in mind that the value of a parameter is strictly what you pass in when you call the function, regardless of what the variable was called in the function's definition. That said, appropriately unique names for variables do make the code easier for human readers to understand.
== Summary ==
# Variables store values (which can be any arbitrary Haskell expression).
# Variables do not change within a scope.
# Functions help you write reusable code.
# Functions can accept more than one parameter.
We also learned about non-code text comments within a source file.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Haskell Basics}}
{{BookCat}}
cowm5t37o66ys6pqir0njmvnpddaa68
Haskell/Alternative and MonadPlus
0
80348
4676022
4342264
2026-10-14T11:14:19Z
Luciérnaga de conocimiento
3401314
4676022
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Monads}}
In our studies so far, we saw that both <code>Maybe</code> and lists can represent computations with a varying number of results. We use <code>Maybe</code> to indicate a computation can fail somehow (that is, it can have either zero results or one result), and we use lists for computations that can have many possible results (ranging from zero to arbitrarily many results). In both of these cases, one useful operation is amalgamating ''all'' possible results from multiple computations into a single computation. With lists, for instance, that would amount to concatenating lists of possible results. The <code>Alternative</code> class captures this amalgamation in a general way.
== Definition ==
{{body note|The <code>Alternative</code> class and its methods can be found in the {{Haskell lib|p=base|v=latest|Control|Applicative}} module.}}
<code>Alternative</code> is a subclass of <code>Applicative</code> whose instances must define, at a minimum, the following two methods:
<syntaxhighlight lang="haskell">
class Applicative f => Alternative f where
empty :: f a
(<|>) :: f a -> f a -> f a
</syntaxhighlight>
<code>empty</code> is an applicative computation with zero results, while <code>(<|>)</code> is a binary function which combines two computations.
Here are the two instance definitions for <code>Maybe</code> and lists:
<syntaxhighlight lang="haskell">
instance Alternative Maybe where
empty = Nothing
-- Note that this could have been written more compactly.
Nothing <|> Nothing = Nothing -- 0 results + 0 results = 0 results
Just x <|> Nothing = Just x -- 1 result + 0 results = 1 result
Nothing <|> Just x = Just x -- 0 results + 1 result = 1 result
Just x <|> Just y = Just x -- 1 result + 1 result = 1 result:
-- Maybe can only hold up to one result,
-- so we discard the second one.
instance Alternative [] where
empty = []
(<|>) = (++) -- length xs + length ys = length (xs ++ ys)
</syntaxhighlight>
== Example: parallel parsing ==
Traditional input parsing involves functions which consume an input one character at a time. That is, a parsing function takes an input string and chops off (i.e. "consumes") characters from the front if they satisfy certain criteria. For example, you could write a function which consumes one uppercase character. If the characters on the front of the string don't satisfy the given criteria, the parser has ''failed''. In the example below, for instance, we consume a digit in the input and return the digit that was parsed. The possibility of failure is expressed by using <code>Maybe</code>.
<syntaxhighlight lang="haskell">
digit i (c:_)
| i > 9 || i < 0 = Nothing
| otherwise =
if [c] == show i then Just i else Nothing
</syntaxhighlight>
The guards assure that the <code>Int</code> we are checking for is a single digit. Otherwise, we are just checking that the first character of our String matches the digit we are checking for. If it passes, we return the digit wrapped in a <code>Just</code>. Otherwise we return <code>Nothing</code>.
Now, <code>(<|>)</code> can be used to run two parsers ''in parallel''. That is, we use the result of the first one if it succeeds, and otherwise, we use the result of the second. If both fail, then the combined parser returns <code>Nothing</code>. We can use <code>digit</code> with <code>(<|>)</code> to, for instance, parse strings of binary digits:
<syntaxhighlight lang="haskell">
binChar :: String -> Maybe Int
binChar s = digit 0 s <|> digit 1 s
</syntaxhighlight>
Parser libraries often make use of <code>Alternative</code> in this way. Two examples are <code>(+++)</code> in {{Haskell lib|p=base|v=latest|Text|ParserCombinators|ReadP}} and <code>(<|>)</code> in {{Haskell lib|p=parsec|v=latest|Text|ParserCombinators|Parsec|Prim}}. This usage pattern can be described in terms of ''choice''. For instance, if we want to give <code>binChar</code> a string that will be successfully parsed, we have two choices: either to begin the string with <code>'0'</code> or with <code>'1'</code>.
== MonadPlus ==
The <code>MonadPlus</code> class is closely related to <code>Alternative</code>:
<syntaxhighlight lang="haskell">
class Monad m => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a
</syntaxhighlight>
Its definition is the same as <code>Alternative</code>, except for different method names and the <code>Applicative</code> constraint being changed into <code>Monad</code>. Unsurprisingly, for types that have instances of both <code>Alternative</code> and <code>MonadPlus</code>, <code>mzero</code> and <code>mplus</code> should be equivalent to <code>empty</code> and <code>(<|>)</code> respectively.
One might legitimately wonder why the seemingly redundant <code>MonadPlus</code> class exists. Part of the reason is historical: just like <code>Monad</code> existed in Haskell long before <code>Applicative</code> was introduced, <code>MonadPlus</code> is much older than <code>Alternative</code>. Beyond such accidents, there are additional expectations (ones that do not apply to <code>Alternative</code>) about how the <code>MonadPlus</code> methods should interact with the <code>Monad</code>, and therefore indicating that something is a <code>MonadPlus</code> is a stronger claim than indicating that it is both an <code>Alternative</code> and a <code>Monad</code>. We will make some additional considerations about this issue in the following section.
== Alternative and MonadPlus laws ==
Like most general-purpose classes, <code>Alternative</code> and <code>MonadPlus</code> are expected to follow a handful of laws. However, there isn't universal agreement on what the full set of laws should look like. The most commonly adopted laws, and the most crucial for providing intuition about <code>Alternative</code>, say that <code>empty</code> and <code>(<|>)</code> form a ''monoid''. By that, we mean:
<syntaxhighlight lang="haskell">
-- empty is a neutral element
empty <|> u = u
u <|> empty = u
-- (<|>) is associative
u <|> (v <|> w) = (u <|> v) <|> w
</syntaxhighlight>
There is nothing fancy about "forming a monoid": in the above, "neutral element" and "associative" here is just like how addition of integer numbers is said to be associative and to have zero as its neutral element. In fact, this analogy is the source of the names of the <code>MonadPlus</code> methods, <code>mzero</code> and <code>mplus</code>.
As for <code>MonadPlus</code>, at a minimum there usually are the monoid laws, which correspond exactly to the ones just above...
<syntaxhighlight lang="haskell">
mzero `mplus` m = m
m `mplus` mzero = m
m `mplus` (n `mplus` o) = (m `mplus` n) `mplus` o
</syntaxhighlight>
... plus the additional two laws, quoted by the {{Haskell lib|p=base|v=latest|Control|Monad}} documentation:
<syntaxhighlight lang="haskell">
mzero >>= f = mzero -- left zero
m >> mzero = mzero -- right zero
</syntaxhighlight>
If <code>mzero</code> is interpreted as a failed computation, these laws state that a failure within a chain of monadic computations leads to the failure of the whole chain.
We will touch upon some additional suggestions of laws for <code>Alternative</code> and <code>MonadPlus</code> at the end of the chapter.
== Useful functions ==
In addition to <code>(<|>)</code> and <code>empty</code>, there are two other general-purpose functions in the base libraries involving <code>Alternative</code>.
=== asum ===
A common task when working with <code>Alternative</code> is taking a list of alternative values, e.g. <code>[Maybe a]</code> or <code><nowiki>[[a]]</nowiki></code>, and folding it down with <code>(<|>)</code>. The function <code>asum</code>, from <code>Data.Foldable</code> fulfills this role:
<syntaxhighlight lang="haskell">
asum :: (Alternative f, Foldable t) => t (f a) -> f a
asum = foldr (<|>) empty
</syntaxhighlight>
In a sense, <code>asum</code> generalizes the list-specific <code>concat</code> operation. Indeed, the two are equivalent when lists are the <code>Alternative</code> being used. For Maybe, <code>asum</code> finds the first <code>Just x</code> in the list and returns <code>Nothing</code> if there aren't any.
It should also be mentioned that <code>msum</code>, available from both `Data.Foldable` and `Control.Monad`, is just <code>asum</code> specialised to <code>MonadPlus</code>.
<syntaxhighlight lang="haskell">
msum :: (MonadPlus m, Foldable t) => t (m a) -> m a
</syntaxhighlight>
=== guard ===
When discussing the [[Haskell/Understanding monads/List|list monad]] we noted how similar it was to list comprehensions, but we didn't discuss how to mirror list comprehension filtering. The <code>guard</code> function from <code>Control.Monad</code> allows us to do exactly that.
Consider the following comprehension which retrieves all [[w:Pythagorean_triple|pythagorean triples]] (i.e. trios of integer numbers which work as the lengths of the sides for a right triangle). First we'll examine the brute-force approach. We'll use a boolean condition for filtering; namely, Pythagoras' theorem:
<syntaxhighlight lang="haskell">
pythags = [ (x, y, z) | z <- [1..], x <- [1..z], y <- [x..z], x^2 + y^2 == z^2 ]
</syntaxhighlight>
The translation of the comprehension above to a list monad do-block is:
<syntaxhighlight lang="haskell">
pythags = do
z <- [1..]
x <- [1..z]
y <- [x..z]
guard (x^2 + y^2 == z^2)
return (x, y, z)
</syntaxhighlight>
The <code>guard</code> function can be defined for all <code>Alternative</code>s like this:
<syntaxhighlight lang="haskell">
guard :: Alternative m => Bool -> m ()
guard True = pure ()
guard _ = empty
</syntaxhighlight>
<code>guard</code> will reduce a do-block to <code>empty</code> if its predicate is <code>False</code>. Given the left zero law...
<syntaxhighlight lang="haskell">
mzero >>= f = mzero
-- Or, equivalently:
empty >>= f = empty
</syntaxhighlight>
... an <code>empty</code> on the left-hand side of an <code>>>=</code> operation will produce <code>empty</code> again. As do-blocks are decomposed to lots of expressions joined up by <code>(>>=)</code>, an <code>empty</code> at any point will cause the entire do-block to become <code>empty</code>.
Let's examine in detail what <code>guard</code> does in the <code>pythags</code>. First, here is <code>guard</code> defined for the list monad:
<syntaxhighlight lang="haskell">
-- guard :: Bool -> [()]
guard True = [()]
guard _ = []
</syntaxhighlight>
Basically, <code>guard</code> ''blocks off'' a route. In <code>pythags</code>, we want to block off all the routes (or combinations of <code>x</code>, <code>y</code> and <code>z</code>) where <code>x^2 + y^2 == z^2</code> is <code>False</code>. Let's look at the expansion of the above <code>do</code>-block to see how it works:
<syntaxhighlight lang="haskell">
pythags =
[1..] >>= \z ->
[1..z] >>= \x ->
[x..z] >>= \y ->
guard (x^2 + y^2 == z^2) >>= \_ ->
return (x, y, z)
</syntaxhighlight>
Replacing <code>>>=</code> and <code>return</code> with their definitions for the list monad (and using some let-bindings to keep it readable), we obtain:
<syntaxhighlight lang="haskell">
pythags =
let ret x y z = [(x, y, z)]
gd z x y = concatMap (\_ -> ret x y z) (guard $ x^2 + y^2 == z^2)
doY z x = concatMap (gd z x) [x..z]
doX z = concatMap (doY z ) [1..z]
doZ = concatMap (doX ) [1..]
in doZ
</syntaxhighlight>
Remember that <code>guard</code> returns the empty list in the case of its argument being <code>False</code>. Mapping across the empty list produces the empty list, no matter what function you pass in. So an empty list produced by the call to <code>guard</code> in <code>gd</code> will cause <code>gd</code> to produce an empty list, with <code>\_ -> ret x y z</code>, which would otherwise add a result, not being actually called.
To understand why this matters, think about list-computations as a tree. With our Pythagorean triple algorithm, we need a branch starting from the top for every choice of <code>z</code>, then a branch from each of these branches for every value of <code>x</code>, then from each of these, a branch for every value of <code>y</code>. So the tree looks like this:
start
|_________________________...
| | |
z 1 2 3
| |____ |____________
| | | | | |
x 1 1 2 1 2 3
| |_ | |___ |_ |
| | | | | | | | | |
y 1 1 2 2 1 2 3 2 3 3
Each combination of z, x and y represents a route through the tree. Once all the functions have been applied, the results of each branch are concatenated together, starting from the bottom. Any route where our predicate doesn't hold evaluates to an empty list, and so has no impact on this concatenation.
== Exercises ==
{{Exercises|1=
<ol>
<li>Prove the <code>Alternative</code> monoid laws for <code>Maybe</code> and lists.</li>
<li> We could augment the parser from the parallel parsing example so that it would handle any character, in the following manner:
<syntaxhighlight lang="haskell">
-- | Consume a given character in the input, and return
-- the character we just consumed, paired with rest of
-- the string. We use a do-block so that if the
-- pattern match fails at any point, 'fail' of the
-- Maybe monad (i.e. Nothing) is returned.
char :: Char -> String -> Maybe (Char, String)
char c s = do
c' : s' <- return s
guard (c == c')
return (c, s')
</syntaxhighlight>
It would then be possible to write a <code>hexChar</code> function which parses any valid hexadecimal character (0-9 or a-f). Try writing this function (hint: <code>map digit [0..9] :: [String -> Maybe Int]</code>).</li>
<li>Use <code>guard</code> and the <code>Applicative</code> combinators (<code>pure</code>, <code>(<*>)</code>, <code>(*>)</code>, etc.) to implement <code>safeLog</code> from [[Haskell/Understanding monads/Maybe|the Maybe monad chapter]]. Do not use the <code>Monad</code> combinators (<code>return</code>, <code>(>>=)</code>, <code>(>>)</code>, etc.).</li>
</ol>
}}
== Relationship with monoids ==
While discussing the <code>Alternative</code> laws above, we alluded to the mathematical concept of monoids. There is in fact already a <code>Monoid</code> class in Haskell (defined in {{Haskell lib|p=base|v=latest|Data|Monoid}}). A thorough presentation of monoid will be given in [[Haskell/Monoids|a later chapter]]. However for now it suffices to say that a minimal definition of <code>Monoid</code> implements two methods; namely, a neutral element (or 'zero') and an associative binary operation (or 'plus').
<syntaxhighlight lang="haskell">
class Monoid m where
mempty :: m
mappend :: m -> m -> m
</syntaxhighlight>
For example, lists form a simple monoid:
<syntaxhighlight lang="haskell">
instance Monoid [a] where
mempty = []
mappend = (++)
</syntaxhighlight>
Looks familiar, doesn't it? In spite of the uncanny resemblance to <code>Alternative</code> and <code>MonadPlus</code>, there is a key difference. Note the use of <code><nowiki>[a]</nowiki></code> instead of <code><nowiki>[]</nowiki></code> in the instance declaration. Monoids are not necessarily "wrappers" of anything, or parametrically polymorphic. For instance, the integer numbers form a monoid under addition with <code>0</code> as neutral element. <code>Alternative</code> is a separate type class because it captures a specific sort of monoid with distinctive properties − for instance, a binary operation {{nowrap|<code>(<{{!}}>) :: Alternative f {{=}}> f a -> f a -> f a</code>}} that is intrinsically linked to an <code>Applicative</code> context.
== Other suggested laws ==
{{body note|Consider this as a bonus section. While it is good to be aware of there being various takes on these laws, the whole issue is, generally speaking, not worth losing sleep over.}}
Beyond the commonly assumed laws mentioned a few sections above, there are a handful of others which make sense from certain perspectives, but do not hold for all existing instances of <code>Alternative</code> and <code>MonadPlus</code>. The current <code>MonadPlus</code>, in particular, might be seen as an intersection between a handful of hypothetical classes that would have additional laws.
The following two additional laws are commonly suggested for <code>Alternative</code>. While they do hold for both <code>Maybe</code> and lists, there are counterexamples in the core libraries. Also note that, for <code>Alternative</code>s that are also <code>MonadPlus</code>, the <code>mzero</code> laws mentioned earlier are not a consequence of these laws.
<syntaxhighlight lang="haskell">
(f <|> g) <*> a = (f <*> a) <|> (g <*> a) -- right distributivity (of <*>)
empty <*> a = empty -- right absorption (for <*>)
</syntaxhighlight>
As for <code>MonadPlus</code>, a common suggestion is the ''left distribution'' law, which holds for lists, but not for <code>Maybe</code>:
<syntaxhighlight lang="haskell">
(m `mplus` n) >>= k = (m >>= k) `mplus` (n >>= k) -- left distribution
</syntaxhighlight>
Conversely, the ''left catch'' law holds for <code>Maybe</code> but not for lists:
<syntaxhighlight lang="haskell">
return x `mplus` m = return x -- left catch
</syntaxhighlight>
It is generally assumed that either left distribution or left catch will hold for any <code>MonadPlus</code> instance. Why not both? Suppose they both hold. Then for any <code>x, y :: m a</code>,
<syntaxhighlight lang="haskell">
x `mplus` y
= -- monad identity
(return x >>= id) `mplus` (return y >>= id)
= -- left distribution
(return x `mplus` return y) >>= id
= -- left catch
return x >>= id
= -- monad identity
x
</syntaxhighlight>
This immediately rules out all but the most trivial <code>MonadPlus</code> implementation. Even worse, it implies that for any <code>x</code>, <code>mzero `mplus` x = mzero</code>. Adding the monoid identity law <code>mzero `mplus` x = x</code> then implies that the monad has only one value, and is thus isomorphic to the trivial monad <code>Data.Proxy.Proxy</code>.
Finally, it is worth noting that there are divergences even about the monoid laws. One case sometimes raised against them is that for certain non-determinism monads typically expressed in terms of <code>MonadPlus</code> the key laws are left zero and left distribution, while the monoid laws in such cases lead to difficulties and should be relaxed or dropped entirely.
Some entirely optional further reading, for the curious reader:
* [http://www.haskell.org/haskellwiki/MonadPlus The Haskell Wiki on MonadPlus] (note that this debate long predates the existence of <code>Alternative</code>).
* [http://stackoverflow.com/q/10167879/2751851 ''Distinction between typeclasses MonadPlus, Alternative, and Monoid?''] and [http://stackoverflow.com/q/13080606/2751851 ''Confused by the meaning of the 'Alternative' type class and its relationship to other type classes''] at Stack Overflow (detailed overviews of the ''status quo'' reflected by the documentation of the relevant libraries as of GHC 7.x/8.x − as opposed to the 2010 Haskell Report, which is less prescriptive on this matter.)
* [https://lirias.kuleuven.be/handle/123456789/499951 ''From monoids to near-semirings: the essence of MonadPlus and Alternative'' by Rivas, Jaskelioff and Schrijvers] (a formulation that includes, beyond the monoid laws, right distribution and right absorption for <code>Alternative</code>, as well as left zero and left distribution for <code>MonadPlus</code>).
* [http://winterkoninkje.dreamwidth.org/90905.html Wren Romano on MonadPlus and seminearrings] (argues that the <code>MonadPlus</code> right zero law is too strong).
* [http://okmij.org/ftp/Computation/monads.html#monadplus Oleg Kiselyov on the MonadPlus laws] (argues against the monoid laws in the case of non-determinism monads).
* [http://stackoverflow.com/q/15722906/2751851 ''Must mplus always be associative?'' at Stack Overflow] (a discussion about the merits of the monoid laws of <code>MonadPlus</code>).
{{Haskell/Navigation|chapter=Monads}}
{{BookCat}}
fdbopmrb7qmffjpemp3w5bsa5vb3vqa
Haskell/Pattern matching
0
81100
4675935
4485968
2026-10-13T23:53:01Z
~2026-54868-50
3628373
4675935
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Elementary Haskell}}
In the previous modules, we introduced and made occasional reference to pattern matching. Now that we have developed some familiarity with the language, it is time to take a proper, deeper look. We will kick-start the discussion with a condensed description, which we will expand upon throughout the chapter:
''In pattern matching, we attempt to '''match''' values against '''patterns''' and, if so desired, '''bind''' variables to successful matches''.
== Analysing pattern matching ==
Pattern matching is virtually everywhere. For example, consider this definition of <code>map</code>:
<syntaxhighlight lang="haskell">
map _ [] = []
map f (x:xs) = f x : map f xs
</syntaxhighlight>
At surface level, there are four different patterns involved, two per equation.
* <code>f</code> is a pattern which matches ''anything at all'', and binds the <code>f</code> variable to whatever is matched.
* <code>(x:xs)</code> is a pattern that matches a ''non-empty list'' which is formed by something (which gets bound to the <code>x</code> variable) which was cons'd (by the <code>(:)</code> function) onto something else (which gets bound to <code>xs</code>).
* <code>[]</code> is a pattern that matches ''the empty list''. It doesn't bind any variables.
* <code>_</code> is the pattern which matches anything without binding (wildcard, "don't care" pattern).
In the <code>(x:xs)</code> pattern, <code>x</code> and <code>xs</code> can be seen as sub-patterns used to match the parts of the list. Just like <code>f</code>, they match anything - though it is evident that if there is a successful match and <code>x</code> has type <code>a</code>, <code>xs</code> will have type <code>[a]</code>. Finally, these considerations imply that <code>xs</code> will also match an empty list, and so a one-element list matches <code>(x:xs)</code>.
From the above dissection, we can say pattern matching gives us a way to:
* ''recognize values''. For instance, when <code>map</code> is called and the second argument matches <code>[]</code> the first equation for <code>map</code> is used instead of the second one.
* ''bind variables'' to the recognized values. In this case, the variables <code>f</code>, <code>x</code>, and <code>xs</code> are assigned to the values passed as arguments to <code>map</code> when the second equation is used, and so we can use these values through the variables in the right-hand side of <code>=</code>. As <code>_</code> and <code>[]</code> show, binding is not an essential part of pattern matching, but just a side effect of using variable names as patterns.
* ''break down values into parts'', as the <code>(x:xs)</code> pattern does by binding two variables to parts (head and tail) of a matched argument (the non-empty list).
==The connection with constructors==
Despite the detailed analysis above, it may seem a little too magical how we break down a list as if we were undoing the effects of the <code>(:)</code> operator. Be careful: this process will not work with any arbitrary operator. For example, one might think of defining a function which uses <code>(++)</code> to chop off the first three elements of a list:
<syntaxhighlight lang="haskell">
dropThree ([x,y,z] ++ xs) = xs
</syntaxhighlight>
But that ''will not work''. The function <code>(++)</code> is not allowed in patterns. In fact, most other functions that act on lists are similarly prohibited from pattern matching. Which functions, then, ''are'' allowed?
In one word, ''constructors'' – the functions used to build values of algebraic data types. Let us consider a random example:
<syntaxhighlight lang="haskell">
data Foo = Bar | Baz Int
</syntaxhighlight>
Here <code>Bar</code> and <code>Baz</code> are constructors for the type <code>Foo</code>. You ''can'' use them for pattern matching <code>Foo</code> values and bind variables to the <code>Int</code> value contained in a <code>Foo</code> constructed with <code>Baz</code>:
<syntaxhighlight lang="haskell">
f :: Foo -> Int
f Bar = 1
f (Baz x) = x - 1
</syntaxhighlight>
This is exactly like <code>showAnniversary</code> and <code>showDate</code> in the Type declarations module. For instance:
<syntaxhighlight lang="haskell">
data Date = Date Int Int Int -- Year, Month, Day
showDate :: Date -> String
showDate (Date y m d) = show y ++ "-" ++ show m ++ "-" ++ show d
</syntaxhighlight>
The <code>(Date y m d)</code> pattern in the left-hand side of the <code>showDate</code> definition matches a <code>Date</code> (built with the <code>Date</code> constructor) and binds the variables <code>y</code>, <code>m</code> and <code>d</code> to the contents of the <code>Date</code> value.
===Why does it work with lists?===
As for lists, they are no different from <code>data</code>-defined algebraic data types as far as pattern matching is concerned. It works as if lists were defined with this <code>data</code> declaration (note that the following isn't actually valid syntax: lists are actually too deeply ingrained into Haskell to be defined like this):
<syntaxhighlight lang="haskell">
data [a] = [] | a : [a]
</syntaxhighlight>
So the empty list, <code>[]</code> and the <code>(:)</code> function are constructors of the list datatype, and so you can pattern match with them. <code>[]</code> takes no arguments, and therefore no variables can be bound when it is used for pattern matching. <code>(:)</code> takes two arguments, the list head and tail, which may then have variables bound to them when the pattern is recognized. (This might seem odd if you slipped into thinking that : adds to a list. It doesn’t- it constructs a new list and the old one remains unchanged.)
<pre>
Prelude> :t []
[] :: [a]
Prelude> :t (:)
(:) :: a -> [a] -> [a]
</pre>
Furthermore, since <code>[x, y, z]</code> is just syntactic sugar for <code>x:y:z:[]</code>, we can achieve something like <code>dropThree</code> using pattern matching alone:
<syntaxhighlight lang="haskell">
dropThree :: [a] -> [a]
dropThree (_:_:_:xs) = xs
dropThree _ = []
</syntaxhighlight>
The first pattern will match any list with at least three elements. The catch-all second definition provides a reasonable default<ref>Reasonable ''for this particular task'', and only because it makes sense to expect that <code>dropThree</code> will give <code>[]</code> when applied to a list of, say, two elements. With a different problem, it might not be reasonable to return ''any'' list if the first match failed. In a later chapter, we will consider one simple way of dealing with such cases.</ref> when lists fail to match the main pattern, and thus prevents runtime crashes due to pattern match failure.
{{body note|
From the fact that we ''could'' write a <code>dropThree</code> function with bare pattern matching it doesn't follow that we ''should'' do so! Even though the solution is simple, it is still a waste of effort to code something this specific when we could just use Prelude and settle it with <code>drop 3 xs</code> instead. Mirroring what was said before about baking bare recursive functions, we might say: ''don't get too excited about pattern matching either...''
}}
=== Tuple constructors ===
Analogous considerations are valid for tuples. Our access to their components via pattern matching...
<syntaxhighlight lang="haskell">
fstPlusSnd :: (Num a) => (a, a) -> a
fstPlusSnd (x, y) = x + y
norm3D :: (Floating a) => (a, a, a) -> a
norm3D (x, y, z) = sqrt (x^2 + y^2 + z^2)
</syntaxhighlight>
... is granted by the existence of tuple constructors. For pairs, the constructor is the comma operator, <code>(,)</code>; for larger tuples there are <code>(,,)</code>; <code>(,,,)</code> and so on. These operators are slightly unusual in that we can't use them infix in the regular way; so <code>5 , 3</code> is not a valid way to write <code>(5, 3)</code>. All of them, however, can be used prefix, which is occasionally useful.
<pre>
Prelude> (,) 5 3
(5,3)
Prelude> (,,,) "George" "John" "Paul" "Ringo"
("George","John","Paul","Ringo")
</pre>
== Matching literal values ==
As discussed earlier in the book, a simple piece-wise function definition like this one
<syntaxhighlight lang="haskell">
f :: Int -> Int
f 0 = 1
f 1 = 5
f 2 = 2
f _ = -1
</syntaxhighlight>
is performing pattern matching as well, matching the argument of <code>f</code> with the <code>Int</code> literals 0, 1 and 2, and finally with <code>_</code> . In general, numeric and character literals can be used in pattern matching on their own<ref>As perhaps could be expected, this kind of matching with literals is not constructor-based. Rather, there is an equality comparison behind the scenes</ref> as well as together with constructor patterns. For instance, this function
<syntaxhighlight lang="haskell">
g :: [Int] -> Bool
g (0:[]) = False
g (0:xs) = True
g _ = False
</syntaxhighlight>
will evaluate to False for the [0] list, to True if the list has 0 as first element and a non-empty tail and to False in all other cases. Also, lists with literal elements like [1,2,3], or even "abc" (which is equivalent to ['a','b','c']) can be used for pattern matching as well, since these forms are only syntactic sugar for the (:) constructor.
The above considerations are only valid for literal values, so the following will '''not''' work:
<syntaxhighlight lang="haskell">
k = 1
--again, this won't work as expected
h :: Int -> Bool
h k = True
h _ = False
</syntaxhighlight>
{{Exercises|1=
# Test the flawed <code>h</code> function above in GHCi, with arguments equal to and different from 1. Then, explain what goes wrong.
# In this section about pattern matching with literal values, we made no mention of the boolean values <code>True</code> and <code>False</code>, but we can do pattern matching with them as well, as demonstrated in the [[../Next steps#Introducing pattern matching|Next steps]] chapter. Can you guess why we omitted them? (Hint: is there anything distinctive about the way we write boolean values?)
}}
== Syntax tricks ==
=== As-patterns ===
Sometimes, when matching a sub-pattern within a value, it may be useful to bind a name to the whole value being matched. As-patterns allow exactly this: they are of the form ''<code>var@pattern</code>'' and have the additional effect to bind the name <code>var</code> to the whole value being matched by <code>pattern</code>. For instance, here is a toy variation on the map theme:
<syntaxhighlight lang="haskell">
contrivedMap :: ([a] -> a -> b) -> [a] -> [b]
contrivedMap f [] = []
contrivedMap f list@(x:xs) = f list x : contrivedMap f xs
</syntaxhighlight>
<code>contrivedMap</code> passes to the parameter function <code>f</code> not only <code>x</code> but also the undivided list used as argument of each recursive call. Writing it without as-patterns would have been a bit clunky because we would have to either use <code>head</code> or needlessly ''reconstruct'' the original value of <code>list</code>, i.e. actually evaluate <code>x:xs</code> on the right side:
<syntaxhighlight lang="haskell">
contrivedMap :: ([a] -> a -> b) -> [a] -> [b]
contrivedMap f [] = []
contrivedMap f (x:xs) = f (x:xs) x : contrivedMap f xs
</syntaxhighlight>
{{Exercises|1=
Implement <code>scanr</code>, as in the exercise in [[Haskell/Lists III#Scans|Lists III]], but this time using an as-pattern.
}}
=== Introduction to records ===
For constructors with many elements, ''records'' provide a way of naming values in a datatype using the following syntax:
<syntaxhighlight lang="haskell">
data Foo2 = Bar2 | Baz2 {bazNumber::Int, bazName::String}
</syntaxhighlight>
Using records allows doing matching and binding only for the variables relevant to the function we're writing, making code much clearer:
<syntaxhighlight lang="haskell">
h :: Foo2 -> Int
h Baz2 {bazName=name} = length name
h Bar2 {} = 0
x = Baz2 1 "Haskell" -- construct by declaration order, try ":t Baz2" in GHCi
y = Baz2 {bazName = "Curry", bazNumber = 2} -- construct by name
h x -- 7
h y -- 5
</syntaxhighlight>
Also, the <code>{}</code> pattern can be used for matching a constructor regardless of the datatype elements even if you don't use records in the <code>data</code> declaration:
<syntaxhighlight lang="haskell">
data Foo = Bar | Baz Int
g :: Foo -> Bool
g Bar {} = True
g Baz {} = False
</syntaxhighlight>
The function <code>g</code> does not have to be changed if we modify the number or the type of elements of the constructors <code>Bar</code> or <code>Baz</code>.
There are further advantages to using record syntax which we will cover in more details in the [[../More on datatypes#Named Fields (Record Syntax)|Named fields]] section of the More on datatypes chapter.
== Where we can use pattern matching ==
The short answer is that ''wherever you can bind variables, you can pattern match''. Let us have a glance at such places we have seen before; a few more will be introduced in the following chapters.
=== Equations ===
The most obvious use case is the left-hand side of function definition equations, which were the subject of our examples so far.
<syntaxhighlight lang="haskell">
map _ [] = []
map f (x:xs) = f x : map f xs
</syntaxhighlight>
In the <code>map</code> definition we're doing pattern matching on the left hand side of both equations, and also binding variables on the second one.
==== <code>let</code> expressions and <code>where</code> clauses ====
Both <code>let</code> and <code>where</code> are ways of doing local variable bindings. As such, you can also use pattern matching in them. A simple example:
<syntaxhighlight lang="haskell">
y = let (x:_) = map (*2) [1,2,3]
in x + 5
</syntaxhighlight>
Or, equivalently,
<syntaxhighlight lang="haskell">
y = x + 5
where
(x:_) = map (*2) [1,2,3]
</syntaxhighlight>
Here, <code>x</code> will be bound to the first element of <code>map ((*) 2) [1,2,3]</code>. <code>y</code>, therefore, will evaluate to <math>2 + 5 = 7</math>.
=== Lambda abstractions ===
Pattern matching can be used directly in lambda abstractions:
<syntaxhighlight lang="haskell">
swap = \(x,y) -> (y,x)
</syntaxhighlight>
It is clear, however, that this syntax permits only one pattern (or one for each argument in the case of a multi-argument lambda abstraction).
=== List comprehensions ===
After the <code>|</code> in list comprehensions you can pattern match. This is actually extremely useful, and adds a lot to the expressiveness of comprehensions. Let's see how that works with a slightly more sophisticated example. Prelude provides a <code>Maybe</code> type which has the following constructors:
<syntaxhighlight lang="haskell">
data Maybe a = Nothing | Just a
</syntaxhighlight>
It is typically used to hold values resulting from an operation which may or may not succeed; if the operation succeeds, the <code>Just</code> constructor is used and the value is passed to it; otherwise <code>Nothing</code> is used.<ref>The canonical example of such an operation is looking up values in a ''dictionary'' - which might just be a <code>[(a, b)]</code> list with the tuples being key-value pairs, or a more sophisticated implementation. In any case, if we, given an arbitrary key, try to retrieve a value there is no guarantee we will actually find a value associated to the key.</ref> The utility function <code>catMaybes</code> (which is available from Data.Maybe library module) takes a list of Maybes (which may contain both "Just" and "Nothing" Maybes), and retrieves the contained values by filtering out the <code>Nothing</code> values and getting rid of the <code>Just</code> wrappers of the <code>Just x</code>. Writing it with list comprehensions is very straightforward:
<syntaxhighlight lang="haskell">
catMaybes :: [Maybe a] -> [a]
catMaybes ms = [ x | Just x <- ms ]
</syntaxhighlight>
Another nice thing about using a list comprehension for this task is that if the pattern match fails (that is, it meets a Nothing) it just moves on to the next element in <code>ms</code>, thus avoiding the need of explicitly handling constructors we are not interested in with alternate function definitions.<ref>The reason why it works this way instead of crashing out on a pattern matching failure has to do with the real nature of list comprehensions: They are actually wrappers for the list monad. We will eventually explain what that means when we discuss monads.</ref>
=== <code>do</code> blocks ===
Within a <code>do</code> block like the ones we used in the [[../Simple input and output|Simple input and output]] chapter, we can pattern match with the left-hand side of the left arrow variable bindings:
<syntaxhighlight lang="haskell">
putFirstChar = do
(c:_) <- getLine
putStrLn [c]
</syntaxhighlight>
Furthermore, the <code>let</code> bindings in <code>do</code> blocks are, as far as pattern matching is concerned, just the same as the "real" let expressions.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Elementary Haskell}}
{{BookCat}}
rmuzymcc0thf1nry69v0wx2ha30gwfr
Template:Deleted
10
81169
4675820
1886211
2026-10-13T13:01:35Z
~2026-55040-66
3628329
4675820
wikitext
text/x-wiki
{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{tmbox|text='''{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{{1|{{{page|<noinclude>{{PAGENAME}}</noinclude>}}}}}} was deleted due to {{{2|{{{reason|it not being a [[wikt:textbook|textbook]]}}}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}}}.''' You are welcome to contribute constructively. You can learn how by reading [[Using Wikibooks]]. You can ask any unanswered questions in the [[WB:PROJECTS|project reading room]]. Thanks. {{<includeonly>safesubst:</includeonly>#if:{{{sig|}}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}|<includeonly>~~</includeonly>~~}}}}<noinclude>{{documentation}}</noinclude>
n6rcbecgtwhnt7x4yna78cun6oevmsf
4675821
4675820
2026-10-13T13:01:46Z
Veritas Sapientiae
3399623
Reverted edits by [[Special:Contribs/~2026-55040-66|~2026-55040-66]] ([[User talk:~2026-55040-66|talk]]) to last version by Adrignola: reverting vandalism
1886211
wikitext
text/x-wiki
{{tmbox|text='''{{{1|{{{page|<noinclude>{{PAGENAME}}</noinclude>}}}}}} was deleted due to {{{2|{{{reason|it not being a [[wikt:textbook|textbook]]}}}}}}.''' You are welcome to contribute constructively. You can learn how by reading [[Using Wikibooks]]. You can ask any unanswered questions in the [[WB:PROJECTS|project reading room]]. Thanks. {{<includeonly>safesubst:</includeonly>#if:{{{sig|}}}|<includeonly>~~</includeonly>~~}}}}<noinclude>{{documentation}}</noinclude>
fc4b66bzejtexvcdntuyajfm2ohta41
4675822
4675821
2026-10-13T13:02:13Z
~2026-55040-66
3628329
Undid revision [[Special:Diff/4675821|4675821]] by [[Special:Contributions/Veritas Sapientiae|Veritas Sapientiae]] ([[User talk:Veritas Sapientiae|discuss]])
4675822
wikitext
text/x-wiki
{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{tmbox|text='''{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{{1|{{{page|<noinclude>{{PAGENAME}}</noinclude>}}}}}} was deleted due to {{{2|{{{reason|it not being a [[wikt:textbook|textbook]]}}}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}}}.''' You are welcome to contribute constructively. You can learn how by reading [[Using Wikibooks]]. You can ask any unanswered questions in the [[WB:PROJECTS|project reading room]]. Thanks. {{<includeonly>safesubst:</includeonly>#if:{{{sig|}}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}|<includeonly>~~</includeonly>~~}}}}<noinclude>{{documentation}}</noinclude>
n6rcbecgtwhnt7x4yna78cun6oevmsf
4675823
4675822
2026-10-13T13:02:31Z
Veritas Sapientiae
3399623
Reverted edits by [[Special:Contribs/~2026-55040-66|~2026-55040-66]] ([[User talk:~2026-55040-66|talk]]) to last version by Veritas Sapientiae: reverting vandalism
1886211
wikitext
text/x-wiki
{{tmbox|text='''{{{1|{{{page|<noinclude>{{PAGENAME}}</noinclude>}}}}}} was deleted due to {{{2|{{{reason|it not being a [[wikt:textbook|textbook]]}}}}}}.''' You are welcome to contribute constructively. You can learn how by reading [[Using Wikibooks]]. You can ask any unanswered questions in the [[WB:PROJECTS|project reading room]]. Thanks. {{<includeonly>safesubst:</includeonly>#if:{{{sig|}}}|<includeonly>~~</includeonly>~~}}}}<noinclude>{{documentation}}</noinclude>
fc4b66bzejtexvcdntuyajfm2ohta41
4675826
4675823
2026-10-13T13:03:35Z
~2026-55040-66
3628329
Undid revision [[Special:Diff/4675823|4675823]] by [[Special:Contributions/Veritas Sapientiae|Veritas Sapientiae]] ([[User talk:Veritas Sapientiae|discuss]])
4675826
wikitext
text/x-wiki
{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{tmbox|text='''{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{{1|{{{page|<noinclude>{{PAGENAME}}</noinclude>}}}}}} was deleted due to {{{2|{{{reason|it not being a [[wikt:textbook|textbook]]}}}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}}}.''' You are welcome to contribute constructively. You can learn how by reading [[Using Wikibooks]]. You can ask any unanswered questions in the [[WB:PROJECTS|project reading room]]. Thanks. {{<includeonly>safesubst:</includeonly>#if:{{{sig|}}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}|<includeonly>~~</includeonly>~~}}}}<noinclude>{{documentation}}</noinclude>
n6rcbecgtwhnt7x4yna78cun6oevmsf
4675827
4675826
2026-10-13T13:03:55Z
Veritas Sapientiae
3399623
[[WB:REVERT|Reverted]] edit by [[Special:Contributions/~2026-55040-66|~2026-55040-66]] ([[User talk:~2026-55040-66|talk]]) to last version by Veritas Sapientiae
1886211
wikitext
text/x-wiki
{{tmbox|text='''{{{1|{{{page|<noinclude>{{PAGENAME}}</noinclude>}}}}}} was deleted due to {{{2|{{{reason|it not being a [[wikt:textbook|textbook]]}}}}}}.''' You are welcome to contribute constructively. You can learn how by reading [[Using Wikibooks]]. You can ask any unanswered questions in the [[WB:PROJECTS|project reading room]]. Thanks. {{<includeonly>safesubst:</includeonly>#if:{{{sig|}}}|<includeonly>~~</includeonly>~~}}}}<noinclude>{{documentation}}</noinclude>
fc4b66bzejtexvcdntuyajfm2ohta41
Haskell/Getting set up
0
82126
4675907
4675618
2026-10-13T19:04:58Z
Luciérnaga de conocimiento
3401314
4675907
wikitext
text/x-wiki
== Installing Haskell ==
Haskell is a ''programming language'', i.e. a language in which humans can express how computers should behave. It's like writing a cooking recipe: you write the recipe and the computer executes it.
To use Haskell programs, you need a special program called a Haskell ''compiler''. A compiler takes code written in Haskell and translates it into ''machine code'', a more elementary language that the computer understands. Using the cooking analogy, you write a recipe (your Haskell program) and a cook (a compiler program) does the work of putting together actual ingredients into an edible dish (an executable file). Of course, you can't easily get the recipe from a final dish (and you can't get the Haskell code from the executable after it's compiled).
To get started, visit [https://www.haskell.org/downloads haskell.org/downloads] for the latest instructions. The current recommended way is to use [https://haskell.org/ghcup GHCup]. Use it to install the latest recommended version of GHC, <code>cabal</code> (not <code>stack</code>), and the Haskell language server. You should use <code>cabal</code> to install any Haskell library you need. We will cover using <code>cabal</code> in depth in [[Haskell/Packaging]]
{{body note|1=
Linux users:
'''It is heavily, heavily discouraged to install anything pertaining to Haskell using your system's package repositories and package manager (unless you're using Fedora or NixOS). Specifically distributions like Arch Linux and Debian manage Haskell packages very badly, and will lead to a bad experience with the tooling. Use GHCup and Cabal as noted above.'''
}}
To just test some Haskell basics without downloading and installing, there is a [https://play.haskell.org/ playground] which includes a few packages by default. Most instructions here on the Wikibook will also work on the playground, though it doesn't accept user input.
== First code ==
After installation, we will do our first Haskell coding with the program called '''GHCi''' (the 'i' stands for 'interactive'). Depending on your operating system, perform the following steps:
* On Windows: Click Start, then Run, then type 'cmd' and hit Enter, then type <code>ghci</code> and hit Enter once more.
* On MacOS: Open the application "Terminal" found in the "Applications/Utilities" folder, type the letters <code>ghci</code> into the window that appears, and hit the Enter key.
* On Linux: Open a terminal and run <code>ghci</code>.
You should get output that looks something like the following:
<pre>
GHCi, version 8.10.7: http://www.haskell.org/ghc/ :? for help
Prelude>
</pre>
The first bit is GHCi's version, and tells your how to get help in GHCi. The <code>Prelude></code> bit is known as the ''prompt''. This is where you enter commands, and GHCi will respond with their results. The prompt also tells you that the current loaded module is <code>Prelude</code>, which gives you access to most of the built-in functions.
Now let's try some basic arithmetic:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
Prelude> 5 + 4 * 3
17
Prelude> 2 ^ 5
32
}}
These operators match most other programming languages: <code>+</code> is addition, <code>*</code> is multiplication, and <code>^</code> is exponentiation (raising to the power of, or <math>a ^ b</math>). As shown in the second example, Haskell follows standard order of math operations (e.g. multiplication before addition).
Now you know how to use Haskell as a calculator. Actually, Haskell is ''always'' a calculator — just a really powerful one, able to deal not only with numbers but also with other objects like characters, lists, functions, trees, and even other programs (if you aren't familiar with these terms yet, don't worry).
To leave GHCi once you are done, use <code>:quit</code> (or just <code>:q</code>):
{{Haskell/GHCi|
Prelude> :quit
Leaving GHCi.
}}
GHCi is a powerful development environment. As we progress, we will learn how to load files with source code into GHCi and evaluate different parts of them.
Assuming you're clear on everything so far (if not, use the talk page and help us improve this Wikibook!), then you are ready for the next chapter where we will introduce some of the basic concepts of Haskell and make our first Haskell functions.
{{Haskell/Navigation|chapter=Haskell Basics|noexercises=1}}
{{BookCat}}
ahphnz85606p4a4nb0a89hv55061asw
Template:Haskell/Example
10
84988
4675879
4626901
2026-10-13T17:54:06Z
Luciérnaga de conocimiento
3401314
4675879
wikitext
text/x-wiki
<div style="background: {{{backgroundcolor|transparent}}}; color: {{{foregroundcolor|inherit}}}; margin: 1em 3em">
'''Example:''' {{{1}}}
<div>{{{2}}}</div></div><noinclude><!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentation|content=This template is used for Haskell (source) examples in Haskell books.
If you want do display GHCi transcripts use [[Template:HaskellGHCi]] or [[Template:HaskellGHCiExample]].
This template is also used if you want do display Haskell source code examples; in this
case use the <code><nowiki><syntaxhighlight lang="haskell">...</syntaxhighlight></nowiki></code>
tags as shown below (it's not possible to use a custom template for source code
because wikimedia syntax can't handle <code>{{!}}</code> in template context
which is used by Haskell guards).
Source only example:
<pre><nowiki>
{{Haskell/Example|1=The abs function.|2=<syntaxhighlight lang="haskell">
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>}}
</nowiki></pre>
Is rendered as:
{{HaskellExample|1=The abs function.|2=<syntaxhighlight lang="haskell">
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>}}
Another example:
<pre><nowiki>
{{HaskellExample|1=The signum function.|2=
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0 then
-1
else if x > 0 then
1
else
0
</syntaxhighlight>
You can experiment with this as:
{{HaskellGHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1
}}
}}
</nowiki></pre>
Is rendered as:
{{HaskellExample|1=The signum function.|2=
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0 then
-1
else if x > 0 then
1
else
0
</syntaxhighlight>
You can experiment with this as:
{{HaskellGHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1
}}
}}
The <code>{{!}}1=</code> and <code>{{!}}2=</code> are necessary as the text may contain equal signs. Otherwise just <code>{{{1}}}</code> would get displayed.
}}{{BookCat}}</noinclude>
d8me7hkjy34ilnn1krb2ca5frdgwtm1
4675880
4675879
2026-10-13T17:57:33Z
Luciérnaga de conocimiento
3401314
4675880
wikitext
text/x-wiki
<div style="background: {{{backgroundcolor|transparent}}}; color: {{{foregroundcolor|inherit}}}; margin: 1em 3em">
'''Example:''' {{{1}}}
<div>{{{2}}}</div></div><noinclude><!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentation|content=This template is used for Haskell (source) examples in Haskell books.
If you want do display GHCi transcripts use [[Template:HaskellGHCi]] or [[Template:HaskellGHCiExample]].
This template is also used if you want do display Haskell source code examples; in this
case use the <code><nowiki><syntaxhighlight lang="haskell">...</syntaxhighlight></nowiki></code>
tags as shown below (it's not possible to use a custom template for source code
because wikimedia syntax can't handle <code>{{!}}</code> in template context
which is used by Haskell guards).
Source only example:
<pre><nowiki>
{{Haskell/Example|1=The abs function.|2=<syntaxhighlight lang="haskell">
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>}}
</nowiki></pre>
Is rendered as:
{{HaskellExample|1=The abs function.|2=<syntaxhighlight lang="haskell">
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>}}
Another example:
<pre><nowiki>
{{Haskell/Example|1=The signum function.|2=
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0 then
-1
else if x > 0 then
1
else
0
</syntaxhighlight>
You can experiment with this as:
{{HaskellGHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1
}}
}}
</nowiki></pre>
Is rendered as:
{{Haskell/Example|1=The signum function.|2=
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0 then
-1
else if x > 0 then
1
else
0
</syntaxhighlight>
You can experiment with this as:
{{HaskellGHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1
}}
}}
The <code>{{!}}1=</code> and <code>{{!}}2=</code> are necessary as the text may contain equal signs. Otherwise just <code>{{{1}}}</code> would get displayed.
}}{{BookCat}}</noinclude>
bkabmi4yztijtdnhvnwmrg1l2cvmqpl
4675881
4675880
2026-10-13T17:58:17Z
Luciérnaga de conocimiento
3401314
4675881
wikitext
text/x-wiki
<div style="background: {{{backgroundcolor|transparent}}}; color: {{{foregroundcolor|inherit}}}; margin: 1em 3em">
'''Example:''' {{{1}}}
<div>{{{2}}}</div></div><noinclude><!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentation|content=This template is used for Haskell (source) examples in Haskell books.
If you want do display GHCi transcripts use [[Template:Haskell/GHCi]] or [[Template:HaskellGHCi/Example]].
This template is also used if you want do display Haskell source code examples; in this
case use the <code><nowiki><syntaxhighlight lang="haskell">...</syntaxhighlight></nowiki></code>
tags as shown below (it's not possible to use a custom template for source code
because wikimedia syntax can't handle <code>{{!}}</code> in template context
which is used by Haskell guards).
Source only example:
<pre><nowiki>
{{Haskell/Example|1=The abs function.|2=<syntaxhighlight lang="haskell">
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>}}
</nowiki></pre>
Is rendered as:
{{HaskellExample|1=The abs function.|2=<syntaxhighlight lang="haskell">
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>}}
Another example:
<pre><nowiki>
{{Haskell/Example|1=The signum function.|2=
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0 then
-1
else if x > 0 then
1
else
0
</syntaxhighlight>
You can experiment with this as:
{{HaskellGHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1
}}
}}
</nowiki></pre>
Is rendered as:
{{Haskell/Example|1=The signum function.|2=
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0 then
-1
else if x > 0 then
1
else
0
</syntaxhighlight>
You can experiment with this as:
{{HaskellGHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1
}}
}}
The <code>{{!}}1=</code> and <code>{{!}}2=</code> are necessary as the text may contain equal signs. Otherwise just <code>{{{1}}}</code> would get displayed.
}}{{BookCat}}</noinclude>
meemkcf9fdnocv7ejoet75u3y0u2dw2
4675882
4675881
2026-10-13T17:58:31Z
Luciérnaga de conocimiento
3401314
4675882
wikitext
text/x-wiki
<div style="background: {{{backgroundcolor|transparent}}}; color: {{{foregroundcolor|inherit}}}; margin: 1em 3em">
'''Example:''' {{{1}}}
<div>{{{2}}}</div></div><noinclude><!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentation|content=This template is used for Haskell (source) examples in Haskell books.
If you want do display GHCi transcripts use [[Template:Haskell/GHCi]] or [[Template:Haskell/GHCiExample]].
This template is also used if you want do display Haskell source code examples; in this
case use the <code><nowiki><syntaxhighlight lang="haskell">...</syntaxhighlight></nowiki></code>
tags as shown below (it's not possible to use a custom template for source code
because wikimedia syntax can't handle <code>{{!}}</code> in template context
which is used by Haskell guards).
Source only example:
<pre><nowiki>
{{Haskell/Example|1=The abs function.|2=<syntaxhighlight lang="haskell">
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>}}
</nowiki></pre>
Is rendered as:
{{HaskellExample|1=The abs function.|2=<syntaxhighlight lang="haskell">
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>}}
Another example:
<pre><nowiki>
{{Haskell/Example|1=The signum function.|2=
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0 then
-1
else if x > 0 then
1
else
0
</syntaxhighlight>
You can experiment with this as:
{{HaskellGHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1
}}
}}
</nowiki></pre>
Is rendered as:
{{Haskell/Example|1=The signum function.|2=
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0 then
-1
else if x > 0 then
1
else
0
</syntaxhighlight>
You can experiment with this as:
{{HaskellGHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1
}}
}}
The <code>{{!}}1=</code> and <code>{{!}}2=</code> are necessary as the text may contain equal signs. Otherwise just <code>{{{1}}}</code> would get displayed.
}}{{BookCat}}</noinclude>
28iztyb5zp72r7xew3f8u46ipwoj5fm
4675959
4675882
2026-10-14T00:53:46Z
~2026-54868-50
3628373
4675959
wikitext
text/x-wiki
<div style="background: {{{backgroundcolor|transparent}}}; color: {{{foregroundcolor|inherit}}}; margin: 1em 3em">
'''Example:''' {{{1}}}
<div>{{{2}}}</div></div><noinclude><!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentation|content=This template is used for Haskell (source) examples in Haskell books.
If you want do display GHCi transcripts use [[Template:Haskell/GHCi]] or [[Template:Haskell/GHCiExample]].
This template is also used if you want do display Haskell source code examples; in this
case use the <code><nowiki><syntaxhighlight lang="haskell">...</syntaxhighlight></nowiki></code>
tags as shown below (it's not possible to use a custom template for source code
because wikimedia syntax can't handle <code>{{!}}</code> in template context
which is used by Haskell guards).
Source only example:
<pre><nowiki>
{{Haskell/Example|1=The abs function.|2=<syntaxhighlight lang="haskell">
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>}}
</nowiki></pre>
Is rendered as:
{{Haskell/Example|1=The abs function.|2=<syntaxhighlight lang="haskell">
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>}}
Another example:
<pre><nowiki>
{{Haskell/Example|1=The signum function.|2=
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0 then
-1
else if x > 0 then
1
else
0
</syntaxhighlight>
You can experiment with this as:
{{Haskell/GHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1
}}
}}
</nowiki></pre>
Is rendered as:
{{Haskell/Example|1=The signum function.|2=
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0 then
-1
else if x > 0 then
1
else
0
</syntaxhighlight>
You can experiment with this as:
{{HaskellGHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5-10)
-1
*Main> mySignum (-1)
-1
}}
}}
The <code>{{!}}1=</code> and <code>{{!}}2=</code> are necessary as the text may contain equal signs. Otherwise just <code>{{{1}}}</code> would get displayed.
}}{{BookCat}}</noinclude>
o9behzmgydjkds684rd2xx8fbhitzco
Haskell/Type basics
0
84992
4675872
4666173
2026-10-13T16:58:48Z
Luciérnaga de conocimiento
3401314
4675872
wikitext
text/x-wiki
{{clear}}
{{Haskell minitoc|chapter=Haskell Basics}}
In programming, '''Types''' are used to group similar values into categories. In Haskell, the type system is a powerful way of reducing the number of mistakes in your code.
== Introduction ==
Programming deals with different sorts of entities. For example, consider adding two numbers together:
<math>2 + 3</math>
What are 2 and 3? Well, they are numbers. What about the plus sign in the middle? That's certainly not a number, but it stands for an operation which we can do with two numbers – namely, addition.
Similarly, consider a program that asks you for your name and then greets you with a "Hello" message. Neither your name nor the word Hello are numbers. What are they then? We might refer to all words and sentences and so forth as text. It's normal in programming to use a slightly more esoteric word: ''String'', which is short for "string of characters".
{{side note|Haskell has a rule that all type names have to begin with a capital letter. We shall adhere to this convention henceforth.}}
Databases illustrate clearly the concept of types. For example, say we had a table in a database to store details about a person's contacts; a kind of personal telephone book. The contents might look like this:
{|class="wikitable"
| First Name
| Last Name
| Address
| Telephone number
|-
| Sherlock
| Holmes
| 221B Baker Street London
| 743756
|-
| Bob
| Jones
| 99 Long Road Street Villestown
| 655523
|}
The fields in each entry contain values. <code>Sherlock</code> is a value as is <code>99 Long Road Street Villestown</code> as well as <code>655523</code>. Let's classify the values in this example in terms of types. "First Name" and "Last Name" contain text, so we say that the values are of type String.
At first glance, we might classify address as a String. However, the semantics behind an innocent address are quite complex. Many human conventions dictate how we interpret addresses. For example, if the beginning of the address text contains a number it is likely the number of the house. If not, then it's probably the name of the house – except if it starts with "PO Box", in which case it's just a postal box address and doesn't indicate where the person lives at all. Each part of the address has its own meaning.
In principle, we can indeed say that addresses are Strings, but that doesn't capture many important features of addresses. When we describe something as a String, all that we are saying is that it is a sequence of characters (letters, numbers, etc). Recognizing something as a specialized type is far more meaningful. If we know something is an Address, we instantly know much more about the piece of data – for instance, that we can interpret it using the "human conventions" that give meaning to addresses.
We might also apply this rationale to the telephone numbers. We could specify a TelephoneNumber type. Then, if we were to come across some arbitrary sequence of digits which happened to be of type TelephoneNumber we would have access to a lot more information than if it were just a Number – for instance, we could start looking for things such as area and country codes on the initial digits.
Another reason not to consider the telephone numbers as Numbers is that doing arithmetic with them makes no sense. What is the meaning and expected effect of, say, multiplying a TelephoneNumber by 100? It would not allow calling anyone by phone. Also, each digit comprising a telephone number is important; we cannot accept losing some of them by rounding or even by omitting leading zeros.
=== Why types are useful ===
How does it help us program well to describe and categorize things? Once we define a type, we can specify what we can or cannot do with it. That makes it far easier to manage larger programs and avoid errors.
== Using the interactive <code>:type</code> command ==
Let's explore how types work using GHCi. The type of any expression can be checked with <code>:type</code> (or shortened to <code>:t</code>) command. Try this on the boolean values from the previous module:
{{HaskellGHCiExample|1=Exploring the types of boolean values in GHCi|2=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
The symbol <code>::</code>, which will appear in a couple other places, can be read as simply "is of type", and indicates a ''type signature''.
<code>:type</code> reveals that truth values in Haskell are of type <code>Bool</code>, as illustrated above for the two possible values, <code>True</code> and <code>False</code>, as well as for a sample expression that will evaluate to one of them. Note that boolean values are not just for value comparisons. <code>Bool</code> captures the semantics of a yes/no answer, so it can represent any information of such kind – say, whether a name was found in a spreadsheet, or whether a user has toggled an on/off option.
=== Characters and strings ===
Now let's try <code>:t</code> on something new. Literal characters are entered by enclosing them with single quotation marks. For instance, this is the single letter H:
{{HaskellGHCiExample|1=Using the :type command in GHCi on a literal character|2=
Prelude> :t 'H'
'H' :: Char
}}
So, literal character values have type <code>Char</code> (short for "character"). Now, single quotation marks only work for individual characters, so if we need to enter longer text – that is, a string of characters – we use ''double'' quotation marks instead:
{{HaskellGHCiExample|1=Using the :t command in GHCi on a literal string|2=
Prelude> :t "Hello World"
"Hello World" :: [Char]
}}
Why did we get <code>Char</code> again? The difference is the square brackets. <code>[Char]</code> means a number of characters chained together, forming a ''list'' of characters. Haskell considers all Strings to be lists of characters. Lists in general are important entities in Haskell, and we will cover them in more detail in a little while.
{{Exercises|1=
# Try using <code>:type</code> on the literal value <code>"H"</code> (notice the double quotes). What happens? Why?
# Try using <code>:type</code> on the literal value <code>'Hello World'</code> (notice the single quotes). What happens? Why?}}
Incidentally, Haskell allows for ''type synonyms'', which work pretty much like synonyms in human languages (words that mean the same thing – say, 'big' and 'large'). In Haskell, type synonyms are alternative names for types. For instance, <code>String</code> is defined as a synonym of <code>[Char]</code>, and so we can freely substitute one with the other. Therefore, to say:
<syntaxhighlight lang="haskell">
"Hello World" :: String
</syntaxhighlight>
is also perfectly valid, and in many cases a lot more readable. From here on we'll mostly refer to text values as <code>String</code>, rather than <code>[Char]</code>.
== Functional types ==
So far, we have seen how values (strings, booleans, characters, etc.) have types and how these types help us to categorize and describe them. Now, the big twist that makes Haskell's type system truly powerful: ''Functions'' have types as well.<ref>The deeper truth is that functions ''are'' values, just like all the others.</ref><!-- This stays as just a footnote for the moment --> Let's look at some examples to see how that works.
=== Example: <code>not</code> ===
We can negate boolean values with <code>not</code> (e.g. <code>not True</code> evaluates to <code>False</code> and vice-versa). To figure out the type of a function, we consider two things: the type of values it takes as its input and the type of value it returns. In this example, things are easy. <code>not</code> takes a <code>Bool</code> (the <code>Bool</code> to be negated), and returns a <code>Bool</code> (the negated <code>Bool</code>). The notation for writing that down is:
{{HaskellExample|1=Type signature for <code>not</code>|2=<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>}}
You can read this as "<code>not</code> is a function from things of type <code>Bool</code> to things of type <code>Bool</code>".
Using <code>:t</code> on a function will work just as expected:
{{HaskellGHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
The description of a function's type is in terms of the types of argument(s) it takes and the type of value it evaluates to.
=== Example: <code>chr</code> and <code>ord</code> ===
Text presents a problem to computers. At its lowest level, a computer only knows binary 1s and 0s. To represent text, every character is first converted to a number, then that number is converted to binary and stored. That's how a piece of text (which is just a sequence of characters) is encoded into binary. Normally, we're only interested in how to encode characters into their numerical representations, because the computer takes care of the conversion to binary numbers without our intervention.
The easiest way to convert characters to numbers is simply to write all the possible characters down, then number them. For example, we might decide that 'a' corresponds to 1, then 'b' to 2, and so on. This is what something called the ASCII standard is: take 128 commonly-used characters and number them (ASCII doesn't actually start with 'a', but the general idea is the same). Of course, it would be quite a chore to sit down and look up a character in a big lookup table every time we wanted to encode it, so we've got two functions that do it for us, <code>chr</code> (pronounced 'char') and <code>ord</code><ref>This isn't quite what <code>chr</code> and <code>ord</code> do, but that description fits our purposes well, and it's close enough.</ref>:
{{HaskellExample|1=Type signatures for <code>chr</code> and <code>ord</code>|2=<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>}}
We already know what <code>Char</code> means. The new type on the signatures above, <code>Int</code>, refers to integer numbers, and is one of quite a few different types of numbers.<ref>In fact, it is not even the only type for integers! We will meet its relatives in a short while.</ref> The type signature of <code>chr</code> tells us that it takes an argument of type <code>Int</code>, an integer number, and evaluates to a result of type Char. The converse is the case with <code>ord</code>: It takes things of type Char and returns things of type Int. With the info from the type signatures, it becomes immediately clear which of the functions encodes a character into a numeric code (<code>ord</code>) and which does the decoding back to a character (<code>chr</code>).
To make things more concrete, here are a few examples. Notice that the two functions aren't available by default; so before trying them in GHCi you need to use the <code>:module Data.Char</code> (or <code>:m Data.Char</code>) command to load the Data.Char module where they are defined.
{{HaskellGHCiExample|1=Function calls to <code>chr</code> and <code>ord</code>|2=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Functions with more than one argument ===
What would be the type of a function that takes more than one argument?
{{HaskellExample|1=A function with more than one argument|2=<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
(<code>xor</code> is the exclusive-or function, which evaluates to <code>True</code> if either one or the other argument is <code>True</code>, ''but not both''; and <code>False</code> otherwise.)
The general technique for forming the type of a function that accepts more than one argument is simply to write down all the types of the arguments in a row, in order (so in this case <code>p</code> first then <code>q</code>), then link them all with <code>-></code>. Finally, add the type of the result to the end of the row and stick a final <code>-></code> in just before it.<ref>This method might seem just a trivial hack by now, but actually there are very deep reasons behind it, which we'll cover in the chapter on [[../Higher-order functions|higher-order functions]].</ref> In this example, we have:
<!-- There's a problem with using continuing list numbering, <pre>, and wiki syntax all together -->
<ol>
<li>
Write down the types of the arguments. In this case, the use of <code>(||)</code> and <code>(&&)</code> gives away that <code>p</code> and <code>q</code> have to be of type <code>Bool</code>:
<pre>
Bool Bool
^^ p is a Bool ^^ q is a Bool as well
</pre>
</li>
<li>Fill in the gaps with <code>-></code>:
<pre>Bool -> Bool</pre>
</li>
<li>Add in the result type and a final <code>-></code>. In our case, we're just doing some basic boolean operations so the result remains a Bool.
<pre>
Bool -> Bool -> Bool
^^ We're returning a Bool
^^ This is the extra -> that got added in </pre>
</li>
</ol>
The final signature, then, is:
{{HaskellExample|1=The signature of <code>xor</code>|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>}}
=== Real world example: <code>openWindow</code> ===
{{Side note|side=right|A library is a collection of common code used by many programs.}} As you'll learn in the Haskell in Practice section of the course, one popular group of Haskell libraries are the GUI ('''G'''raphical '''U'''ser '''I'''nterface) ones. These provide functions for dealing with the visual things computer users are familiar with: menus, buttons, application windows, moving the mouse around, etc. One function from one of these libraries is called <code>openWindow</code>, and you can use it to open a new window in your application. For example, say you're writing a word processor, and the user has clicked on the 'Options' button. You need to open a new window which contains all the options that they can change. Let's look at the type signature for this function:<ref>This has been somewhat simplified to fit our purposes. Don't worry, the essence of the function is there.</ref>
{{HaskellExample|1=<code>openWindow</code>|2=<syntaxhighlight lang="haskell">
openWindow :: WindowTitle -> WindowSize -> Window
</syntaxhighlight>}}
You don't know these types, but they're quite simple. All three of the types there, <code>WindowTitle</code>, <code>WindowSize</code> and <code>Window</code> are defined by the GUI library that provides <code>openWindow</code>. As we saw earlier, the two arrows mean that the first two types are the types of the parameters, and the last is the type of the result. <code>WindowTitle</code> holds the title of the window (which typically appears in a title bar at the very top of the window), and <code>WindowSize</code> specifies how big the window should be. The function then returns a value of type <code>Window</code> which represents the actual window.
So, even if you have never seen a function before or don't know how it actually works, a type signature can give you a general idea of what the function does. Make a habit of testing every new function you meet with <code>:t</code>. If you start doing that now, you'll not only learn about the standard library Haskell functions but also develop a useful kind of intuition about functions in Haskell.
{{Exercises|
What are the types of the following functions? For any functions involving numbers, you can just pretend the numbers are Ints.
# The <code>negate</code> function, which takes an Int and returns that Int with its sign swapped. For example, <code><nowiki>negate 4 = -4</nowiki></code>, and <code><nowiki>negate (-2) = 2</nowiki></code> <!-- work around buggy MediaWiki parsing -->
# The <code>({{!}}{{!}})</code> function, pronounced 'or', that takes two Bools and returns a third Bool which is True if either of the arguments were, and False otherwise. <!-- more MediaWiki badness -->
# A <code>monthLength</code> function which takes a Bool which is True if we are considering a leap year and False otherwise, and an Int which is the number of a month; and returns another Int which is the number of days in that month.
# <code><nowiki>f x y = not x && y</nowiki></code>
# <code><nowiki>g x = (2*x - 1)^2</nowiki></code>
}}
== Type signatures in code ==
We have explored the basic theory behind types and how they apply to Haskell. Now, we will see how type signatures are used for annotating functions in source files. Consider the <code>xor</code> function from an earlier example:
{{HaskellExample|1=A function with its signature|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
That is all we have to do. For maximum clarity, type signatures go above the corresponding function definition.
The signatures we add in this way serve a dual role: they clarify the type of the functions both to human readers and to the compiler/interpreter.
=== Type inference ===
If type signatures tell the interpreter (or compiler) about the function type, how did we write our earliest Haskell code without type signatures? Well, when you don't tell Haskell the types of your functions and variables it figures them out through a process called ''type inference''. In essence, the compiler starts with the types of things it knows and then works out the types of the rest of the values. Consider a general example:
{{HaskellExample|1=Simple type inference|2=<syntaxhighlight lang="haskell">
-- We're deliberately not providing a type signature for this function
isL c = c == 'l'
</syntaxhighlight>}}
<code>isL</code> is a function that takes an argument <code>c</code> and returns the result of evaluating <code>c == 'l'</code>. Without a type signature, the type of <code>c</code> and the type of the result are not specified. In the expression <code>c == 'l'</code>, however, the compiler knows that <code>'l'</code> is a <code>Char</code>. Since <code>c</code> and <code>'l'</code> are being compared with equality with <code>(==)</code> and both arguments of <code>(==)</code> must have the same type,<ref>As discussed in [[Haskell/Truth values|Truth values]]. That fact is actually stated by the type signature of <code>(==)</code> – if you are curious you can check it, although you will have to wait a little bit more for a full explanation of the notation used in that.</ref> it follows that <code>c</code> must be a <code>Char</code>. Finally, since <code>isL c</code> is the result of <code>(==)</code> it must be a <code>Bool</code>. And thus we have a signature for the function:
{{HaskellExample|1=<code>isL</code> with a type|2=<syntaxhighlight lang="haskell">
isL :: Char -> Bool
isL c = c == 'l'
</syntaxhighlight>}}
Indeed, if you leave out the type signature, the Haskell compiler will discover it through this process. You can verify that by using <code>:t</code> on <code>isL</code> with or without a signature.
So why write type signatures if they will be inferred anyway? In some cases, the compiler lacks information to infer the type, and so the signature becomes obligatory. In some other cases, we can use a type signature to influence to a certain extent the final type of a function or value. These cases needn't concern us for now, but we have a few other reasons to include type signatures:
* '''Documentation''': type signatures make your code easier to read. With most functions, the name of the function along with the type of the function is sufficient to guess what the function does. Of course, commenting your code helps, but having the types clearly stated helps too.<!-- add a discreet note on Haddock later -->
* '''Debugging''': when you annotate a function with a type signature and then make a typo in the body of the function which changes the type of a variable, the compiler will tell you, ''at compile-time'', that your function is wrong. Leaving off the type signature might allow your erroneous function to compile, and the compiler would assign it the wrong type. You wouldn't know until you ran your program that you made this mistake.
=== Types and readability ===
A somewhat more realistic example will help us understand better how signatures can help documentation. The piece of code quoted below is a tiny ''module'' (modules are the typical way of preparing a library), and this way of organizing code is like that in the libraries bundled with GHC.
{{body note|
Do not go crazy trying to understand how the functions here actually work; that is beside the point as we still have not covered many of the features being used. Just keep reading and play along.
}}
{{HaskellExample|1=Module with type signatures|2=<syntaxhighlight lang="haskell">
module StringManip where
import Data.Char
uppercase, lowercase :: String -> String
uppercase = map toUpper
lowercase = map toLower
capitalize :: String -> String
capitalize x =
let capWord [] = []
capWord (x:xs) = toUpper x : xs
in unwords (map capWord (words x))
</syntaxhighlight>}}
This tiny library provides three string manipulation functions. <code>uppercase</code> converts a string to upper case, <code>lowercase</code> to lower case, and <code>capitalize</code> capitalizes the first letter of every word. Each of these functions takes a <code>String</code> as argument and evaluates to another <code>String</code>. Even if we do not understand how these functions work, looking at the type signatures allows us to immediately know the types of the arguments and return values. Paired with sensible function names, we have enough information to figure out how we can use the functions.
Note that when functions have the same type we have the option of writing just one signature for all of them, by separating their names with commas, as above with <code>uppercase</code> and <code>lowercase</code>.
=== Types prevent errors ===
The role of types in preventing errors is central to typed languages. When passing expressions around you have to make sure the types match up like they did here. If they don't, you'll get ''type errors'' when you try to compile; your program won't pass the ''typecheck''. This helps reduce bugs in your programs. To take a very trivial example:
{{HaskellExample|1=A non-typechecking program|2=<syntaxhighlight lang="haskell">
"hello" + " world" -- type error
</syntaxhighlight>}}
That line will cause a program to fail when compiling. You can't add two strings together. In all likelihood, the programmer intended to use the similar-looking concatenation operator, which can be used to join two strings together into a single one:
{{HaskellExample|1=Our erroneous program, fixed|2=<syntaxhighlight lang="haskell">
"hello" ++ " world" -- "hello world"
</syntaxhighlight>}}
An easy typo to make, but Haskell catches the error when you tried to compile. You don't have to wait until you run the program for the bug to become apparent.
Updating a program commonly involves changes to types. If a change is unintended, or has unforeseen consequences, then it will show up when compiling. Haskell programmers often remark that once they have fixed all the type errors, and their programs compile, that they tend to "just work". The behavior may not always match the intention, but the program won't crash. Haskell has far fewer ''run-time errors'' (where your program goes wrong when you run it rather than when you compile) than other languages.
{{Haskell/NotesSection}}
{{Haskell navigation|chapter=Haskell Basics}}
{{BookCat}}
d1eknv6tksxa8rst1rve6m6ey07kn8n
4675873
4675872
2026-10-13T17:01:27Z
Luciérnaga de conocimiento
3401314
4675873
wikitext
text/x-wiki
{{clear}}
{{Haskell minitoc|chapter=Haskell Basics}}
In programming, '''Types''' are used to group similar values into categories. In Haskell, the type system is a powerful way of reducing the number of mistakes in your code.
== Introduction ==
Programming deals with different sorts of entities. For example, consider adding two numbers together:
<math>2 + 3</math>
What are 2 and 3? Well, they are numbers. What about the plus sign in the middle? That's certainly not a number, but it stands for an operation which we can do with two numbers – namely, addition.
Similarly, consider a program that asks you for your name and then greets you with a "Hello" message. Neither your name nor the word Hello are numbers. What are they then? We might refer to all words and sentences and so forth as text. It's normal in programming to use a slightly more esoteric word: ''String'', which is short for "string of characters".
{{side note|Haskell has a rule that all type names have to begin with a capital letter. We shall adhere to this convention henceforth.}}
Databases illustrate clearly the concept of types. For example, say we had a table in a database to store details about a person's contacts; a kind of personal telephone book. The contents might look like this:
{|class="wikitable"
| First Name
| Last Name
| Address
| Telephone number
|-
| Sherlock
| Holmes
| 221B Baker Street London
| 743756
|-
| Bob
| Jones
| 99 Long Road Street Villestown
| 655523
|}
The fields in each entry contain values. <code>Sherlock</code> is a value as is <code>99 Long Road Street Villestown</code> as well as <code>655523</code>. Let's classify the values in this example in terms of types. "First Name" and "Last Name" contain text, so we say that the values are of type String.
At first glance, we might classify address as a String. However, the semantics behind an innocent address are quite complex. Many human conventions dictate how we interpret addresses. For example, if the beginning of the address text contains a number it is likely the number of the house. If not, then it's probably the name of the house – except if it starts with "PO Box", in which case it's just a postal box address and doesn't indicate where the person lives at all. Each part of the address has its own meaning.
In principle, we can indeed say that addresses are Strings, but that doesn't capture many important features of addresses. When we describe something as a String, all that we are saying is that it is a sequence of characters (letters, numbers, etc). Recognizing something as a specialized type is far more meaningful. If we know something is an Address, we instantly know much more about the piece of data – for instance, that we can interpret it using the "human conventions" that give meaning to addresses.
We might also apply this rationale to the telephone numbers. We could specify a TelephoneNumber type. Then, if we were to come across some arbitrary sequence of digits which happened to be of type TelephoneNumber we would have access to a lot more information than if it were just a Number – for instance, we could start looking for things such as area and country codes on the initial digits.
Another reason not to consider the telephone numbers as Numbers is that doing arithmetic with them makes no sense. What is the meaning and expected effect of, say, multiplying a TelephoneNumber by 100? It would not allow calling anyone by phone. Also, each digit comprising a telephone number is important; we cannot accept losing some of them by rounding or even by omitting leading zeros.
=== Why types are useful ===
How does it help us program well to describe and categorize things? Once we define a type, we can specify what we can or cannot do with it. That makes it far easier to manage larger programs and avoid errors.
== Using the interactive <code>:type</code> command ==
Let's explore how types work using GHCi. The type of any expression can be checked with <code>:type</code> (or shortened to <code>:t</code>) command. Try this on the boolean values from the previous module:
{{Haskell/GHCiExample|1=Exploring the types of boolean values in GHCi|2=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
The symbol <code>::</code>, which will appear in a couple other places, can be read as simply "is of type", and indicates a ''type signature''.
<code>:type</code> reveals that truth values in Haskell are of type <code>Bool</code>, as illustrated above for the two possible values, <code>True</code> and <code>False</code>, as well as for a sample expression that will evaluate to one of them. Note that boolean values are not just for value comparisons. <code>Bool</code> captures the semantics of a yes/no answer, so it can represent any information of such kind – say, whether a name was found in a spreadsheet, or whether a user has toggled an on/off option.
=== Characters and strings ===
Now let's try <code>:t</code> on something new. Literal characters are entered by enclosing them with single quotation marks. For instance, this is the single letter H:
{{Haskell/GHCiExample|1=Using the :type command in GHCi on a literal character|2=
Prelude> :t 'H'
'H' :: Char
}}
So, literal character values have type <code>Char</code> (short for "character"). Now, single quotation marks only work for individual characters, so if we need to enter longer text – that is, a string of characters – we use ''double'' quotation marks instead:
{{Haskell/GHCiExample|1=Using the :t command in GHCi on a literal string|2=
Prelude> :t "Hello World"
"Hello World" :: [Char]
}}
Why did we get <code>Char</code> again? The difference is the square brackets. <code>[Char]</code> means a number of characters chained together, forming a ''list'' of characters. Haskell considers all Strings to be lists of characters. Lists in general are important entities in Haskell, and we will cover them in more detail in a little while.
{{Exercises|1=
# Try using <code>:type</code> on the literal value <code>"H"</code> (notice the double quotes). What happens? Why?
# Try using <code>:type</code> on the literal value <code>'Hello World'</code> (notice the single quotes). What happens? Why?}}
Incidentally, Haskell allows for ''type synonyms'', which work pretty much like synonyms in human languages (words that mean the same thing – say, 'big' and 'large'). In Haskell, type synonyms are alternative names for types. For instance, <code>String</code> is defined as a synonym of <code>[Char]</code>, and so we can freely substitute one with the other. Therefore, to say:
<syntaxhighlight lang="haskell">
"Hello World" :: String
</syntaxhighlight>
is also perfectly valid, and in many cases a lot more readable. From here on we'll mostly refer to text values as <code>String</code>, rather than <code>[Char]</code>.
== Functional types ==
So far, we have seen how values (strings, booleans, characters, etc.) have types and how these types help us to categorize and describe them. Now, the big twist that makes Haskell's type system truly powerful: ''Functions'' have types as well.<ref>The deeper truth is that functions ''are'' values, just like all the others.</ref><!-- This stays as just a footnote for the moment --> Let's look at some examples to see how that works.
=== Example: <code>not</code> ===
We can negate boolean values with <code>not</code> (e.g. <code>not True</code> evaluates to <code>False</code> and vice-versa). To figure out the type of a function, we consider two things: the type of values it takes as its input and the type of value it returns. In this example, things are easy. <code>not</code> takes a <code>Bool</code> (the <code>Bool</code> to be negated), and returns a <code>Bool</code> (the negated <code>Bool</code>). The notation for writing that down is:
{{Haskell/Example|1=Type signature for <code>not</code>|2=<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>}}
You can read this as "<code>not</code> is a function from things of type <code>Bool</code> to things of type <code>Bool</code>".
Using <code>:t</code> on a function will work just as expected:
{{HaskellGHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
The description of a function's type is in terms of the types of argument(s) it takes and the type of value it evaluates to.
=== Example: <code>chr</code> and <code>ord</code> ===
Text presents a problem to computers. At its lowest level, a computer only knows binary 1s and 0s. To represent text, every character is first converted to a number, then that number is converted to binary and stored. That's how a piece of text (which is just a sequence of characters) is encoded into binary. Normally, we're only interested in how to encode characters into their numerical representations, because the computer takes care of the conversion to binary numbers without our intervention.
The easiest way to convert characters to numbers is simply to write all the possible characters down, then number them. For example, we might decide that 'a' corresponds to 1, then 'b' to 2, and so on. This is what something called the ASCII standard is: take 128 commonly-used characters and number them (ASCII doesn't actually start with 'a', but the general idea is the same). Of course, it would be quite a chore to sit down and look up a character in a big lookup table every time we wanted to encode it, so we've got two functions that do it for us, <code>chr</code> (pronounced 'char') and <code>ord</code><ref>This isn't quite what <code>chr</code> and <code>ord</code> do, but that description fits our purposes well, and it's close enough.</ref>:
{{Haskell/Example|1=Type signatures for <code>chr</code> and <code>ord</code>|2=<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>}}
We already know what <code>Char</code> means. The new type on the signatures above, <code>Int</code>, refers to integer numbers, and is one of quite a few different types of numbers.<ref>In fact, it is not even the only type for integers! We will meet its relatives in a short while.</ref> The type signature of <code>chr</code> tells us that it takes an argument of type <code>Int</code>, an integer number, and evaluates to a result of type Char. The converse is the case with <code>ord</code>: It takes things of type Char and returns things of type Int. With the info from the type signatures, it becomes immediately clear which of the functions encodes a character into a numeric code (<code>ord</code>) and which does the decoding back to a character (<code>chr</code>).
To make things more concrete, here are a few examples. Notice that the two functions aren't available by default; so before trying them in GHCi you need to use the <code>:module Data.Char</code> (or <code>:m Data.Char</code>) command to load the Data.Char module where they are defined.
{{Haskell/GHCiExample|1=Function calls to <code>chr</code> and <code>ord</code>|2=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Functions with more than one argument ===
What would be the type of a function that takes more than one argument?
{{Haskell/Example|1=A function with more than one argument|2=<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
(<code>xor</code> is the exclusive-or function, which evaluates to <code>True</code> if either one or the other argument is <code>True</code>, ''but not both''; and <code>False</code> otherwise.)
The general technique for forming the type of a function that accepts more than one argument is simply to write down all the types of the arguments in a row, in order (so in this case <code>p</code> first then <code>q</code>), then link them all with <code>-></code>. Finally, add the type of the result to the end of the row and stick a final <code>-></code> in just before it.<ref>This method might seem just a trivial hack by now, but actually there are very deep reasons behind it, which we'll cover in the chapter on [[../Higher-order functions|higher-order functions]].</ref> In this example, we have:
<!-- There's a problem with using continuing list numbering, <pre>, and wiki syntax all together -->
<ol>
<li>
Write down the types of the arguments. In this case, the use of <code>(||)</code> and <code>(&&)</code> gives away that <code>p</code> and <code>q</code> have to be of type <code>Bool</code>:
<pre>
Bool Bool
^^ p is a Bool ^^ q is a Bool as well
</pre>
</li>
<li>Fill in the gaps with <code>-></code>:
<pre>Bool -> Bool</pre>
</li>
<li>Add in the result type and a final <code>-></code>. In our case, we're just doing some basic boolean operations so the result remains a Bool.
<pre>
Bool -> Bool -> Bool
^^ We're returning a Bool
^^ This is the extra -> that got added in </pre>
</li>
</ol>
The final signature, then, is:
{{Haskell/Example|1=The signature of <code>xor</code>|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>}}
=== Real world example: <code>openWindow</code> ===
{{Side note|side=right|A library is a collection of common code used by many programs.}} As you'll learn in the Haskell in Practice section of the course, one popular group of Haskell libraries are the GUI ('''G'''raphical '''U'''ser '''I'''nterface) ones. These provide functions for dealing with the visual things computer users are familiar with: menus, buttons, application windows, moving the mouse around, etc. One function from one of these libraries is called <code>openWindow</code>, and you can use it to open a new window in your application. For example, say you're writing a word processor, and the user has clicked on the 'Options' button. You need to open a new window which contains all the options that they can change. Let's look at the type signature for this function:<ref>This has been somewhat simplified to fit our purposes. Don't worry, the essence of the function is there.</ref>
{{Haskell/Example|1=<code>openWindow</code>|2=<syntaxhighlight lang="haskell">
openWindow :: WindowTitle -> WindowSize -> Window
</syntaxhighlight>}}
You don't know these types, but they're quite simple. All three of the types there, <code>WindowTitle</code>, <code>WindowSize</code> and <code>Window</code> are defined by the GUI library that provides <code>openWindow</code>. As we saw earlier, the two arrows mean that the first two types are the types of the parameters, and the last is the type of the result. <code>WindowTitle</code> holds the title of the window (which typically appears in a title bar at the very top of the window), and <code>WindowSize</code> specifies how big the window should be. The function then returns a value of type <code>Window</code> which represents the actual window.
So, even if you have never seen a function before or don't know how it actually works, a type signature can give you a general idea of what the function does. Make a habit of testing every new function you meet with <code>:t</code>. If you start doing that now, you'll not only learn about the standard library Haskell functions but also develop a useful kind of intuition about functions in Haskell.
{{Exercises|
What are the types of the following functions? For any functions involving numbers, you can just pretend the numbers are Ints.
# The <code>negate</code> function, which takes an Int and returns that Int with its sign swapped. For example, <code><nowiki>negate 4 = -4</nowiki></code>, and <code><nowiki>negate (-2) = 2</nowiki></code> <!-- work around buggy MediaWiki parsing -->
# The <code>({{!}}{{!}})</code> function, pronounced 'or', that takes two Bools and returns a third Bool which is True if either of the arguments were, and False otherwise. <!-- more MediaWiki badness -->
# A <code>monthLength</code> function which takes a Bool which is True if we are considering a leap year and False otherwise, and an Int which is the number of a month; and returns another Int which is the number of days in that month.
# <code><nowiki>f x y = not x && y</nowiki></code>
# <code><nowiki>g x = (2*x - 1)^2</nowiki></code>
}}
== Type signatures in code ==
We have explored the basic theory behind types and how they apply to Haskell. Now, we will see how type signatures are used for annotating functions in source files. Consider the <code>xor</code> function from an earlier example:
{{Haskell/Example|1=A function with its signature|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
That is all we have to do. For maximum clarity, type signatures go above the corresponding function definition.
The signatures we add in this way serve a dual role: they clarify the type of the functions both to human readers and to the compiler/interpreter.
=== Type inference ===
If type signatures tell the interpreter (or compiler) about the function type, how did we write our earliest Haskell code without type signatures? Well, when you don't tell Haskell the types of your functions and variables it figures them out through a process called ''type inference''. In essence, the compiler starts with the types of things it knows and then works out the types of the rest of the values. Consider a general example:
{{Haskell/Example|1=Simple type inference|2=<syntaxhighlight lang="haskell">
-- We're deliberately not providing a type signature for this function
isL c = c == 'l'
</syntaxhighlight>}}
<code>isL</code> is a function that takes an argument <code>c</code> and returns the result of evaluating <code>c == 'l'</code>. Without a type signature, the type of <code>c</code> and the type of the result are not specified. In the expression <code>c == 'l'</code>, however, the compiler knows that <code>'l'</code> is a <code>Char</code>. Since <code>c</code> and <code>'l'</code> are being compared with equality with <code>(==)</code> and both arguments of <code>(==)</code> must have the same type,<ref>As discussed in [[Haskell/Truth values|Truth values]]. That fact is actually stated by the type signature of <code>(==)</code> – if you are curious you can check it, although you will have to wait a little bit more for a full explanation of the notation used in that.</ref> it follows that <code>c</code> must be a <code>Char</code>. Finally, since <code>isL c</code> is the result of <code>(==)</code> it must be a <code>Bool</code>. And thus we have a signature for the function:
{{Haskell/Example|1=<code>isL</code> with a type|2=<syntaxhighlight lang="haskell">
isL :: Char -> Bool
isL c = c == 'l'
</syntaxhighlight>}}
Indeed, if you leave out the type signature, the Haskell compiler will discover it through this process. You can verify that by using <code>:t</code> on <code>isL</code> with or without a signature.
So why write type signatures if they will be inferred anyway? In some cases, the compiler lacks information to infer the type, and so the signature becomes obligatory. In some other cases, we can use a type signature to influence to a certain extent the final type of a function or value. These cases needn't concern us for now, but we have a few other reasons to include type signatures:
* '''Documentation''': type signatures make your code easier to read. With most functions, the name of the function along with the type of the function is sufficient to guess what the function does. Of course, commenting your code helps, but having the types clearly stated helps too.<!-- add a discreet note on Haddock later -->
* '''Debugging''': when you annotate a function with a type signature and then make a typo in the body of the function which changes the type of a variable, the compiler will tell you, ''at compile-time'', that your function is wrong. Leaving off the type signature might allow your erroneous function to compile, and the compiler would assign it the wrong type. You wouldn't know until you ran your program that you made this mistake.
=== Types and readability ===
A somewhat more realistic example will help us understand better how signatures can help documentation. The piece of code quoted below is a tiny ''module'' (modules are the typical way of preparing a library), and this way of organizing code is like that in the libraries bundled with GHC.
{{body note|
Do not go crazy trying to understand how the functions here actually work; that is beside the point as we still have not covered many of the features being used. Just keep reading and play along.
}}
{{Haskell/Example|1=Module with type signatures|2=<syntaxhighlight lang="haskell">
module StringManip where
import Data.Char
uppercase, lowercase :: String -> String
uppercase = map toUpper
lowercase = map toLower
capitalize :: String -> String
capitalize x =
let capWord [] = []
capWord (x:xs) = toUpper x : xs
in unwords (map capWord (words x))
</syntaxhighlight>}}
This tiny library provides three string manipulation functions. <code>uppercase</code> converts a string to upper case, <code>lowercase</code> to lower case, and <code>capitalize</code> capitalizes the first letter of every word. Each of these functions takes a <code>String</code> as argument and evaluates to another <code>String</code>. Even if we do not understand how these functions work, looking at the type signatures allows us to immediately know the types of the arguments and return values. Paired with sensible function names, we have enough information to figure out how we can use the functions.
Note that when functions have the same type we have the option of writing just one signature for all of them, by separating their names with commas, as above with <code>uppercase</code> and <code>lowercase</code>.
=== Types prevent errors ===
The role of types in preventing errors is central to typed languages. When passing expressions around you have to make sure the types match up like they did here. If they don't, you'll get ''type errors'' when you try to compile; your program won't pass the ''typecheck''. This helps reduce bugs in your programs. To take a very trivial example:
{{Haskell/Example|1=A non-typechecking program|2=<syntaxhighlight lang="haskell">
"hello" + " world" -- type error
</syntaxhighlight>}}
That line will cause a program to fail when compiling. You can't add two strings together. In all likelihood, the programmer intended to use the similar-looking concatenation operator, which can be used to join two strings together into a single one:
{{Haskell/Example|1=Our erroneous program, fixed|2=<syntaxhighlight lang="haskell">
"hello" ++ " world" -- "hello world"
</syntaxhighlight>}}
An easy typo to make, but Haskell catches the error when you tried to compile. You don't have to wait until you run the program for the bug to become apparent.
Updating a program commonly involves changes to types. If a change is unintended, or has unforeseen consequences, then it will show up when compiling. Haskell programmers often remark that once they have fixed all the type errors, and their programs compile, that they tend to "just work". The behavior may not always match the intention, but the program won't crash. Haskell has far fewer ''run-time errors'' (where your program goes wrong when you run it rather than when you compile) than other languages.
{{Haskell/NotesSection}}
{{Haskell navigation|chapter=Haskell Basics}}
{{BookCat}}
mf3jzdkrzo6xs2dbc4ksyc5vviete9p
4675874
4675873
2026-10-13T17:04:31Z
Luciérnaga de conocimiento
3401314
4675874
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Haskell Basics}}
In programming, '''Types''' are used to group similar values into categories. In Haskell, the type system is a powerful way of reducing the number of mistakes in your code.
== Introduction ==
Programming deals with different sorts of entities. For example, consider adding two numbers together:
<math>2 + 3</math>
What are 2 and 3? Well, they are numbers. What about the plus sign in the middle? That's certainly not a number, but it stands for an operation which we can do with two numbers – namely, addition.
Similarly, consider a program that asks you for your name and then greets you with a "Hello" message. Neither your name nor the word Hello are numbers. What are they then? We might refer to all words and sentences and so forth as text. It's normal in programming to use a slightly more esoteric word: ''String'', which is short for "string of characters".
{{side note|Haskell has a rule that all type names have to begin with a capital letter. We shall adhere to this convention henceforth.}}
Databases illustrate clearly the concept of types. For example, say we had a table in a database to store details about a person's contacts; a kind of personal telephone book. The contents might look like this:
{|class="wikitable"
| First Name
| Last Name
| Address
| Telephone number
|-
| Sherlock
| Holmes
| 221B Baker Street London
| 743756
|-
| Bob
| Jones
| 99 Long Road Street Villestown
| 655523
|}
The fields in each entry contain values. <code>Sherlock</code> is a value as is <code>99 Long Road Street Villestown</code> as well as <code>655523</code>. Let's classify the values in this example in terms of types. "First Name" and "Last Name" contain text, so we say that the values are of type String.
At first glance, we might classify address as a String. However, the semantics behind an innocent address are quite complex. Many human conventions dictate how we interpret addresses. For example, if the beginning of the address text contains a number it is likely the number of the house. If not, then it's probably the name of the house – except if it starts with "PO Box", in which case it's just a postal box address and doesn't indicate where the person lives at all. Each part of the address has its own meaning.
In principle, we can indeed say that addresses are Strings, but that doesn't capture many important features of addresses. When we describe something as a String, all that we are saying is that it is a sequence of characters (letters, numbers, etc). Recognizing something as a specialized type is far more meaningful. If we know something is an Address, we instantly know much more about the piece of data – for instance, that we can interpret it using the "human conventions" that give meaning to addresses.
We might also apply this rationale to the telephone numbers. We could specify a TelephoneNumber type. Then, if we were to come across some arbitrary sequence of digits which happened to be of type TelephoneNumber we would have access to a lot more information than if it were just a Number – for instance, we could start looking for things such as area and country codes on the initial digits.
Another reason not to consider the telephone numbers as Numbers is that doing arithmetic with them makes no sense. What is the meaning and expected effect of, say, multiplying a TelephoneNumber by 100? It would not allow calling anyone by phone. Also, each digit comprising a telephone number is important; we cannot accept losing some of them by rounding or even by omitting leading zeros.
=== Why types are useful ===
How does it help us program well to describe and categorize things? Once we define a type, we can specify what we can or cannot do with it. That makes it far easier to manage larger programs and avoid errors.
== Using the interactive <code>:type</code> command ==
Let's explore how types work using GHCi. The type of any expression can be checked with <code>:type</code> (or shortened to <code>:t</code>) command. Try this on the boolean values from the previous module:
{{Haskell/GHCiExample|1=Exploring the types of boolean values in GHCi|2=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
The symbol <code>::</code>, which will appear in a couple other places, can be read as simply "is of type", and indicates a ''type signature''.
<code>:type</code> reveals that truth values in Haskell are of type <code>Bool</code>, as illustrated above for the two possible values, <code>True</code> and <code>False</code>, as well as for a sample expression that will evaluate to one of them. Note that boolean values are not just for value comparisons. <code>Bool</code> captures the semantics of a yes/no answer, so it can represent any information of such kind – say, whether a name was found in a spreadsheet, or whether a user has toggled an on/off option.
=== Characters and strings ===
Now let's try <code>:t</code> on something new. Literal characters are entered by enclosing them with single quotation marks. For instance, this is the single letter H:
{{Haskell/GHCiExample|1=Using the :type command in GHCi on a literal character|2=
Prelude> :t 'H'
'H' :: Char
}}
So, literal character values have type <code>Char</code> (short for "character"). Now, single quotation marks only work for individual characters, so if we need to enter longer text – that is, a string of characters – we use ''double'' quotation marks instead:
{{Haskell/GHCiExample|1=Using the :t command in GHCi on a literal string|2=
Prelude> :t "Hello World"
"Hello World" :: [Char]
}}
Why did we get <code>Char</code> again? The difference is the square brackets. <code>[Char]</code> means a number of characters chained together, forming a ''list'' of characters. Haskell considers all Strings to be lists of characters. Lists in general are important entities in Haskell, and we will cover them in more detail in a little while.
{{Exercises|1=
# Try using <code>:type</code> on the literal value <code>"H"</code> (notice the double quotes). What happens? Why?
# Try using <code>:type</code> on the literal value <code>'Hello World'</code> (notice the single quotes). What happens? Why?}}
Incidentally, Haskell allows for ''type synonyms'', which work pretty much like synonyms in human languages (words that mean the same thing – say, 'big' and 'large'). In Haskell, type synonyms are alternative names for types. For instance, <code>String</code> is defined as a synonym of <code>[Char]</code>, and so we can freely substitute one with the other. Therefore, to say:
<syntaxhighlight lang="haskell">
"Hello World" :: String
</syntaxhighlight>
is also perfectly valid, and in many cases a lot more readable. From here on we'll mostly refer to text values as <code>String</code>, rather than <code>[Char]</code>.
== Functional types ==
So far, we have seen how values (strings, booleans, characters, etc.) have types and how these types help us to categorize and describe them. Now, the big twist that makes Haskell's type system truly powerful: ''Functions'' have types as well.<ref>The deeper truth is that functions ''are'' values, just like all the others.</ref><!-- This stays as just a footnote for the moment --> Let's look at some examples to see how that works.
=== Example: <code>not</code> ===
We can negate boolean values with <code>not</code> (e.g. <code>not True</code> evaluates to <code>False</code> and vice-versa). To figure out the type of a function, we consider two things: the type of values it takes as its input and the type of value it returns. In this example, things are easy. <code>not</code> takes a <code>Bool</code> (the <code>Bool</code> to be negated), and returns a <code>Bool</code> (the negated <code>Bool</code>). The notation for writing that down is:
{{Haskell/Example|1=Type signature for <code>not</code>|2=<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>}}
You can read this as "<code>not</code> is a function from things of type <code>Bool</code> to things of type <code>Bool</code>".
Using <code>:t</code> on a function will work just as expected:
{{Haskell/GHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
The description of a function's type is in terms of the types of argument(s) it takes and the type of value it evaluates to.
=== Example: <code>chr</code> and <code>ord</code> ===
Text presents a problem to computers. At its lowest level, a computer only knows binary 1s and 0s. To represent text, every character is first converted to a number, then that number is converted to binary and stored. That's how a piece of text (which is just a sequence of characters) is encoded into binary. Normally, we're only interested in how to encode characters into their numerical representations, because the computer takes care of the conversion to binary numbers without our intervention.
The easiest way to convert characters to numbers is simply to write all the possible characters down, then number them. For example, we might decide that 'a' corresponds to 1, then 'b' to 2, and so on. This is what something called the ASCII standard is: take 128 commonly-used characters and number them (ASCII doesn't actually start with 'a', but the general idea is the same). Of course, it would be quite a chore to sit down and look up a character in a big lookup table every time we wanted to encode it, so we've got two functions that do it for us, <code>chr</code> (pronounced 'char') and <code>ord</code><ref>This isn't quite what <code>chr</code> and <code>ord</code> do, but that description fits our purposes well, and it's close enough.</ref>:
{{Haskell/Example|1=Type signatures for <code>chr</code> and <code>ord</code>|2=<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>}}
We already know what <code>Char</code> means. The new type on the signatures above, <code>Int</code>, refers to integer numbers, and is one of quite a few different types of numbers.<ref>In fact, it is not even the only type for integers! We will meet its relatives in a short while.</ref> The type signature of <code>chr</code> tells us that it takes an argument of type <code>Int</code>, an integer number, and evaluates to a result of type Char. The converse is the case with <code>ord</code>: It takes things of type Char and returns things of type Int. With the info from the type signatures, it becomes immediately clear which of the functions encodes a character into a numeric code (<code>ord</code>) and which does the decoding back to a character (<code>chr</code>).
To make things more concrete, here are a few examples. Notice that the two functions aren't available by default; so before trying them in GHCi you need to use the <code>:module Data.Char</code> (or <code>:m Data.Char</code>) command to load the Data.Char module where they are defined.
{{Haskell/GHCiExample|1=Function calls to <code>chr</code> and <code>ord</code>|2=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Functions with more than one argument ===
What would be the type of a function that takes more than one argument?
{{Haskell/Example|1=A function with more than one argument|2=<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
(<code>xor</code> is the exclusive-or function, which evaluates to <code>True</code> if either one or the other argument is <code>True</code>, ''but not both''; and <code>False</code> otherwise.)
The general technique for forming the type of a function that accepts more than one argument is simply to write down all the types of the arguments in a row, in order (so in this case <code>p</code> first then <code>q</code>), then link them all with <code>-></code>. Finally, add the type of the result to the end of the row and stick a final <code>-></code> in just before it.<ref>This method might seem just a trivial hack by now, but actually there are very deep reasons behind it, which we'll cover in the chapter on [[../Higher-order functions|higher-order functions]].</ref> In this example, we have:
<!-- There's a problem with using continuing list numbering, <pre>, and wiki syntax all together -->
<ol>
<li>
Write down the types of the arguments. In this case, the use of <code>(||)</code> and <code>(&&)</code> gives away that <code>p</code> and <code>q</code> have to be of type <code>Bool</code>:
<pre>
Bool Bool
^^ p is a Bool ^^ q is a Bool as well
</pre>
</li>
<li>Fill in the gaps with <code>-></code>:
<pre>Bool -> Bool</pre>
</li>
<li>Add in the result type and a final <code>-></code>. In our case, we're just doing some basic boolean operations so the result remains a Bool.
<pre>
Bool -> Bool -> Bool
^^ We're returning a Bool
^^ This is the extra -> that got added in </pre>
</li>
</ol>
The final signature, then, is:
{{Haskell/Example|1=The signature of <code>xor</code>|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>}}
=== Real world example: <code>openWindow</code> ===
{{Side note|side=right|A library is a collection of common code used by many programs.}} As you'll learn in the Haskell in Practice section of the course, one popular group of Haskell libraries are the GUI ('''G'''raphical '''U'''ser '''I'''nterface) ones. These provide functions for dealing with the visual things computer users are familiar with: menus, buttons, application windows, moving the mouse around, etc. One function from one of these libraries is called <code>openWindow</code>, and you can use it to open a new window in your application. For example, say you're writing a word processor, and the user has clicked on the 'Options' button. You need to open a new window which contains all the options that they can change. Let's look at the type signature for this function:<ref>This has been somewhat simplified to fit our purposes. Don't worry, the essence of the function is there.</ref>
{{Haskell/Example|1=<code>openWindow</code>|2=<syntaxhighlight lang="haskell">
openWindow :: WindowTitle -> WindowSize -> Window
</syntaxhighlight>}}
You don't know these types, but they're quite simple. All three of the types there, <code>WindowTitle</code>, <code>WindowSize</code> and <code>Window</code> are defined by the GUI library that provides <code>openWindow</code>. As we saw earlier, the two arrows mean that the first two types are the types of the parameters, and the last is the type of the result. <code>WindowTitle</code> holds the title of the window (which typically appears in a title bar at the very top of the window), and <code>WindowSize</code> specifies how big the window should be. The function then returns a value of type <code>Window</code> which represents the actual window.
So, even if you have never seen a function before or don't know how it actually works, a type signature can give you a general idea of what the function does. Make a habit of testing every new function you meet with <code>:t</code>. If you start doing that now, you'll not only learn about the standard library Haskell functions but also develop a useful kind of intuition about functions in Haskell.
{{Exercises|
What are the types of the following functions? For any functions involving numbers, you can just pretend the numbers are Ints.
# The <code>negate</code> function, which takes an Int and returns that Int with its sign swapped. For example, <code><nowiki>negate 4 = -4</nowiki></code>, and <code><nowiki>negate (-2) = 2</nowiki></code> <!-- work around buggy MediaWiki parsing -->
# The <code>({{!}}{{!}})</code> function, pronounced 'or', that takes two Bools and returns a third Bool which is True if either of the arguments were, and False otherwise. <!-- more MediaWiki badness -->
# A <code>monthLength</code> function which takes a Bool which is True if we are considering a leap year and False otherwise, and an Int which is the number of a month; and returns another Int which is the number of days in that month.
# <code><nowiki>f x y = not x && y</nowiki></code>
# <code><nowiki>g x = (2*x - 1)^2</nowiki></code>
}}
== Type signatures in code ==
We have explored the basic theory behind types and how they apply to Haskell. Now, we will see how type signatures are used for annotating functions in source files. Consider the <code>xor</code> function from an earlier example:
{{Haskell/Example|1=A function with its signature|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
That is all we have to do. For maximum clarity, type signatures go above the corresponding function definition.
The signatures we add in this way serve a dual role: they clarify the type of the functions both to human readers and to the compiler/interpreter.
=== Type inference ===
If type signatures tell the interpreter (or compiler) about the function type, how did we write our earliest Haskell code without type signatures? Well, when you don't tell Haskell the types of your functions and variables it figures them out through a process called ''type inference''. In essence, the compiler starts with the types of things it knows and then works out the types of the rest of the values. Consider a general example:
{{Haskell/Example|1=Simple type inference|2=<syntaxhighlight lang="haskell">
-- We're deliberately not providing a type signature for this function
isL c = c == 'l'
</syntaxhighlight>}}
<code>isL</code> is a function that takes an argument <code>c</code> and returns the result of evaluating <code>c == 'l'</code>. Without a type signature, the type of <code>c</code> and the type of the result are not specified. In the expression <code>c == 'l'</code>, however, the compiler knows that <code>'l'</code> is a <code>Char</code>. Since <code>c</code> and <code>'l'</code> are being compared with equality with <code>(==)</code> and both arguments of <code>(==)</code> must have the same type,<ref>As discussed in [[Haskell/Truth values|Truth values]]. That fact is actually stated by the type signature of <code>(==)</code> – if you are curious you can check it, although you will have to wait a little bit more for a full explanation of the notation used in that.</ref> it follows that <code>c</code> must be a <code>Char</code>. Finally, since <code>isL c</code> is the result of <code>(==)</code> it must be a <code>Bool</code>. And thus we have a signature for the function:
{{Haskell/Example|1=<code>isL</code> with a type|2=<syntaxhighlight lang="haskell">
isL :: Char -> Bool
isL c = c == 'l'
</syntaxhighlight>}}
Indeed, if you leave out the type signature, the Haskell compiler will discover it through this process. You can verify that by using <code>:t</code> on <code>isL</code> with or without a signature.
So why write type signatures if they will be inferred anyway? In some cases, the compiler lacks information to infer the type, and so the signature becomes obligatory. In some other cases, we can use a type signature to influence to a certain extent the final type of a function or value. These cases needn't concern us for now, but we have a few other reasons to include type signatures:
* '''Documentation''': type signatures make your code easier to read. With most functions, the name of the function along with the type of the function is sufficient to guess what the function does. Of course, commenting your code helps, but having the types clearly stated helps too.<!-- add a discreet note on Haddock later -->
* '''Debugging''': when you annotate a function with a type signature and then make a typo in the body of the function which changes the type of a variable, the compiler will tell you, ''at compile-time'', that your function is wrong. Leaving off the type signature might allow your erroneous function to compile, and the compiler would assign it the wrong type. You wouldn't know until you ran your program that you made this mistake.
=== Types and readability ===
A somewhat more realistic example will help us understand better how signatures can help documentation. The piece of code quoted below is a tiny ''module'' (modules are the typical way of preparing a library), and this way of organizing code is like that in the libraries bundled with GHC.
{{body note|
Do not go crazy trying to understand how the functions here actually work; that is beside the point as we still have not covered many of the features being used. Just keep reading and play along.
}}
{{Haskell/Example|1=Module with type signatures|2=<syntaxhighlight lang="haskell">
module StringManip where
import Data.Char
uppercase, lowercase :: String -> String
uppercase = map toUpper
lowercase = map toLower
capitalize :: String -> String
capitalize x =
let capWord [] = []
capWord (x:xs) = toUpper x : xs
in unwords (map capWord (words x))
</syntaxhighlight>}}
This tiny library provides three string manipulation functions. <code>uppercase</code> converts a string to upper case, <code>lowercase</code> to lower case, and <code>capitalize</code> capitalizes the first letter of every word. Each of these functions takes a <code>String</code> as argument and evaluates to another <code>String</code>. Even if we do not understand how these functions work, looking at the type signatures allows us to immediately know the types of the arguments and return values. Paired with sensible function names, we have enough information to figure out how we can use the functions.
Note that when functions have the same type we have the option of writing just one signature for all of them, by separating their names with commas, as above with <code>uppercase</code> and <code>lowercase</code>.
=== Types prevent errors ===
The role of types in preventing errors is central to typed languages. When passing expressions around you have to make sure the types match up like they did here. If they don't, you'll get ''type errors'' when you try to compile; your program won't pass the ''typecheck''. This helps reduce bugs in your programs. To take a very trivial example:
{{Haskell/Example|1=A non-typechecking program|2=<syntaxhighlight lang="haskell">
"hello" + " world" -- type error
</syntaxhighlight>}}
That line will cause a program to fail when compiling. You can't add two strings together. In all likelihood, the programmer intended to use the similar-looking concatenation operator, which can be used to join two strings together into a single one:
{{Haskell/Example|1=Our erroneous program, fixed|2=<syntaxhighlight lang="haskell">
"hello" ++ " world" -- "hello world"
</syntaxhighlight>}}
An easy typo to make, but Haskell catches the error when you tried to compile. You don't have to wait until you run the program for the bug to become apparent.
Updating a program commonly involves changes to types. If a change is unintended, or has unforeseen consequences, then it will show up when compiling. Haskell programmers often remark that once they have fixed all the type errors, and their programs compile, that they tend to "just work". The behavior may not always match the intention, but the program won't crash. Haskell has far fewer ''run-time errors'' (where your program goes wrong when you run it rather than when you compile) than other languages.
{{Haskell/NotesSection}}
{{Haskell navigation|chapter=Haskell Basics}}
{{BookCat}}
ifom3wollce23pqgdgha23kls4rkger
4675875
4675874
2026-10-13T17:06:33Z
Luciérnaga de conocimiento
3401314
4675875
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Haskell/Haskell Basics}}
In programming, '''Types''' are used to group similar values into categories. In Haskell, the type system is a powerful way of reducing the number of mistakes in your code.
== Introduction ==
Programming deals with different sorts of entities. For example, consider adding two numbers together:
<math>2 + 3</math>
What are 2 and 3? Well, they are numbers. What about the plus sign in the middle? That's certainly not a number, but it stands for an operation which we can do with two numbers – namely, addition.
Similarly, consider a program that asks you for your name and then greets you with a "Hello" message. Neither your name nor the word Hello are numbers. What are they then? We might refer to all words and sentences and so forth as text. It's normal in programming to use a slightly more esoteric word: ''String'', which is short for "string of characters".
{{side note|Haskell has a rule that all type names have to begin with a capital letter. We shall adhere to this convention henceforth.}}
Databases illustrate clearly the concept of types. For example, say we had a table in a database to store details about a person's contacts; a kind of personal telephone book. The contents might look like this:
{|class="wikitable"
| First Name
| Last Name
| Address
| Telephone number
|-
| Sherlock
| Holmes
| 221B Baker Street London
| 743756
|-
| Bob
| Jones
| 99 Long Road Street Villestown
| 655523
|}
The fields in each entry contain values. <code>Sherlock</code> is a value as is <code>99 Long Road Street Villestown</code> as well as <code>655523</code>. Let's classify the values in this example in terms of types. "First Name" and "Last Name" contain text, so we say that the values are of type String.
At first glance, we might classify address as a String. However, the semantics behind an innocent address are quite complex. Many human conventions dictate how we interpret addresses. For example, if the beginning of the address text contains a number it is likely the number of the house. If not, then it's probably the name of the house – except if it starts with "PO Box", in which case it's just a postal box address and doesn't indicate where the person lives at all. Each part of the address has its own meaning.
In principle, we can indeed say that addresses are Strings, but that doesn't capture many important features of addresses. When we describe something as a String, all that we are saying is that it is a sequence of characters (letters, numbers, etc). Recognizing something as a specialized type is far more meaningful. If we know something is an Address, we instantly know much more about the piece of data – for instance, that we can interpret it using the "human conventions" that give meaning to addresses.
We might also apply this rationale to the telephone numbers. We could specify a TelephoneNumber type. Then, if we were to come across some arbitrary sequence of digits which happened to be of type TelephoneNumber we would have access to a lot more information than if it were just a Number – for instance, we could start looking for things such as area and country codes on the initial digits.
Another reason not to consider the telephone numbers as Numbers is that doing arithmetic with them makes no sense. What is the meaning and expected effect of, say, multiplying a TelephoneNumber by 100? It would not allow calling anyone by phone. Also, each digit comprising a telephone number is important; we cannot accept losing some of them by rounding or even by omitting leading zeros.
=== Why types are useful ===
How does it help us program well to describe and categorize things? Once we define a type, we can specify what we can or cannot do with it. That makes it far easier to manage larger programs and avoid errors.
== Using the interactive <code>:type</code> command ==
Let's explore how types work using GHCi. The type of any expression can be checked with <code>:type</code> (or shortened to <code>:t</code>) command. Try this on the boolean values from the previous module:
{{Haskell/GHCiExample|1=Exploring the types of boolean values in GHCi|2=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
The symbol <code>::</code>, which will appear in a couple other places, can be read as simply "is of type", and indicates a ''type signature''.
<code>:type</code> reveals that truth values in Haskell are of type <code>Bool</code>, as illustrated above for the two possible values, <code>True</code> and <code>False</code>, as well as for a sample expression that will evaluate to one of them. Note that boolean values are not just for value comparisons. <code>Bool</code> captures the semantics of a yes/no answer, so it can represent any information of such kind – say, whether a name was found in a spreadsheet, or whether a user has toggled an on/off option.
=== Characters and strings ===
Now let's try <code>:t</code> on something new. Literal characters are entered by enclosing them with single quotation marks. For instance, this is the single letter H:
{{Haskell/GHCiExample|1=Using the :type command in GHCi on a literal character|2=
Prelude> :t 'H'
'H' :: Char
}}
So, literal character values have type <code>Char</code> (short for "character"). Now, single quotation marks only work for individual characters, so if we need to enter longer text – that is, a string of characters – we use ''double'' quotation marks instead:
{{Haskell/GHCiExample|1=Using the :t command in GHCi on a literal string|2=
Prelude> :t "Hello World"
"Hello World" :: [Char]
}}
Why did we get <code>Char</code> again? The difference is the square brackets. <code>[Char]</code> means a number of characters chained together, forming a ''list'' of characters. Haskell considers all Strings to be lists of characters. Lists in general are important entities in Haskell, and we will cover them in more detail in a little while.
{{Exercises|1=
# Try using <code>:type</code> on the literal value <code>"H"</code> (notice the double quotes). What happens? Why?
# Try using <code>:type</code> on the literal value <code>'Hello World'</code> (notice the single quotes). What happens? Why?}}
Incidentally, Haskell allows for ''type synonyms'', which work pretty much like synonyms in human languages (words that mean the same thing – say, 'big' and 'large'). In Haskell, type synonyms are alternative names for types. For instance, <code>String</code> is defined as a synonym of <code>[Char]</code>, and so we can freely substitute one with the other. Therefore, to say:
<syntaxhighlight lang="haskell">
"Hello World" :: String
</syntaxhighlight>
is also perfectly valid, and in many cases a lot more readable. From here on we'll mostly refer to text values as <code>String</code>, rather than <code>[Char]</code>.
== Functional types ==
So far, we have seen how values (strings, booleans, characters, etc.) have types and how these types help us to categorize and describe them. Now, the big twist that makes Haskell's type system truly powerful: ''Functions'' have types as well.<ref>The deeper truth is that functions ''are'' values, just like all the others.</ref><!-- This stays as just a footnote for the moment --> Let's look at some examples to see how that works.
=== Example: <code>not</code> ===
We can negate boolean values with <code>not</code> (e.g. <code>not True</code> evaluates to <code>False</code> and vice-versa). To figure out the type of a function, we consider two things: the type of values it takes as its input and the type of value it returns. In this example, things are easy. <code>not</code> takes a <code>Bool</code> (the <code>Bool</code> to be negated), and returns a <code>Bool</code> (the negated <code>Bool</code>). The notation for writing that down is:
{{Haskell/Example|1=Type signature for <code>not</code>|2=<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>}}
You can read this as "<code>not</code> is a function from things of type <code>Bool</code> to things of type <code>Bool</code>".
Using <code>:t</code> on a function will work just as expected:
{{Haskell/GHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
The description of a function's type is in terms of the types of argument(s) it takes and the type of value it evaluates to.
=== Example: <code>chr</code> and <code>ord</code> ===
Text presents a problem to computers. At its lowest level, a computer only knows binary 1s and 0s. To represent text, every character is first converted to a number, then that number is converted to binary and stored. That's how a piece of text (which is just a sequence of characters) is encoded into binary. Normally, we're only interested in how to encode characters into their numerical representations, because the computer takes care of the conversion to binary numbers without our intervention.
The easiest way to convert characters to numbers is simply to write all the possible characters down, then number them. For example, we might decide that 'a' corresponds to 1, then 'b' to 2, and so on. This is what something called the ASCII standard is: take 128 commonly-used characters and number them (ASCII doesn't actually start with 'a', but the general idea is the same). Of course, it would be quite a chore to sit down and look up a character in a big lookup table every time we wanted to encode it, so we've got two functions that do it for us, <code>chr</code> (pronounced 'char') and <code>ord</code><ref>This isn't quite what <code>chr</code> and <code>ord</code> do, but that description fits our purposes well, and it's close enough.</ref>:
{{Haskell/Example|1=Type signatures for <code>chr</code> and <code>ord</code>|2=<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>}}
We already know what <code>Char</code> means. The new type on the signatures above, <code>Int</code>, refers to integer numbers, and is one of quite a few different types of numbers.<ref>In fact, it is not even the only type for integers! We will meet its relatives in a short while.</ref> The type signature of <code>chr</code> tells us that it takes an argument of type <code>Int</code>, an integer number, and evaluates to a result of type Char. The converse is the case with <code>ord</code>: It takes things of type Char and returns things of type Int. With the info from the type signatures, it becomes immediately clear which of the functions encodes a character into a numeric code (<code>ord</code>) and which does the decoding back to a character (<code>chr</code>).
To make things more concrete, here are a few examples. Notice that the two functions aren't available by default; so before trying them in GHCi you need to use the <code>:module Data.Char</code> (or <code>:m Data.Char</code>) command to load the Data.Char module where they are defined.
{{Haskell/GHCiExample|1=Function calls to <code>chr</code> and <code>ord</code>|2=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Functions with more than one argument ===
What would be the type of a function that takes more than one argument?
{{Haskell/Example|1=A function with more than one argument|2=<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
(<code>xor</code> is the exclusive-or function, which evaluates to <code>True</code> if either one or the other argument is <code>True</code>, ''but not both''; and <code>False</code> otherwise.)
The general technique for forming the type of a function that accepts more than one argument is simply to write down all the types of the arguments in a row, in order (so in this case <code>p</code> first then <code>q</code>), then link them all with <code>-></code>. Finally, add the type of the result to the end of the row and stick a final <code>-></code> in just before it.<ref>This method might seem just a trivial hack by now, but actually there are very deep reasons behind it, which we'll cover in the chapter on [[../Higher-order functions|higher-order functions]].</ref> In this example, we have:
<!-- There's a problem with using continuing list numbering, <pre>, and wiki syntax all together -->
<ol>
<li>
Write down the types of the arguments. In this case, the use of <code>(||)</code> and <code>(&&)</code> gives away that <code>p</code> and <code>q</code> have to be of type <code>Bool</code>:
<pre>
Bool Bool
^^ p is a Bool ^^ q is a Bool as well
</pre>
</li>
<li>Fill in the gaps with <code>-></code>:
<pre>Bool -> Bool</pre>
</li>
<li>Add in the result type and a final <code>-></code>. In our case, we're just doing some basic boolean operations so the result remains a Bool.
<pre>
Bool -> Bool -> Bool
^^ We're returning a Bool
^^ This is the extra -> that got added in </pre>
</li>
</ol>
The final signature, then, is:
{{Haskell/Example|1=The signature of <code>xor</code>|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>}}
=== Real world example: <code>openWindow</code> ===
{{Side note|side=right|A library is a collection of common code used by many programs.}} As you'll learn in the Haskell in Practice section of the course, one popular group of Haskell libraries are the GUI ('''G'''raphical '''U'''ser '''I'''nterface) ones. These provide functions for dealing with the visual things computer users are familiar with: menus, buttons, application windows, moving the mouse around, etc. One function from one of these libraries is called <code>openWindow</code>, and you can use it to open a new window in your application. For example, say you're writing a word processor, and the user has clicked on the 'Options' button. You need to open a new window which contains all the options that they can change. Let's look at the type signature for this function:<ref>This has been somewhat simplified to fit our purposes. Don't worry, the essence of the function is there.</ref>
{{Haskell/Example|1=<code>openWindow</code>|2=<syntaxhighlight lang="haskell">
openWindow :: WindowTitle -> WindowSize -> Window
</syntaxhighlight>}}
You don't know these types, but they're quite simple. All three of the types there, <code>WindowTitle</code>, <code>WindowSize</code> and <code>Window</code> are defined by the GUI library that provides <code>openWindow</code>. As we saw earlier, the two arrows mean that the first two types are the types of the parameters, and the last is the type of the result. <code>WindowTitle</code> holds the title of the window (which typically appears in a title bar at the very top of the window), and <code>WindowSize</code> specifies how big the window should be. The function then returns a value of type <code>Window</code> which represents the actual window.
So, even if you have never seen a function before or don't know how it actually works, a type signature can give you a general idea of what the function does. Make a habit of testing every new function you meet with <code>:t</code>. If you start doing that now, you'll not only learn about the standard library Haskell functions but also develop a useful kind of intuition about functions in Haskell.
{{Exercises|
What are the types of the following functions? For any functions involving numbers, you can just pretend the numbers are Ints.
# The <code>negate</code> function, which takes an Int and returns that Int with its sign swapped. For example, <code><nowiki>negate 4 = -4</nowiki></code>, and <code><nowiki>negate (-2) = 2</nowiki></code> <!-- work around buggy MediaWiki parsing -->
# The <code>({{!}}{{!}})</code> function, pronounced 'or', that takes two Bools and returns a third Bool which is True if either of the arguments were, and False otherwise. <!-- more MediaWiki badness -->
# A <code>monthLength</code> function which takes a Bool which is True if we are considering a leap year and False otherwise, and an Int which is the number of a month; and returns another Int which is the number of days in that month.
# <code><nowiki>f x y = not x && y</nowiki></code>
# <code><nowiki>g x = (2*x - 1)^2</nowiki></code>
}}
== Type signatures in code ==
We have explored the basic theory behind types and how they apply to Haskell. Now, we will see how type signatures are used for annotating functions in source files. Consider the <code>xor</code> function from an earlier example:
{{Haskell/Example|1=A function with its signature|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
That is all we have to do. For maximum clarity, type signatures go above the corresponding function definition.
The signatures we add in this way serve a dual role: they clarify the type of the functions both to human readers and to the compiler/interpreter.
=== Type inference ===
If type signatures tell the interpreter (or compiler) about the function type, how did we write our earliest Haskell code without type signatures? Well, when you don't tell Haskell the types of your functions and variables it figures them out through a process called ''type inference''. In essence, the compiler starts with the types of things it knows and then works out the types of the rest of the values. Consider a general example:
{{Haskell/Example|1=Simple type inference|2=<syntaxhighlight lang="haskell">
-- We're deliberately not providing a type signature for this function
isL c = c == 'l'
</syntaxhighlight>}}
<code>isL</code> is a function that takes an argument <code>c</code> and returns the result of evaluating <code>c == 'l'</code>. Without a type signature, the type of <code>c</code> and the type of the result are not specified. In the expression <code>c == 'l'</code>, however, the compiler knows that <code>'l'</code> is a <code>Char</code>. Since <code>c</code> and <code>'l'</code> are being compared with equality with <code>(==)</code> and both arguments of <code>(==)</code> must have the same type,<ref>As discussed in [[Haskell/Truth values|Truth values]]. That fact is actually stated by the type signature of <code>(==)</code> – if you are curious you can check it, although you will have to wait a little bit more for a full explanation of the notation used in that.</ref> it follows that <code>c</code> must be a <code>Char</code>. Finally, since <code>isL c</code> is the result of <code>(==)</code> it must be a <code>Bool</code>. And thus we have a signature for the function:
{{Haskell/Example|1=<code>isL</code> with a type|2=<syntaxhighlight lang="haskell">
isL :: Char -> Bool
isL c = c == 'l'
</syntaxhighlight>}}
Indeed, if you leave out the type signature, the Haskell compiler will discover it through this process. You can verify that by using <code>:t</code> on <code>isL</code> with or without a signature.
So why write type signatures if they will be inferred anyway? In some cases, the compiler lacks information to infer the type, and so the signature becomes obligatory. In some other cases, we can use a type signature to influence to a certain extent the final type of a function or value. These cases needn't concern us for now, but we have a few other reasons to include type signatures:
* '''Documentation''': type signatures make your code easier to read. With most functions, the name of the function along with the type of the function is sufficient to guess what the function does. Of course, commenting your code helps, but having the types clearly stated helps too.<!-- add a discreet note on Haddock later -->
* '''Debugging''': when you annotate a function with a type signature and then make a typo in the body of the function which changes the type of a variable, the compiler will tell you, ''at compile-time'', that your function is wrong. Leaving off the type signature might allow your erroneous function to compile, and the compiler would assign it the wrong type. You wouldn't know until you ran your program that you made this mistake.
=== Types and readability ===
A somewhat more realistic example will help us understand better how signatures can help documentation. The piece of code quoted below is a tiny ''module'' (modules are the typical way of preparing a library), and this way of organizing code is like that in the libraries bundled with GHC.
{{body note|
Do not go crazy trying to understand how the functions here actually work; that is beside the point as we still have not covered many of the features being used. Just keep reading and play along.
}}
{{Haskell/Example|1=Module with type signatures|2=<syntaxhighlight lang="haskell">
module StringManip where
import Data.Char
uppercase, lowercase :: String -> String
uppercase = map toUpper
lowercase = map toLower
capitalize :: String -> String
capitalize x =
let capWord [] = []
capWord (x:xs) = toUpper x : xs
in unwords (map capWord (words x))
</syntaxhighlight>}}
This tiny library provides three string manipulation functions. <code>uppercase</code> converts a string to upper case, <code>lowercase</code> to lower case, and <code>capitalize</code> capitalizes the first letter of every word. Each of these functions takes a <code>String</code> as argument and evaluates to another <code>String</code>. Even if we do not understand how these functions work, looking at the type signatures allows us to immediately know the types of the arguments and return values. Paired with sensible function names, we have enough information to figure out how we can use the functions.
Note that when functions have the same type we have the option of writing just one signature for all of them, by separating their names with commas, as above with <code>uppercase</code> and <code>lowercase</code>.
=== Types prevent errors ===
The role of types in preventing errors is central to typed languages. When passing expressions around you have to make sure the types match up like they did here. If they don't, you'll get ''type errors'' when you try to compile; your program won't pass the ''typecheck''. This helps reduce bugs in your programs. To take a very trivial example:
{{Haskell/Example|1=A non-typechecking program|2=<syntaxhighlight lang="haskell">
"hello" + " world" -- type error
</syntaxhighlight>}}
That line will cause a program to fail when compiling. You can't add two strings together. In all likelihood, the programmer intended to use the similar-looking concatenation operator, which can be used to join two strings together into a single one:
{{Haskell/Example|1=Our erroneous program, fixed|2=<syntaxhighlight lang="haskell">
"hello" ++ " world" -- "hello world"
</syntaxhighlight>}}
An easy typo to make, but Haskell catches the error when you tried to compile. You don't have to wait until you run the program for the bug to become apparent.
Updating a program commonly involves changes to types. If a change is unintended, or has unforeseen consequences, then it will show up when compiling. Haskell programmers often remark that once they have fixed all the type errors, and their programs compile, that they tend to "just work". The behavior may not always match the intention, but the program won't crash. Haskell has far fewer ''run-time errors'' (where your program goes wrong when you run it rather than when you compile) than other languages.
{{Haskell/NotesSection}}
{{Haskell navigation|chapter=Haskell Basics}}
{{BookCat}}
5jrscz7xdhgr1hws2mcs2idalvh7w98
4675876
4675875
2026-10-13T17:06:49Z
Luciérnaga de conocimiento
3401314
Undid revision [[Special:Diff/4675875|4675875]] by [[Special:Contributions/Luciérnaga de conocimiento|Luciérnaga de conocimiento]] ([[User talk:Luciérnaga de conocimiento|discuss]])
4675876
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Haskell Basics}}
In programming, '''Types''' are used to group similar values into categories. In Haskell, the type system is a powerful way of reducing the number of mistakes in your code.
== Introduction ==
Programming deals with different sorts of entities. For example, consider adding two numbers together:
<math>2 + 3</math>
What are 2 and 3? Well, they are numbers. What about the plus sign in the middle? That's certainly not a number, but it stands for an operation which we can do with two numbers – namely, addition.
Similarly, consider a program that asks you for your name and then greets you with a "Hello" message. Neither your name nor the word Hello are numbers. What are they then? We might refer to all words and sentences and so forth as text. It's normal in programming to use a slightly more esoteric word: ''String'', which is short for "string of characters".
{{side note|Haskell has a rule that all type names have to begin with a capital letter. We shall adhere to this convention henceforth.}}
Databases illustrate clearly the concept of types. For example, say we had a table in a database to store details about a person's contacts; a kind of personal telephone book. The contents might look like this:
{|class="wikitable"
| First Name
| Last Name
| Address
| Telephone number
|-
| Sherlock
| Holmes
| 221B Baker Street London
| 743756
|-
| Bob
| Jones
| 99 Long Road Street Villestown
| 655523
|}
The fields in each entry contain values. <code>Sherlock</code> is a value as is <code>99 Long Road Street Villestown</code> as well as <code>655523</code>. Let's classify the values in this example in terms of types. "First Name" and "Last Name" contain text, so we say that the values are of type String.
At first glance, we might classify address as a String. However, the semantics behind an innocent address are quite complex. Many human conventions dictate how we interpret addresses. For example, if the beginning of the address text contains a number it is likely the number of the house. If not, then it's probably the name of the house – except if it starts with "PO Box", in which case it's just a postal box address and doesn't indicate where the person lives at all. Each part of the address has its own meaning.
In principle, we can indeed say that addresses are Strings, but that doesn't capture many important features of addresses. When we describe something as a String, all that we are saying is that it is a sequence of characters (letters, numbers, etc). Recognizing something as a specialized type is far more meaningful. If we know something is an Address, we instantly know much more about the piece of data – for instance, that we can interpret it using the "human conventions" that give meaning to addresses.
We might also apply this rationale to the telephone numbers. We could specify a TelephoneNumber type. Then, if we were to come across some arbitrary sequence of digits which happened to be of type TelephoneNumber we would have access to a lot more information than if it were just a Number – for instance, we could start looking for things such as area and country codes on the initial digits.
Another reason not to consider the telephone numbers as Numbers is that doing arithmetic with them makes no sense. What is the meaning and expected effect of, say, multiplying a TelephoneNumber by 100? It would not allow calling anyone by phone. Also, each digit comprising a telephone number is important; we cannot accept losing some of them by rounding or even by omitting leading zeros.
=== Why types are useful ===
How does it help us program well to describe and categorize things? Once we define a type, we can specify what we can or cannot do with it. That makes it far easier to manage larger programs and avoid errors.
== Using the interactive <code>:type</code> command ==
Let's explore how types work using GHCi. The type of any expression can be checked with <code>:type</code> (or shortened to <code>:t</code>) command. Try this on the boolean values from the previous module:
{{Haskell/GHCiExample|1=Exploring the types of boolean values in GHCi|2=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
The symbol <code>::</code>, which will appear in a couple other places, can be read as simply "is of type", and indicates a ''type signature''.
<code>:type</code> reveals that truth values in Haskell are of type <code>Bool</code>, as illustrated above for the two possible values, <code>True</code> and <code>False</code>, as well as for a sample expression that will evaluate to one of them. Note that boolean values are not just for value comparisons. <code>Bool</code> captures the semantics of a yes/no answer, so it can represent any information of such kind – say, whether a name was found in a spreadsheet, or whether a user has toggled an on/off option.
=== Characters and strings ===
Now let's try <code>:t</code> on something new. Literal characters are entered by enclosing them with single quotation marks. For instance, this is the single letter H:
{{Haskell/GHCiExample|1=Using the :type command in GHCi on a literal character|2=
Prelude> :t 'H'
'H' :: Char
}}
So, literal character values have type <code>Char</code> (short for "character"). Now, single quotation marks only work for individual characters, so if we need to enter longer text – that is, a string of characters – we use ''double'' quotation marks instead:
{{Haskell/GHCiExample|1=Using the :t command in GHCi on a literal string|2=
Prelude> :t "Hello World"
"Hello World" :: [Char]
}}
Why did we get <code>Char</code> again? The difference is the square brackets. <code>[Char]</code> means a number of characters chained together, forming a ''list'' of characters. Haskell considers all Strings to be lists of characters. Lists in general are important entities in Haskell, and we will cover them in more detail in a little while.
{{Exercises|1=
# Try using <code>:type</code> on the literal value <code>"H"</code> (notice the double quotes). What happens? Why?
# Try using <code>:type</code> on the literal value <code>'Hello World'</code> (notice the single quotes). What happens? Why?}}
Incidentally, Haskell allows for ''type synonyms'', which work pretty much like synonyms in human languages (words that mean the same thing – say, 'big' and 'large'). In Haskell, type synonyms are alternative names for types. For instance, <code>String</code> is defined as a synonym of <code>[Char]</code>, and so we can freely substitute one with the other. Therefore, to say:
<syntaxhighlight lang="haskell">
"Hello World" :: String
</syntaxhighlight>
is also perfectly valid, and in many cases a lot more readable. From here on we'll mostly refer to text values as <code>String</code>, rather than <code>[Char]</code>.
== Functional types ==
So far, we have seen how values (strings, booleans, characters, etc.) have types and how these types help us to categorize and describe them. Now, the big twist that makes Haskell's type system truly powerful: ''Functions'' have types as well.<ref>The deeper truth is that functions ''are'' values, just like all the others.</ref><!-- This stays as just a footnote for the moment --> Let's look at some examples to see how that works.
=== Example: <code>not</code> ===
We can negate boolean values with <code>not</code> (e.g. <code>not True</code> evaluates to <code>False</code> and vice-versa). To figure out the type of a function, we consider two things: the type of values it takes as its input and the type of value it returns. In this example, things are easy. <code>not</code> takes a <code>Bool</code> (the <code>Bool</code> to be negated), and returns a <code>Bool</code> (the negated <code>Bool</code>). The notation for writing that down is:
{{Haskell/Example|1=Type signature for <code>not</code>|2=<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>}}
You can read this as "<code>not</code> is a function from things of type <code>Bool</code> to things of type <code>Bool</code>".
Using <code>:t</code> on a function will work just as expected:
{{Haskell/GHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
The description of a function's type is in terms of the types of argument(s) it takes and the type of value it evaluates to.
=== Example: <code>chr</code> and <code>ord</code> ===
Text presents a problem to computers. At its lowest level, a computer only knows binary 1s and 0s. To represent text, every character is first converted to a number, then that number is converted to binary and stored. That's how a piece of text (which is just a sequence of characters) is encoded into binary. Normally, we're only interested in how to encode characters into their numerical representations, because the computer takes care of the conversion to binary numbers without our intervention.
The easiest way to convert characters to numbers is simply to write all the possible characters down, then number them. For example, we might decide that 'a' corresponds to 1, then 'b' to 2, and so on. This is what something called the ASCII standard is: take 128 commonly-used characters and number them (ASCII doesn't actually start with 'a', but the general idea is the same). Of course, it would be quite a chore to sit down and look up a character in a big lookup table every time we wanted to encode it, so we've got two functions that do it for us, <code>chr</code> (pronounced 'char') and <code>ord</code><ref>This isn't quite what <code>chr</code> and <code>ord</code> do, but that description fits our purposes well, and it's close enough.</ref>:
{{Haskell/Example|1=Type signatures for <code>chr</code> and <code>ord</code>|2=<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>}}
We already know what <code>Char</code> means. The new type on the signatures above, <code>Int</code>, refers to integer numbers, and is one of quite a few different types of numbers.<ref>In fact, it is not even the only type for integers! We will meet its relatives in a short while.</ref> The type signature of <code>chr</code> tells us that it takes an argument of type <code>Int</code>, an integer number, and evaluates to a result of type Char. The converse is the case with <code>ord</code>: It takes things of type Char and returns things of type Int. With the info from the type signatures, it becomes immediately clear which of the functions encodes a character into a numeric code (<code>ord</code>) and which does the decoding back to a character (<code>chr</code>).
To make things more concrete, here are a few examples. Notice that the two functions aren't available by default; so before trying them in GHCi you need to use the <code>:module Data.Char</code> (or <code>:m Data.Char</code>) command to load the Data.Char module where they are defined.
{{Haskell/GHCiExample|1=Function calls to <code>chr</code> and <code>ord</code>|2=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Functions with more than one argument ===
What would be the type of a function that takes more than one argument?
{{Haskell/Example|1=A function with more than one argument|2=<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
(<code>xor</code> is the exclusive-or function, which evaluates to <code>True</code> if either one or the other argument is <code>True</code>, ''but not both''; and <code>False</code> otherwise.)
The general technique for forming the type of a function that accepts more than one argument is simply to write down all the types of the arguments in a row, in order (so in this case <code>p</code> first then <code>q</code>), then link them all with <code>-></code>. Finally, add the type of the result to the end of the row and stick a final <code>-></code> in just before it.<ref>This method might seem just a trivial hack by now, but actually there are very deep reasons behind it, which we'll cover in the chapter on [[../Higher-order functions|higher-order functions]].</ref> In this example, we have:
<!-- There's a problem with using continuing list numbering, <pre>, and wiki syntax all together -->
<ol>
<li>
Write down the types of the arguments. In this case, the use of <code>(||)</code> and <code>(&&)</code> gives away that <code>p</code> and <code>q</code> have to be of type <code>Bool</code>:
<pre>
Bool Bool
^^ p is a Bool ^^ q is a Bool as well
</pre>
</li>
<li>Fill in the gaps with <code>-></code>:
<pre>Bool -> Bool</pre>
</li>
<li>Add in the result type and a final <code>-></code>. In our case, we're just doing some basic boolean operations so the result remains a Bool.
<pre>
Bool -> Bool -> Bool
^^ We're returning a Bool
^^ This is the extra -> that got added in </pre>
</li>
</ol>
The final signature, then, is:
{{Haskell/Example|1=The signature of <code>xor</code>|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>}}
=== Real world example: <code>openWindow</code> ===
{{Side note|side=right|A library is a collection of common code used by many programs.}} As you'll learn in the Haskell in Practice section of the course, one popular group of Haskell libraries are the GUI ('''G'''raphical '''U'''ser '''I'''nterface) ones. These provide functions for dealing with the visual things computer users are familiar with: menus, buttons, application windows, moving the mouse around, etc. One function from one of these libraries is called <code>openWindow</code>, and you can use it to open a new window in your application. For example, say you're writing a word processor, and the user has clicked on the 'Options' button. You need to open a new window which contains all the options that they can change. Let's look at the type signature for this function:<ref>This has been somewhat simplified to fit our purposes. Don't worry, the essence of the function is there.</ref>
{{Haskell/Example|1=<code>openWindow</code>|2=<syntaxhighlight lang="haskell">
openWindow :: WindowTitle -> WindowSize -> Window
</syntaxhighlight>}}
You don't know these types, but they're quite simple. All three of the types there, <code>WindowTitle</code>, <code>WindowSize</code> and <code>Window</code> are defined by the GUI library that provides <code>openWindow</code>. As we saw earlier, the two arrows mean that the first two types are the types of the parameters, and the last is the type of the result. <code>WindowTitle</code> holds the title of the window (which typically appears in a title bar at the very top of the window), and <code>WindowSize</code> specifies how big the window should be. The function then returns a value of type <code>Window</code> which represents the actual window.
So, even if you have never seen a function before or don't know how it actually works, a type signature can give you a general idea of what the function does. Make a habit of testing every new function you meet with <code>:t</code>. If you start doing that now, you'll not only learn about the standard library Haskell functions but also develop a useful kind of intuition about functions in Haskell.
{{Exercises|
What are the types of the following functions? For any functions involving numbers, you can just pretend the numbers are Ints.
# The <code>negate</code> function, which takes an Int and returns that Int with its sign swapped. For example, <code><nowiki>negate 4 = -4</nowiki></code>, and <code><nowiki>negate (-2) = 2</nowiki></code> <!-- work around buggy MediaWiki parsing -->
# The <code>({{!}}{{!}})</code> function, pronounced 'or', that takes two Bools and returns a third Bool which is True if either of the arguments were, and False otherwise. <!-- more MediaWiki badness -->
# A <code>monthLength</code> function which takes a Bool which is True if we are considering a leap year and False otherwise, and an Int which is the number of a month; and returns another Int which is the number of days in that month.
# <code><nowiki>f x y = not x && y</nowiki></code>
# <code><nowiki>g x = (2*x - 1)^2</nowiki></code>
}}
== Type signatures in code ==
We have explored the basic theory behind types and how they apply to Haskell. Now, we will see how type signatures are used for annotating functions in source files. Consider the <code>xor</code> function from an earlier example:
{{Haskell/Example|1=A function with its signature|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
That is all we have to do. For maximum clarity, type signatures go above the corresponding function definition.
The signatures we add in this way serve a dual role: they clarify the type of the functions both to human readers and to the compiler/interpreter.
=== Type inference ===
If type signatures tell the interpreter (or compiler) about the function type, how did we write our earliest Haskell code without type signatures? Well, when you don't tell Haskell the types of your functions and variables it figures them out through a process called ''type inference''. In essence, the compiler starts with the types of things it knows and then works out the types of the rest of the values. Consider a general example:
{{Haskell/Example|1=Simple type inference|2=<syntaxhighlight lang="haskell">
-- We're deliberately not providing a type signature for this function
isL c = c == 'l'
</syntaxhighlight>}}
<code>isL</code> is a function that takes an argument <code>c</code> and returns the result of evaluating <code>c == 'l'</code>. Without a type signature, the type of <code>c</code> and the type of the result are not specified. In the expression <code>c == 'l'</code>, however, the compiler knows that <code>'l'</code> is a <code>Char</code>. Since <code>c</code> and <code>'l'</code> are being compared with equality with <code>(==)</code> and both arguments of <code>(==)</code> must have the same type,<ref>As discussed in [[Haskell/Truth values|Truth values]]. That fact is actually stated by the type signature of <code>(==)</code> – if you are curious you can check it, although you will have to wait a little bit more for a full explanation of the notation used in that.</ref> it follows that <code>c</code> must be a <code>Char</code>. Finally, since <code>isL c</code> is the result of <code>(==)</code> it must be a <code>Bool</code>. And thus we have a signature for the function:
{{Haskell/Example|1=<code>isL</code> with a type|2=<syntaxhighlight lang="haskell">
isL :: Char -> Bool
isL c = c == 'l'
</syntaxhighlight>}}
Indeed, if you leave out the type signature, the Haskell compiler will discover it through this process. You can verify that by using <code>:t</code> on <code>isL</code> with or without a signature.
So why write type signatures if they will be inferred anyway? In some cases, the compiler lacks information to infer the type, and so the signature becomes obligatory. In some other cases, we can use a type signature to influence to a certain extent the final type of a function or value. These cases needn't concern us for now, but we have a few other reasons to include type signatures:
* '''Documentation''': type signatures make your code easier to read. With most functions, the name of the function along with the type of the function is sufficient to guess what the function does. Of course, commenting your code helps, but having the types clearly stated helps too.<!-- add a discreet note on Haddock later -->
* '''Debugging''': when you annotate a function with a type signature and then make a typo in the body of the function which changes the type of a variable, the compiler will tell you, ''at compile-time'', that your function is wrong. Leaving off the type signature might allow your erroneous function to compile, and the compiler would assign it the wrong type. You wouldn't know until you ran your program that you made this mistake.
=== Types and readability ===
A somewhat more realistic example will help us understand better how signatures can help documentation. The piece of code quoted below is a tiny ''module'' (modules are the typical way of preparing a library), and this way of organizing code is like that in the libraries bundled with GHC.
{{body note|
Do not go crazy trying to understand how the functions here actually work; that is beside the point as we still have not covered many of the features being used. Just keep reading and play along.
}}
{{Haskell/Example|1=Module with type signatures|2=<syntaxhighlight lang="haskell">
module StringManip where
import Data.Char
uppercase, lowercase :: String -> String
uppercase = map toUpper
lowercase = map toLower
capitalize :: String -> String
capitalize x =
let capWord [] = []
capWord (x:xs) = toUpper x : xs
in unwords (map capWord (words x))
</syntaxhighlight>}}
This tiny library provides three string manipulation functions. <code>uppercase</code> converts a string to upper case, <code>lowercase</code> to lower case, and <code>capitalize</code> capitalizes the first letter of every word. Each of these functions takes a <code>String</code> as argument and evaluates to another <code>String</code>. Even if we do not understand how these functions work, looking at the type signatures allows us to immediately know the types of the arguments and return values. Paired with sensible function names, we have enough information to figure out how we can use the functions.
Note that when functions have the same type we have the option of writing just one signature for all of them, by separating their names with commas, as above with <code>uppercase</code> and <code>lowercase</code>.
=== Types prevent errors ===
The role of types in preventing errors is central to typed languages. When passing expressions around you have to make sure the types match up like they did here. If they don't, you'll get ''type errors'' when you try to compile; your program won't pass the ''typecheck''. This helps reduce bugs in your programs. To take a very trivial example:
{{Haskell/Example|1=A non-typechecking program|2=<syntaxhighlight lang="haskell">
"hello" + " world" -- type error
</syntaxhighlight>}}
That line will cause a program to fail when compiling. You can't add two strings together. In all likelihood, the programmer intended to use the similar-looking concatenation operator, which can be used to join two strings together into a single one:
{{Haskell/Example|1=Our erroneous program, fixed|2=<syntaxhighlight lang="haskell">
"hello" ++ " world" -- "hello world"
</syntaxhighlight>}}
An easy typo to make, but Haskell catches the error when you tried to compile. You don't have to wait until you run the program for the bug to become apparent.
Updating a program commonly involves changes to types. If a change is unintended, or has unforeseen consequences, then it will show up when compiling. Haskell programmers often remark that once they have fixed all the type errors, and their programs compile, that they tend to "just work". The behavior may not always match the intention, but the program won't crash. Haskell has far fewer ''run-time errors'' (where your program goes wrong when you run it rather than when you compile) than other languages.
{{Haskell/NotesSection}}
{{Haskell navigation|chapter=Haskell Basics}}
{{BookCat}}
ifom3wollce23pqgdgha23kls4rkger
4675877
4675876
2026-10-13T17:09:44Z
Luciérnaga de conocimiento
3401314
4675877
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Haskell Basics}}
In programming, '''Types''' are used to group similar values into categories. In Haskell, the type system is a powerful way of reducing the number of mistakes in your code.
== Introduction ==
Programming deals with different sorts of entities. For example, consider adding two numbers together:
<math>2 + 3</math>
What are 2 and 3? Well, they are numbers. What about the plus sign in the middle? That's certainly not a number, but it stands for an operation which we can do with two numbers – namely, addition.
Similarly, consider a program that asks you for your name and then greets you with a "Hello" message. Neither your name nor the word Hello are numbers. What are they then? We might refer to all words and sentences and so forth as text. It's normal in programming to use a slightly more esoteric word: ''String'', which is short for "string of characters".
{{side note|Haskell has a rule that all type names have to begin with a capital letter. We shall adhere to this convention henceforth.}}
Databases illustrate clearly the concept of types. For example, say we had a table in a database to store details about a person's contacts; a kind of personal telephone book. The contents might look like this:
{|class="wikitable"
| First Name
| Last Name
| Address
| Telephone number
|-
| Sherlock
| Holmes
| 221B Baker Street London
| 743756
|-
| Bob
| Jones
| 99 Long Road Street Villestown
| 655523
|}
The fields in each entry contain values. <code>Sherlock</code> is a value as is <code>99 Long Road Street Villestown</code> as well as <code>655523</code>. Let's classify the values in this example in terms of types. "First Name" and "Last Name" contain text, so we say that the values are of type String.
At first glance, we might classify address as a String. However, the semantics behind an innocent address are quite complex. Many human conventions dictate how we interpret addresses. For example, if the beginning of the address text contains a number it is likely the number of the house. If not, then it's probably the name of the house – except if it starts with "PO Box", in which case it's just a postal box address and doesn't indicate where the person lives at all. Each part of the address has its own meaning.
In principle, we can indeed say that addresses are Strings, but that doesn't capture many important features of addresses. When we describe something as a String, all that we are saying is that it is a sequence of characters (letters, numbers, etc). Recognizing something as a specialized type is far more meaningful. If we know something is an Address, we instantly know much more about the piece of data – for instance, that we can interpret it using the "human conventions" that give meaning to addresses.
We might also apply this rationale to the telephone numbers. We could specify a TelephoneNumber type. Then, if we were to come across some arbitrary sequence of digits which happened to be of type TelephoneNumber we would have access to a lot more information than if it were just a Number – for instance, we could start looking for things such as area and country codes on the initial digits.
Another reason not to consider the telephone numbers as Numbers is that doing arithmetic with them makes no sense. What is the meaning and expected effect of, say, multiplying a TelephoneNumber by 100? It would not allow calling anyone by phone. Also, each digit comprising a telephone number is important; we cannot accept losing some of them by rounding or even by omitting leading zeros.
=== Why types are useful ===
How does it help us program well to describe and categorize things? Once we define a type, we can specify what we can or cannot do with it. That makes it far easier to manage larger programs and avoid errors.
== Using the interactive <code>:type</code> command ==
Let's explore how types work using GHCi. The type of any expression can be checked with <code>:type</code> (or shortened to <code>:t</code>) command. Try this on the boolean values from the previous module:
{{Haskell/GHCiExample|1=Exploring the types of boolean values in GHCi|2=
Prelude> :type True
True :: Bool
Prelude> :type False
False :: Bool
Prelude> :t (3 < 5)
(3 < 5) :: Bool
}}
The symbol <code>::</code>, which will appear in a couple other places, can be read as simply "is of type", and indicates a ''type signature''.
<code>:type</code> reveals that truth values in Haskell are of type <code>Bool</code>, as illustrated above for the two possible values, <code>True</code> and <code>False</code>, as well as for a sample expression that will evaluate to one of them. Note that boolean values are not just for value comparisons. <code>Bool</code> captures the semantics of a yes/no answer, so it can represent any information of such kind – say, whether a name was found in a spreadsheet, or whether a user has toggled an on/off option.
=== Characters and strings ===
Now let's try <code>:t</code> on something new. Literal characters are entered by enclosing them with single quotation marks. For instance, this is the single letter H:
{{Haskell/GHCiExample|1=Using the :type command in GHCi on a literal character|2=
Prelude> :t 'H'
'H' :: Char
}}
So, literal character values have type <code>Char</code> (short for "character"). Now, single quotation marks only work for individual characters, so if we need to enter longer text – that is, a string of characters – we use ''double'' quotation marks instead:
{{Haskell/GHCiExample|1=Using the :t command in GHCi on a literal string|2=
Prelude> :t "Hello World"
"Hello World" :: [Char]
}}
Why did we get <code>Char</code> again? The difference is the square brackets. <code>[Char]</code> means a number of characters chained together, forming a ''list'' of characters. Haskell considers all Strings to be lists of characters. Lists in general are important entities in Haskell, and we will cover them in more detail in a little while.
{{Exercises|1=
# Try using <code>:type</code> on the literal value <code>"H"</code> (notice the double quotes). What happens? Why?
# Try using <code>:type</code> on the literal value <code>'Hello World'</code> (notice the single quotes). What happens? Why?}}
Incidentally, Haskell allows for ''type synonyms'', which work pretty much like synonyms in human languages (words that mean the same thing – say, 'big' and 'large'). In Haskell, type synonyms are alternative names for types. For instance, <code>String</code> is defined as a synonym of <code>[Char]</code>, and so we can freely substitute one with the other. Therefore, to say:
<syntaxhighlight lang="haskell">
"Hello World" :: String
</syntaxhighlight>
is also perfectly valid, and in many cases a lot more readable. From here on we'll mostly refer to text values as <code>String</code>, rather than <code>[Char]</code>.
== Functional types ==
So far, we have seen how values (strings, booleans, characters, etc.) have types and how these types help us to categorize and describe them. Now, the big twist that makes Haskell's type system truly powerful: ''Functions'' have types as well.<ref>The deeper truth is that functions ''are'' values, just like all the others.</ref><!-- This stays as just a footnote for the moment --> Let's look at some examples to see how that works.
=== Example: <code>not</code> ===
We can negate boolean values with <code>not</code> (e.g. <code>not True</code> evaluates to <code>False</code> and vice-versa). To figure out the type of a function, we consider two things: the type of values it takes as its input and the type of value it returns. In this example, things are easy. <code>not</code> takes a <code>Bool</code> (the <code>Bool</code> to be negated), and returns a <code>Bool</code> (the negated <code>Bool</code>). The notation for writing that down is:
{{Haskell/Example|1=Type signature for <code>not</code>|2=<syntaxhighlight lang="haskell">
not :: Bool -> Bool
</syntaxhighlight>}}
You can read this as "<code>not</code> is a function from things of type <code>Bool</code> to things of type <code>Bool</code>".
Using <code>:t</code> on a function will work just as expected:
{{Haskell/GHCi|1=
Prelude> :t not
not :: Bool -> Bool
}}
The description of a function's type is in terms of the types of argument(s) it takes and the type of value it evaluates to.
=== Example: <code>chr</code> and <code>ord</code> ===
Text presents a problem to computers. At its lowest level, a computer only knows binary 1s and 0s. To represent text, every character is first converted to a number, then that number is converted to binary and stored. That's how a piece of text (which is just a sequence of characters) is encoded into binary. Normally, we're only interested in how to encode characters into their numerical representations, because the computer takes care of the conversion to binary numbers without our intervention.
The easiest way to convert characters to numbers is simply to write all the possible characters down, then number them. For example, we might decide that 'a' corresponds to 1, then 'b' to 2, and so on. This is what something called the ASCII standard is: take 128 commonly-used characters and number them (ASCII doesn't actually start with 'a', but the general idea is the same). Of course, it would be quite a chore to sit down and look up a character in a big lookup table every time we wanted to encode it, so we've got two functions that do it for us, <code>chr</code> (pronounced 'char') and <code>ord</code><ref>This isn't quite what <code>chr</code> and <code>ord</code> do, but that description fits our purposes well, and it's close enough.</ref>:
{{Haskell/Example|1=Type signatures for <code>chr</code> and <code>ord</code>|2=<syntaxhighlight lang="haskell">
chr :: Int -> Char
ord :: Char -> Int
</syntaxhighlight>}}
We already know what <code>Char</code> means. The new type on the signatures above, <code>Int</code>, refers to integer numbers, and is one of quite a few different types of numbers.<ref>In fact, it is not even the only type for integers! We will meet its relatives in a short while.</ref> The type signature of <code>chr</code> tells us that it takes an argument of type <code>Int</code>, an integer number, and evaluates to a result of type Char. The converse is the case with <code>ord</code>: It takes things of type Char and returns things of type Int. With the info from the type signatures, it becomes immediately clear which of the functions encodes a character into a numeric code (<code>ord</code>) and which does the decoding back to a character (<code>chr</code>).
To make things more concrete, here are a few examples. Notice that the two functions aren't available by default; so before trying them in GHCi you need to use the <code>:module Data.Char</code> (or <code>:m Data.Char</code>) command to load the Data.Char module where they are defined.
{{Haskell/GHCiExample|1=Function calls to <code>chr</code> and <code>ord</code>|2=
Prelude> :m Data.Char
Prelude Data.Char> chr 97
'a'
Prelude Data.Char> chr 98
'b'
Prelude Data.Char> ord 'c'
99
}}
=== Functions with more than one argument ===
What would be the type of a function that takes more than one argument?
{{Haskell/Example|1=A function with more than one argument|2=<syntaxhighlight lang="haskell">
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
(<code>xor</code> is the exclusive-or function, which evaluates to <code>True</code> if either one or the other argument is <code>True</code>, ''but not both''; and <code>False</code> otherwise.)
The general technique for forming the type of a function that accepts more than one argument is simply to write down all the types of the arguments in a row, in order (so in this case <code>p</code> first then <code>q</code>), then link them all with <code>-></code>. Finally, add the type of the result to the end of the row and stick a final <code>-></code> in just before it.<ref>This method might seem just a trivial hack by now, but actually there are very deep reasons behind it, which we'll cover in the chapter on [[../Higher-order functions|higher-order functions]].</ref> In this example, we have:
<!-- There's a problem with using continuing list numbering, <pre>, and wiki syntax all together -->
<ol>
<li>
Write down the types of the arguments. In this case, the use of <code>(||)</code> and <code>(&&)</code> gives away that <code>p</code> and <code>q</code> have to be of type <code>Bool</code>:
<pre>
Bool Bool
^^ p is a Bool ^^ q is a Bool as well
</pre>
</li>
<li>Fill in the gaps with <code>-></code>:
<pre>Bool -> Bool</pre>
</li>
<li>Add in the result type and a final <code>-></code>. In our case, we're just doing some basic boolean operations so the result remains a Bool.
<pre>
Bool -> Bool -> Bool
^^ We're returning a Bool
^^ This is the extra -> that got added in </pre>
</li>
</ol>
The final signature, then, is:
{{Haskell/Example|1=The signature of <code>xor</code>|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
</syntaxhighlight>}}
=== Real world example: <code>openWindow</code> ===
{{Side note|side=right|A library is a collection of common code used by many programs.}} As you'll learn in the Haskell in Practice section of the course, one popular group of Haskell libraries are the GUI ('''G'''raphical '''U'''ser '''I'''nterface) ones. These provide functions for dealing with the visual things computer users are familiar with: menus, buttons, application windows, moving the mouse around, etc. One function from one of these libraries is called <code>openWindow</code>, and you can use it to open a new window in your application. For example, say you're writing a word processor, and the user has clicked on the 'Options' button. You need to open a new window which contains all the options that they can change. Let's look at the type signature for this function:<ref>This has been somewhat simplified to fit our purposes. Don't worry, the essence of the function is there.</ref>
{{Haskell/Example|1=<code>openWindow</code>|2=<syntaxhighlight lang="haskell">
openWindow :: WindowTitle -> WindowSize -> Window
</syntaxhighlight>}}
You don't know these types, but they're quite simple. All three of the types there, <code>WindowTitle</code>, <code>WindowSize</code> and <code>Window</code> are defined by the GUI library that provides <code>openWindow</code>. As we saw earlier, the two arrows mean that the first two types are the types of the parameters, and the last is the type of the result. <code>WindowTitle</code> holds the title of the window (which typically appears in a title bar at the very top of the window), and <code>WindowSize</code> specifies how big the window should be. The function then returns a value of type <code>Window</code> which represents the actual window.
So, even if you have never seen a function before or don't know how it actually works, a type signature can give you a general idea of what the function does. Make a habit of testing every new function you meet with <code>:t</code>. If you start doing that now, you'll not only learn about the standard library Haskell functions but also develop a useful kind of intuition about functions in Haskell.
{{Exercises|
What are the types of the following functions? For any functions involving numbers, you can just pretend the numbers are Ints.
# The <code>negate</code> function, which takes an Int and returns that Int with its sign swapped. For example, <code><nowiki>negate 4 = -4</nowiki></code>, and <code><nowiki>negate (-2) = 2</nowiki></code> <!-- work around buggy MediaWiki parsing -->
# The <code>({{!}}{{!}})</code> function, pronounced 'or', that takes two Bools and returns a third Bool which is True if either of the arguments were, and False otherwise. <!-- more MediaWiki badness -->
# A <code>monthLength</code> function which takes a Bool which is True if we are considering a leap year and False otherwise, and an Int which is the number of a month; and returns another Int which is the number of days in that month.
# <code><nowiki>f x y = not x && y</nowiki></code>
# <code><nowiki>g x = (2*x - 1)^2</nowiki></code>
}}
== Type signatures in code ==
We have explored the basic theory behind types and how they apply to Haskell. Now, we will see how type signatures are used for annotating functions in source files. Consider the <code>xor</code> function from an earlier example:
{{Haskell/Example|1=A function with its signature|2=<syntaxhighlight lang="haskell">
xor :: Bool -> Bool -> Bool
xor p q = (p || q) && not (p && q)
</syntaxhighlight>}}
That is all we have to do. For maximum clarity, type signatures go above the corresponding function definition.
The signatures we add in this way serve a dual role: they clarify the type of the functions both to human readers and to the compiler/interpreter.
=== Type inference ===
If type signatures tell the interpreter (or compiler) about the function type, how did we write our earliest Haskell code without type signatures? Well, when you don't tell Haskell the types of your functions and variables it figures them out through a process called ''type inference''. In essence, the compiler starts with the types of things it knows and then works out the types of the rest of the values. Consider a general example:
{{Haskell/Example|1=Simple type inference|2=<syntaxhighlight lang="haskell">
-- We're deliberately not providing a type signature for this function
isL c = c == 'l'
</syntaxhighlight>}}
<code>isL</code> is a function that takes an argument <code>c</code> and returns the result of evaluating <code>c == 'l'</code>. Without a type signature, the type of <code>c</code> and the type of the result are not specified. In the expression <code>c == 'l'</code>, however, the compiler knows that <code>'l'</code> is a <code>Char</code>. Since <code>c</code> and <code>'l'</code> are being compared with equality with <code>(==)</code> and both arguments of <code>(==)</code> must have the same type,<ref>As discussed in [[Haskell/Truth values|Truth values]]. That fact is actually stated by the type signature of <code>(==)</code> – if you are curious you can check it, although you will have to wait a little bit more for a full explanation of the notation used in that.</ref> it follows that <code>c</code> must be a <code>Char</code>. Finally, since <code>isL c</code> is the result of <code>(==)</code> it must be a <code>Bool</code>. And thus we have a signature for the function:
{{Haskell/Example|1=<code>isL</code> with a type|2=<syntaxhighlight lang="haskell">
isL :: Char -> Bool
isL c = c == 'l'
</syntaxhighlight>}}
Indeed, if you leave out the type signature, the Haskell compiler will discover it through this process. You can verify that by using <code>:t</code> on <code>isL</code> with or without a signature.
So why write type signatures if they will be inferred anyway? In some cases, the compiler lacks information to infer the type, and so the signature becomes obligatory. In some other cases, we can use a type signature to influence to a certain extent the final type of a function or value. These cases needn't concern us for now, but we have a few other reasons to include type signatures:
* '''Documentation''': type signatures make your code easier to read. With most functions, the name of the function along with the type of the function is sufficient to guess what the function does. Of course, commenting your code helps, but having the types clearly stated helps too.<!-- add a discreet note on Haddock later -->
* '''Debugging''': when you annotate a function with a type signature and then make a typo in the body of the function which changes the type of a variable, the compiler will tell you, ''at compile-time'', that your function is wrong. Leaving off the type signature might allow your erroneous function to compile, and the compiler would assign it the wrong type. You wouldn't know until you ran your program that you made this mistake.
=== Types and readability ===
A somewhat more realistic example will help us understand better how signatures can help documentation. The piece of code quoted below is a tiny ''module'' (modules are the typical way of preparing a library), and this way of organizing code is like that in the libraries bundled with GHC.
{{body note|
Do not go crazy trying to understand how the functions here actually work; that is beside the point as we still have not covered many of the features being used. Just keep reading and play along.
}}
{{Haskell/Example|1=Module with type signatures|2=<syntaxhighlight lang="haskell">
module StringManip where
import Data.Char
uppercase, lowercase :: String -> String
uppercase = map toUpper
lowercase = map toLower
capitalize :: String -> String
capitalize x =
let capWord [] = []
capWord (x:xs) = toUpper x : xs
in unwords (map capWord (words x))
</syntaxhighlight>}}
This tiny library provides three string manipulation functions. <code>uppercase</code> converts a string to upper case, <code>lowercase</code> to lower case, and <code>capitalize</code> capitalizes the first letter of every word. Each of these functions takes a <code>String</code> as argument and evaluates to another <code>String</code>. Even if we do not understand how these functions work, looking at the type signatures allows us to immediately know the types of the arguments and return values. Paired with sensible function names, we have enough information to figure out how we can use the functions.
Note that when functions have the same type we have the option of writing just one signature for all of them, by separating their names with commas, as above with <code>uppercase</code> and <code>lowercase</code>.
=== Types prevent errors ===
The role of types in preventing errors is central to typed languages. When passing expressions around you have to make sure the types match up like they did here. If they don't, you'll get ''type errors'' when you try to compile; your program won't pass the ''typecheck''. This helps reduce bugs in your programs. To take a very trivial example:
{{Haskell/Example|1=A non-typechecking program|2=<syntaxhighlight lang="haskell">
"hello" + " world" -- type error
</syntaxhighlight>}}
That line will cause a program to fail when compiling. You can't add two strings together. In all likelihood, the programmer intended to use the similar-looking concatenation operator, which can be used to join two strings together into a single one:
{{Haskell/Example|1=Our erroneous program, fixed|2=<syntaxhighlight lang="haskell">
"hello" ++ " world" -- "hello world"
</syntaxhighlight>}}
An easy typo to make, but Haskell catches the error when you tried to compile. You don't have to wait until you run the program for the bug to become apparent.
Updating a program commonly involves changes to types. If a change is unintended, or has unforeseen consequences, then it will show up when compiling. Haskell programmers often remark that once they have fixed all the type errors, and their programs compile, that they tend to "just work". The behavior may not always match the intention, but the program won't crash. Haskell has far fewer ''run-time errors'' (where your program goes wrong when you run it rather than when you compile) than other languages.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Haskell Basics}}
{{BookCat}}
dv5c49fqkqzfu7qxl29iydjv6xw8bdt
Haskell/Recursion
0
85006
4675924
4046891
2026-10-13T23:00:11Z
Luciérnaga de conocimiento
3401314
4675924
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Elementary Haskell}}
Recursive functions play a central role in Haskell, and are used throughout computer science and mathematics generally. '''Recursion''' is basically a form of repetition, and we can understand it by making distinct what it ''means'' for a function to be recursive, as compared to how it ''behaves''.
A recursive function simply means this: a function that has the ability to invoke itself.
And it behaves such that it invokes itself only when a condition is met, as with an if/else/then expression, or a pattern match which contains at least one ''base case'' that terminates the recursion, as well as a ''recursive case'' which causes the function to call itself, creating a loop.
Without a terminating condition, a recursive function may remain in a loop forever, causing an infinite regress.
== Numeric recursion ==
=== The factorial function ===
Mathematics (specifically combinatorics) has a function called '''factorial'''.<ref>In mathematics, ''n''! normally means the factorial of a non-negative integer ''n'', but that syntax is impossible in Haskell, so we don't use it here.</ref> It takes a single non-negative integer as an argument, finds all the positive integers less than or equal to “n”, and multiplies them all together. For example, the factorial of 6 (denoted as <math>6!</math>) is <math>1 \times 2 \times 3 \times 4 \times 5 \times 6 = 720</math>. We can use a recursive style to define this in Haskell:
Let's look at the factorials of two adjacent numbers:
{{Haskell/Example|Factorials of consecutive numbers|
<pre>
Factorial of 6 = 6 × 5 × 4 × 3 × 2 × 1
Factorial of 5 = 5 × 4 × 3 × 2 × 1
</pre>
}}
Notice how we've lined things up. You can see here that the <math>6!</math> includes the <math>5!</math>. In fact, <math>6!</math> is just <math>6 \times 5!</math>. Let's continue:
{{Haskell/Example|Factorials of consecutive numbers|
<pre>
Factorial of 4 = 4 × 3 × 2 × 1
Factorial of 3 = 3 × 2 × 1
Factorial of 2 = 2 × 1
Factorial of 1 = 1
</pre>
}}
The factorial of any number is just that number multiplied by the factorial of the number one less than it. There's one exception: if we ask for the factorial of 0, we don't want to multiply 0 by the factorial of -1 (factorial is only for positive numbers). In fact, we just say the factorial of 0 is 1 (we ''define'' it to be so. Just take our word for it that this is right.<ref>Actually, defining the factorial of 0 to be 1 is not just arbitrary; it's because the factorial of 0 represents an [[w:empty product|empty product]].</ref>). So, 0 is the ''base case'' for the recursion: when we get to 0 we can immediately say that the answer is 1, no recursion needed. We can summarize the definition of the factorial function as follows:
* The factorial of 0 is 1.
* The factorial of any other number is that number multiplied by the factorial of the number one less than it.
We can translate this directly into Haskell:
{{Haskell/Example|1=Factorial function|2=<syntaxhighlight lang="haskell">
factorial 0 = 1
factorial n = n * factorial (n - 1)
</syntaxhighlight>}}
This defines a new function called <code>factorial</code>. The first line says that the factorial of 0 is 1, and the second line says that the factorial of any other number <code>n</code> is equal to <code>n</code> times the factorial of <code>n - 1</code>. Note the parentheses around the <code>n - 1</code>; without them this would have been parsed as <code>(factorial n) - 1</code>; remember that function application (applying a function to a value) takes precedence over anything else when grouping isn't specified otherwise (we say that function application ''binds more tightly'' than anything else).
{{body note|1=
The <code>factorial</code> function above is best defined in a file, but since it is a small function, it is feasible to write it in GHCi as a one-liner. To do this, we need to add a semicolon to separate the lines:
<syntaxhighlight lang="haskell">
> let factorial 0 = 1; factorial n = n * factorial (n - 1)
</syntaxhighlight>
Haskell actually uses line separation and other whitespace as a substitute for separation and grouping characters such as semicolons. Haskell programmers generally prefer the clean look of separate lines and appropriate indentation; still, explicit use of semicolons and other markers is always an alternative.
}}
The example above demonstrates the simple relationship between factorial of a number, n, and the factorial of a slightly smaller number, n - 1.
Think of a function call as delegation. The instructions for a recursive function delegate a sub-task. It just so happens that the delegate function uses the same instructions as the delegator; it's only the input data that changes. The only really confusing thing about recursive functions is the fact that each function call uses the same parameter names, so it can be tricky to keep track of the many delegations.
Let's look at what happens when you execute <code>factorial 3</code>:
* 3 isn't 0, so we calculate the factorial of 2
** 2 isn't 0, so we calculate the factorial of 1
*** 1 isn't 0, so we calculate the factorial of 0
**** 0 ''is'' 0, so we return 1.
*** To complete the calculation for factorial 1, we multiply the current number, 1, by the factorial of 0, which is 1, obtaining 1 (1 × 1).
** To complete the calculation for factorial 2, we multiply the current number, 2, by the factorial of 1, which is 1, obtaining 2 (2 × 1 × 1).
* To complete the calculation for factorial 3, we multiply the current number, 3, by the factorial of 2, which is 2, obtaining 6 (3 × 2 × 1 × 1).
(Note that we end up with the one appearing twice, since the base case is 0 rather than 1; but that's okay since multiplying by 1 has no effect. We could have designed <code>factorial</code> to stop at 1 if we had wanted to, but the convention (which is often useful) is to define the factorial of 0.)
When reading or composing recursive functions, you'll rarely need to “unwind” the recursion bit by bit — we leave that to the compiler.
One more note about our recursive definition of <code>factorial</code>: the order of the two declarations (one for <code>factorial 0</code> and one for <code>factorial n</code>) ''is'' important. Haskell decides which function definition to use by starting at the top and picking the first one that matches. If we had the general case (<code>factorial n</code>) before the 'base case' (<code>factorial 0</code>), then the general <code>n</code> would match ''anything'' passed into it – including 0. The compiler would then conclude that <code>factorial 0</code> equals <code>0 * factorial (-1)</code>, and so on to negative infinity (clearly not what we want). So, '''always list multiple function definitions starting with the most specific and proceeding to the most general.'''
{{Exercises|1=
# Type the factorial function into a Haskell source file and load it into GHCi.
# Try examples like <code>factorial 5</code> and <code>factorial 1000</code>.<ref>Interestingly, older scientific calculators can't handle things like factorial of 1000 because they run out of memory with that many digits!</ref>
#* What about <code>factorial (-1)</code>? Why does this happen?
# The ''double factorial'' of a number n is the product of all the integers from 1 up to n that have the same parity as n. For example, the double factorial of 8 is 8 × 6 × 4 × 2 = 384, and the double factorial of 7 is 7 × 5 × 3 × 1 = 105. Define a <code>doubleFactorial</code> function in Haskell.
}}
=== Loops, recursion, and accumulating parameters ===
Imperative languages use ''loops'' in the same sorts of contexts where Haskell programs use recursion. For example, an idiomatic way of writing a factorial function in C, a typical imperative language, would be using a ''for'' loop, like this:
{{Haskell/Example|1=The factorial function in an imperative language|2=
<syntaxhighlight lang="c">
int factorial(int n) {
int res = 1;
for ( ; n > 1; n--)
res *= n;
return res;
}
</syntaxhighlight>
}}
Here, the for loop causes <code>res</code> to be multiplied by <code>n</code> repeatedly. After each repetition, <code>1</code> is subtracted from <code>n</code> (that is what <code>n--</code> does). The repetitions stop when <code>n</code> is no longer greater than <code>1</code>.
A straightforward translation of such a function to Haskell is not possible, since changing the value of the variables <code>res</code> and <code>n</code> (a destructive update) would not be allowed. However, you can always translate a loop into an equivalent recursive form by making each loop variable into an argument of a recursive function. For example, here is a recursive “translation” of the above loop into Haskell:
{{Haskell/Example|1=Using recursion to simulate a loop|2=
<syntaxhighlight lang="haskell">
factorial n = go n 1
where
go n res
| n > 1 = go (n - 1) (res * n)
| otherwise = res
</syntaxhighlight>}}
<code>go</code> is an auxiliary function which actually performs the factorial calculation. It takes an extra argument, <code>res</code>, which is used as an ''accumulating parameter'' to build up the final result.
{{body note|1=Depending on the languages you are familiar with, you might have concerns about performance problems caused by recursion. However, compilers for Haskell and other functional programming languages include a number of optimizations for recursion, (not surprising given how often recursion is needed). Also, Haskell is lazy — calculations are only performed once their results are required by other calculations, and that helps to avoid some of the performance problems. We'll discuss such issues and some of the subtleties they involve further in later chapters.}}
=== Other recursive functions ===
As it turns out, there is nothing particularly special about the <code>factorial</code> function; a great many numeric functions can be defined recursively in a natural way. For example, let's think about multiplication. When you were first learning multiplication (remember that moment? :)), it may have been through a process of 'repeated addition'. That is, 5 × 4 is the same as summing four copies of the number 5. Of course, summing four copies of 5 is the same as summing three copies, and then adding one more – that is, 5 × 4 = 5 × 3 + 5. This leads us to a natural recursive definition of multiplication:
{{Haskell/Example|1=Multiplication defined recursively|2=<syntaxhighlight lang="haskell">
mult _ 0 = 0 -- anything times 0 is zero
mult n m = (mult n (m - 1)) + n -- recurse: multiply by one less, and add an extra copy
</syntaxhighlight>}}
Stepping back a bit, we can see how numeric recursion fits into the general recursive pattern. The base case for numeric recursion usually consists of one or more specific numbers (often 0 or 1) for which the answer can be immediately given. The recursive case computes the result by calling the function recursively with a smaller argument and using the result in some manner to produce the final answer. The 'smaller argument' used is often one less than the current argument, leading to recursion which 'walks down the number line' (like the examples of <code>factorial</code> and <code>mult</code> above). However, the prototypical pattern is not the only possibility; the smaller argument could be produced in some other way as well.
{{Exercises|1=
# Expand out the multiplication 5 × 4 similarly to the expansion we used above for <code>factorial 3</code>.
# Define a recursive function <code>power</code> such that <code>power x y</code> raises <code>x</code> to the <code>y</code> power.
# You are given a function <code>plusOne x = x + 1</code>. Without using any other <code>(+)</code>s, define a recursive function <code>addition</code> such that <code>addition x y</code> adds <code>x</code> and <code>y</code> together.
# (Harder) Implement the function <code>log2</code>, which computes the integer log (base 2) of its argument. That is, <code>log2</code> computes the exponent of the largest power of 2 which is less than or equal to its argument. For example, <code>log2 16 = 4</code>, <code>log2 11 = 3</code>, and <code>log2 1 = 0</code>. (Small hint: read the last phrase of the paragraph immediately preceding these exercises.)
}}
== List-based recursion ==
Haskell has many recursive functions, especially concerning lists.<ref>This is no coincidence; without mutable variables, recursion is the only way to implement control structures. This might sound like a limitation until you get used to it.</ref> Consider the <code>length</code> function that finds the length of a list:
{{Haskell/Example|1=The recursive definition of <code>length</code>|2=<syntaxhighlight lang="haskell">
length :: [a] -> Int
length [] = 0
length (x:xs) = 1 + length xs
</syntaxhighlight>}}
{{body note|If you try to load the definition above from a source file, GHCi will complain about an “ambiguous occurrence” when you try to use it, as the Prelude already provides <code>length</code>. In that case, just change the name of the function which you are defining to something else. like <code>length'</code> or <code>myLength</code>.}}
So, the type signature of <code>length</code> tells us that it takes any type of list and produces an <code>Int</code>. The next line says that the length of an empty list is 0 (this is the base case). The final line is the recursive case: if a list isn't empty, then it can be broken down into a first element (here called <code>x</code>) and the rest of the list (which will just be the empty list if there are no more elements) which will, by convention, be called <code>xs</code> (i.e. plural of <code>x</code>). The length of the list is 1 (accounting for the <code>x</code>) plus the length of <code>xs</code> (as in the <code>tail</code> example in [[Haskell/Next steps|Next steps]], <code>xs</code> is set when the argument list matches the (:) pattern).
Consider the concatenation function <code>(++)</code> which joins two lists together:
{{Haskell/Example|1=The recursive <code>(++)</code>|2=
{{Haskell/GHCi|1=
Prelude> [1,2,3] ++ [4,5,6]
[1,2,3,4,5,6]
Prelude> "Hello " ++ "world" -- Strings are lists of Chars
"Hello world"
}}
<syntaxhighlight lang="haskell">
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : xs ++ ys
</syntaxhighlight>
}}
This is a little more complicated than <code>length</code>. The type says that <code>(++)</code> takes two lists of the same type and produces another list of the same type. The base case says that concatenating the empty list with a list <code>ys</code> is the same as <code>ys</code> itself. Finally, the recursive case breaks the first list into its head (<code>x</code>) and tail (<code>xs</code>) and says that to concatenate the two lists, concatenate the tail of the first list with the second list, and then tack the head <code>x</code> on the front.
There's a pattern here: with list-based functions, the base case usually involves an empty list, and the recursive case involves passing the tail of the list to our function again, so that the list becomes progressively smaller.
{{Exercises|1=
Give recursive definitions for the following list-based functions. In each case, think what the base case would be, then think what the general case would look like, in terms of everything smaller than it. (Note that all of these functions are available in Prelude, so you will want to give them different names when testing your definitions in GHCi.)
# <code>replicate :: Int -> a -> [a]</code>, which takes a count and an element and returns the list which is that element repeated that many times. E.g. <code>replicate 3 'a' = "aaa"</code>. (Hint: think about what replicate of anything with a count of 0 should be; a count of 0 is your 'base case'.)
# <code>(!!) :: [a] -> Int -> a</code>, which returns the element at the given 'index'. The first element is at index 0, the second at index 1, and so on. Note that with this function, you're recursing ''both'' numerically and down a list<ref>Incidentally, <code>(!!)</code> provides a reasonable solution for the problem of the fourth exercise in [[../Lists and tuples#Pending questions|Lists and tuples/Retrieving values]].</ref>.
# (A bit harder.) <code>zip :: [a] -> [b] -> [(a, b)]</code>, which takes two lists and 'zips' them together, so that the first pair in the resulting list is the first two elements of the two lists, and so on. E.g. <code>zip [1,2,3] "abc" = [(1, 'a'), (2, 'b'), (3, 'c')]</code>. If either of the lists is shorter than the other, you can stop once either list runs out. E.g. <code>zip [1,2] "abc" = [(1, 'a'), (2, 'b')]</code>.
#:<br>
# Define <code>length</code> using an auxiliary function and an accumulating parameter, as in the loop-like alternate version of <code>factorial</code>.
}}
Recursion is used to define nearly all functions to do with lists and numbers. The next time you need a list-based algorithm, start with a case for the empty list and a case for the non-empty list and see if your algorithm is recursive.
== Don't get TOO excited about recursion... ==
Despite its ubiquity in Haskell, one rarely has to write functions that are explicitly recursive. Instead, standard library functions perform recursion for us in various ways. For example, a simpler way to implement the <code>factorial</code> function is:
{{Haskell/Example|1=Implementing factorial with a standard library function|2=<syntaxhighlight lang="haskell">
factorial n = product [1..n]
</syntaxhighlight>}}
Almost seems like cheating, doesn't it? :) This is the version of <code>factorial</code> that most experienced Haskell programmers would write, rather than the explicitly recursive version we started out with. Of course, the <code>product</code> function uses some list recursion behind the scenes,<ref>Actually, it uses a function called <code>foldl</code> to which it “delegates” the recursion.</ref> but writing <code>factorial</code> in this way means you, the programmer, don't have to worry about it.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Elementary Haskell}}
{{BookCat}}
6s4vr29zjp6kdzjno7woty4dw4cfh2w
Haskell/Next steps
0
85046
4675922
4628042
2026-10-13T22:55:53Z
Luciérnaga de conocimiento
3401314
4675922
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Haskell Basics|noexercises=0}}
This chapter introduces ''pattern matching'' and two new pieces of syntax: <code>if</code> expressions and <code>let</code> bindings.
== if / then / else ==
Haskell syntax supports garden-variety conditional expressions of the form ''if... then... else...'' . For instance, consider a function that returns <code>(-1)</code> if its argument is less than <code>0</code>; <code>0</code> if its argument ''is'' <code>0</code>; and <code>1</code> if its argument is greater than <code>0</code>. The predefined <code>signum</code> function does that job already; but for the sake of illustration, let's define a version of our own:
{{Haskell/Example|The signum function.|
<syntaxhighlight lang="haskell">
mySignum x =
if x < 0
then -1
else if x > 0
then 1
else 0
</syntaxhighlight>
You can experiment with this:
{{Haskell/GHCi|1=
*Main> mySignum 5
1
*Main> mySignum 0
0
*Main> mySignum (5 - 10)
-1
*Main> mySignum (-1)
-1
}}}}
The parentheses around "-1" in the last example are required; if missing, Haskell will think that you are trying to subtract <code>1</code> from <code>mySignum</code> (which would give a type error).
In an if/then/else construct, first the condition (in this case <code>x < 0</code>) is evaluated. If it results <code>True</code>, the whole construct evaluates to the <code>'''then'''</code> expression; otherwise (if the condition is <code>False</code>), the construct evaluates to the <code>'''else'''</code> expression. All of that is pretty intuitive. If you have programmed in an imperative language before, however, it might seem surprising to know that Haskell always requires ''both'' a <code>'''then'''</code> ''and'' an <code>'''else'''</code> clause. The construct has to result in a value in both cases and, specifically, a value of the same type in both cases.
Function definitions using if / then / else like the one above can be rewritten using [[../Truth_values#Guards|Guards]].
{{Haskell/Example|1=From if to guards|2=<syntaxhighlight lang="haskell">
mySignum x
| x < 0 = -1
| x > 0 = 1
| otherwise = 0
</syntaxhighlight>}}
Similarly, the absolute value function defined in [[../Truth_values#Guards/|Truth values]] can be rendered with an if/then/else:
{{Haskell/Example|1=From guards to if|2=<syntaxhighlight lang="haskell">
absolute x =
if x < 0
then -x
else x
</syntaxhighlight>}}
Why use if/then/else versus guards? As you will see with later examples and in your own programming, either way of handling conditionals may be more readable or convenient depending on the circumstances. In many cases, both options work equally well.
== Introducing pattern matching ==
Consider a program which tracks statistics from a racing competition in which racers receive points based on their classification in each race, the scoring rules being:
* 10 points for the winner;
* 6 for second-placed;
* 4 for third-placed;
* 3 for fourth-placed;
* 2 for fifth-placed;
* 1 for sixth-placed;
* no points for other racers.
We can write a simple function which takes a classification (represented by an integer number: <code>1</code> for first place, etc.<ref>Here we will not be much worried about what happens if a nonsensical value (say, <code>(-4)</code>) is passed to the function. In general, however, it is a good idea to give some thought to such "strange" cases, in order to avoid nasty surprises down the road.</ref>) and returns how many points were earned. One possible solution uses if/then/else:
{{Haskell/Example|1=Computing points with if/then/else|2=<syntaxhighlight lang="haskell">
pts :: Int -> Int
pts x =
if x == 1
then 10
else if x == 2
then 6
else if x == 3
then 4
else if x == 4
then 3
else if x == 5
then 2
else if x == 6
then 1
else 0
</syntaxhighlight>}}
Yuck! Admittedly, it wouldn't look this hideous had we used guards instead of if/then/else, but it still would be tedious to write (and read!) all those equality tests. We can do better, though:
{{Haskell/Example|1=Computing points with a piece-wise definition|2=<syntaxhighlight lang="haskell">
pts :: Int -> Int
pts 1 = 10
pts 2 = 6
pts 3 = 4
pts 4 = 3
pts 5 = 2
pts 6 = 1
pts _ = 0
</syntaxhighlight>}}
''Much'' better. However, even though defining <code>pts</code> in this style (which we will arbitrarily call ''piece-wise definition'' from now on) shows to a reader of the code what the function does in a clear way, the syntax looks odd given what we have seen of Haskell so far. Why are there seven equations for <code>pts</code>? What are those numbers doing in their left-hand sides? What about variable arguments?
This feature of Haskell is called ''pattern matching''. When we call <code>pts</code>, the argument is ''matched'' against the numbers on the left side of each of the equations, which in turn are the ''patterns''. The matching is done in the order we wrote the equations. First, the argument is matched against the <code>1</code> in the first equation. If the argument is indeed <code>1</code>, we have a match and the first equation is used; so <code>pts 1</code> evaluates to <code>10</code> as expected. Otherwise, the other equations are tried in order following the same procedure. The final one, though, is rather different: the <code>_</code> is a special pattern, often called a "wildcard", that might be read as "whatever": it matches with anything; and therefore if the argument doesn't match any of the previous patterns <code>pts</code> will return zero.
As for the lack of <code>x</code> or any other variable standing for the argument, we simply don't need that to write the definitions. All possible return values are constants. Besides, variables are used to express relationships on the right side of the definition, so the <code>x</code> is unnecessary in our <code>pts</code> function.
However, we could use a variable to make <code>pts</code> even more concise. The points given to a racer decrease regularly from third place to sixth place, at a rate of one point per position. After noticing that, we can eliminate three of the seven equations as follows:
{{Haskell/Example|1=Mixing styles|2=<syntaxhighlight lang="haskell">
pts :: Int -> Int
pts 1 = 10
pts 2 = 6
pts x
| x <= 6 = 7 - x
| otherwise = 0
</syntaxhighlight>}}
So, we can mix both styles of definitions. In fact, when we write <code>pts x</code> in the left side of an equation we are using pattern matching too! As a pattern, the <code>x</code> (or any other variable name) matches anything just like <code>_</code>; the only difference being that it also gives us a name to use on the right side (which, in this case, is necessary to write <code>7 - x</code>).
{{Exercises|1=
We cheated a little when moving from the second version of <code>pts</code> to the third one: they do not do exactly the same thing. Can you spot what the difference is?
}}
Beyond integers, pattern matching works with values of various other types. One handy example is booleans. For instance, the <code>(||)</code> logical-or operator we met in [[../Truth values#Boolean operators|Truth values]] could be defined as:
{{Haskell/Example|1=<code>({{!!}})</code>|2=<syntaxhighlight lang="haskell">
(||) :: Bool -> Bool -> Bool
False || False = False
_ || _ = True
</syntaxhighlight>}}
Or:
{{Haskell/Example|1=<code>({{!!}})</code>, done another way|2=<syntaxhighlight lang="haskell">
(||) :: Bool -> Bool -> Bool
True || _ = True
False || y = y
</syntaxhighlight>}}
When matching two or more arguments at once, the equation will only be used if all of them match.
Now, let's discuss a few things that might go wrong when using pattern matching:
* If we put a pattern which matches anything (such as the final patterns in each of the <code>pts</code> example) ''before'' the more specific ones the latter will be ignored. GHC(i) will typically warn us that "Pattern match(es) are overlapped" in such cases.
* If no patterns match, an error will be triggered. Generally, it is a good idea to ensure the patterns cover all cases, in the same way that the <code>otherwise</code> guard is not mandatory but highly recommended.
* Finally, while you can play around with various ways of (re)defining <code>(&&),</code><ref>If you are going to experiment with it in GHCi, call your version something else to avoid a name clash; say, (&!&).</ref> here is one version that will ''not'' work:
<syntaxhighlight lang="haskell">
(&&) :: Bool -> Bool -> Bool
x && x = x -- oops!
_ && _ = False
</syntaxhighlight>
:The program won't test whether the arguments are equal just because we happened to use the same name for both. As far as the matching goes, we could just as well have written <code>_ && _</code> in the first case. And even worse: because we gave the same name to both arguments, GHC(i) will refuse the function due to "Conflicting definitions for `x'".
== Tuple and list patterns ==
While the examples above show that pattern matching helps in writing more elegant code, that does not explain why it is so important. So, let's consider the problem of writing a definition for <code>fst</code>, the function which extracts the first element of a pair. At this point, that appears to be an impossible task, as the only way of accessing the first value of the pair is by using <code>fst</code> itself... The following function, however, does the same thing as <code>fst</code> (confirm it in GHCi):
{{Haskell/Example|1=A definition for <code>fst</code>|2=<syntaxhighlight lang="haskell">
fst' :: (a, b) -> a
fst' (x, _) = x
</syntaxhighlight>}}
It's magic! Instead of using a regular variable in the left side of the equation, we specified the argument with the ''pattern'' of the 2-tuple - that is, <code>(,)</code> - filled with a variable and the <code>_</code> pattern. Then the variable was automatically associated with the first component of the tuple, and we used it to write the right side of the equation. The definition of <code>snd</code> is, of course, analogous.
Furthermore, the trick demonstrated above can be done with lists as well. Here are the actual definitions of <code>head</code> and <code>tail</code>:
{{Haskell/Example|1=<code>head</code>, <code>tail</code> and patterns|2=<syntaxhighlight lang="haskell">
head :: [a] -> a
head (x:_) = x
head [] = error "Prelude.head: empty list"
tail :: [a] -> [a]
tail (_:xs) = xs
tail [] = error "Prelude.tail: empty list"
</syntaxhighlight>}}
The only essential change in relation to the previous example was replacing <code>(,)</code> with the pattern of the cons operator <code>(:)</code>. These functions also have an equation using the pattern of the empty list, <code>[]</code>; however, since empty lists have no head or tail there is nothing to do other than use <code>error</code> to print a prettier error message.
In summary, the power of pattern matching comes from its use in accessing the parts of a complex value. Pattern matching on lists, in particular, will be extensively deployed in [[../Recursion|Recursion]] and the chapters that follow it. Later on, we will explore what is happening behind this seemingly magical feature.
== <code>let</code> bindings ==
To conclude this chapter, a brief word about <code>let</code> bindings (an alternative to <code>where</code> clauses for making local declarations). For instance, take the problem of finding the roots of a polynomial of the form <math>ax^2+bx+c</math> (in other words, the solution to a second degree equation — think back to your middle school math courses). Its solutions are given by:
: <math>x = \frac {-b \pm \sqrt{b^2-4ac}} {2a}</math>.
We could write the following function to compute the two values of <math>x</math>:
<syntaxhighlight lang="haskell">
roots a b c =
((-b + sqrt(b * b - 4 * a * c)) / (2 * a),
(-b - sqrt(b * b - 4 * a * c)) / (2 * a))
</syntaxhighlight>
Writing the <code>sqrt(b * b - 4 * a * c)</code> term in both cases is annoying, though; we can use a local binding instead, using either <code>where</code> or, as will be demonstrated below, a <code>let</code> declaration:
<syntaxhighlight lang="haskell">
roots a b c =
let sdisc = sqrt (b * b - 4 * a * c)
in ((-b + sdisc) / (2 * a),
(-b - sdisc) / (2 * a))
</syntaxhighlight>
We put the <code>let</code> keyword before the declaration, and then use <code>in</code> to signal we are returning to the "main" body of the function. It is possible to put multiple declarations inside a single <code>let</code>...<code>in</code> block — just make sure they are indented the same amount or there will be syntax errors:
<syntaxhighlight lang="haskell">
roots a b c =
let sdisc = sqrt (b * b - 4 * a * c)
twice_a = 2 * a
in ((-b + sdisc) / twice_a,
(-b - sdisc) / twice_a)
</syntaxhighlight>
{{warning|1=
Because indentation matters syntactically in Haskell, you need to be careful about whether you are using tabs or spaces. By far the best solution is to configure your text editor to insert two or four spaces in place of tabs. If you insist on keeping tabs as distinct, at least ensure that your tabs always have the same length.
}}
{{body note|1=
The [[../Indentation|Indentation]] chapter has a full account of indentation rules.
}}
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Haskell Basics}}
{{BookCat}}
p1soj6665gzfrrxgxsrngon4lccyl0p
Haskell/Lists and tuples
0
85159
4675919
3848349
2026-10-13T22:50:55Z
Luciérnaga de conocimiento
3401314
4675919
wikitext
text/x-wiki
Haskell uses two fundamental structures for managing several values: lists and tuples. They both work by grouping multiple values into a single combined value.
{{Haskell/Minitoc|chapter=Haskell Basics}}
==Lists==
Let's build some lists in GHCi:
{{Haskell/GHCi|1=
Prelude> let numbers = [1,2,3,4]
Prelude> let truths = [True, False, False]
Prelude> let strings = ["here", "are", "some", "strings"]
}}
The square brackets delimit the list, and individual elements are separated by commas. The only important restriction is that all elements in a list must be of the same type. Trying to define a list with mixed-type elements results in a typical type error: <!-- alliteration intended -->
{{Haskell/GHCi|1=
Prelude> let mixed = [True, "bonjour"]
<interactive>:1:19:
Couldn't match `Bool' against `[Char]'
Expected type: Bool
Inferred type: [Char]
In the list element: "bonjour"
In the definition of `mixed': mixed = [True, "bonjour"]
}}
=== Building lists ===
In addition to specifying the whole list at once using square brackets and commas, you can build them up piece by piece using the <code>(:)</code> operator pronounced "cons". The process of building up a list this way is often referred to as '''consing'''. This terminology comes from LISP programmers who invented the verb "to cons" (a mnemonic for "constructor") to refer to this specific task of prepending an element to a list.
{{Haskell/GHCiExample|1=Consing something on to a list|2=
Prelude> let numbers = [1,2,3,4]
Prelude> numbers
[1,2,3,4]
Prelude> 0:numbers
[0,1,2,3,4]
}}
When you cons something on to a list (<code>something:someList</code>), you get back another list. Thus, you can keep on consing for as long as you wish. Note that the cons operator evaluates from right to left. Another (more general) way to think of it is that it takes the first value to its left and the whole expression to its right.
{{Haskell/GHCiExample|1=Consing lots of things to a list|2=
Prelude> 1:0:numbers
[1,0,1,2,3,4]
Prelude> 2:1:0:numbers
[2,1,0,1,2,3,4]
Prelude> 5:4:3:2:1:0:numbers
[5,4,3,2,1,0,1,2,3,4]
}}
In fact, Haskell builds all lists this way by consing all elements to the ''empty list'', <code>[]</code>. The commas-and-brackets notation are just ''syntactic sugar''. So <code>[1,2,3,4,5]</code> is exactly equivalent to <code>1:2:3:4:5:[]</code>
You will, however, want to watch out for a potential pitfall in list construction. Whereas <code>True:False:[]</code> is perfectly good Haskell, <code>True:False</code> is ''not'':
{{Haskell/GHCiExample|1=Whoops!|2=
Prelude> True:False
<interactive>:1:5:
Couldn't match `[Bool]' against `Bool'
Expected type: [Bool]
Inferred type: Bool
In the second argument of `(:)', namely `False'
In the definition of `it': it = True : False
}}
<code>True:False</code> produces a familiar-looking type error message. It tells us that the cons operator <code>(:)</code> (which is really just a function) expected a list as its second argument, but we gave it another <code>Bool</code> instead. <code>(:)</code> only knows how to stick things onto lists.<ref>At this point you might question the value of types. While they can feel annoying at first, more often than not they turn out to be extremely helpful. In any case, when you are programming in Haskell and something blows up, you'll probably want to think "type error".</ref>
So, when using cons, remember:
* The elements of the list must have the same type.
* You can only cons <code>(:)</code> something onto a list, not the other way around (you cannot cons a list onto an element). So, the final item on the right must be a list, and the items on the left must be independent elements, not lists.
{{Exercises|1=
# Would the following piece of Haskell work: <code>3:[True,False]</code>? Why or why not?
# Write a function <code>cons8</code> that takes a list as an argument and conses <code>8</code> (at the beginning) on to it. Test it out on the following lists by doing:
## <code>cons8 []</code>
## <code>cons8 [1,2,3]</code>
## <code>cons8 [True,False]</code>
## <code>let foo = cons8 [1,2,3]</code><br><code>cons8 foo</code>
# Adapt the above function in a way that <code>8</code> is at the end of the list. (Hint: recall the concatenation operator <code>++</code> from the previous chapter.)
# Write a function that takes two arguments, a list and a thing, and conses the thing onto the list. You can start out with:
:::<code>let myCons list thing =</code>
}}
=== Strings are just lists ===
As we briefly mentioned in the Type Basics module, strings in Haskell are just lists of characters. That means values of type String can be manipulated just like any other list. For instance, instead of entering strings directly as a sequence of characters enclosed in double quotation marks, they may also be constructed through a sequence of Char values, either linked with <code>(:)</code> and terminated by an empty list or using the commas-and-brackets notation.
{{Haskell/GHCi|1=
Prelude> "hey" == ['h','e','y']
True
Prelude> "hey" == 'h':'e':'y':[]
True
}}
Using double-quoted strings is just more syntactic sugar.
=== Lists of lists ===
Lists can contain ''anything'' — as long as they are all of the same type. Because lists are things too, lists can contain other lists! Try the following in the interpreter:
{{Haskell/GHCiExample|1=Lists can contain lists|2=
Prelude> let listOfLists = [[1,2],[3,4],[5,6]]
Prelude> listOfLists
[[1,2],[3,4],[5,6]]
}}
Lists of lists can be tricky sometimes because a list of things does not have the same type as a thing all by itself. The type <code>Int</code> is different from <code>[Int]</code>. Let's sort through these implications with a few exercises:
{{Exercises|1=
#Which of these are valid Haskell and which are not? Rewrite in cons notation.
## <code><nowiki>[1,2,3,[]]</nowiki></code>
## <code><nowiki>[1,[2,3],4]</nowiki></code>
## <code><nowiki>[[1,2,3],[]]</nowiki></code>
#Which of these are valid Haskell, and which are not? Rewrite in comma and bracket notation.
## <code><nowiki>[]:[[1,2,3],[4,5,6]]</nowiki></code>
## <code>[]:[]</code>
## <code>[]:[]:[]</code>
## <code>[1]:[]:[]</code>
## <code>["hi"]:[1]:[]</code>
#Can Haskell have lists of lists of lists? Why or why not?
#Why is the following list invalid in Haskell?
## <code><nowiki>[[1,2],3,[4,5]]</nowiki></code>
}}
Lists of different types of things cannot be consed, but the empty list can be consed with lists of anything. For example, <code>[]:[[1, 2], [1, 2, 3]]</code> is valid and will produce <code>[[], [1, 2], [1, 2, 3]]</code>, and <code>[1]:[[1, 2], [1, 2, 3]]</code> is valid and will produce <code>[[1], [1, 2], [1, 2, 3]]</code>, but <code>['a']:[[1, 2], [1, 2, 3]]</code> will produce an error message.
Lists of lists allow us to express some kinds of complicated, structured data (two-dimensional matrices, for example). They are also one of the places where the Haskell type system truly shines. Human programmers (including this wikibook co-author) get confused ''all'' the time when working with lists of lists, and having restrictions on types often helps in wading through the potential mess.
== Tuples ==
=== A different notion of many ===
'''Tuples''' offer another way of storing multiple values in a single value. Tuples and lists have two key differences:
* Tuples have a ''fixed'' number of elements (''immutable''); you can't cons to a tuple. Therefore, it makes sense to use tuples when you ''know'' in advance how many values are to be stored. For example, we might want a type for storing 2D coordinates of a point. We know exactly how many values we need for each point (two – the ''x'' and ''y'' coordinates), so tuples are applicable.
* The elements of a tuple do not need to be all of the same type. For instance, in a phonebook application we might want to handle the entries by crunching three values into one: the name, phone number, and the number of times we made calls. In such a case the three values won't have the same type, since the name and the phone number are strings, but contact counter will be a number, so lists wouldn't work.
Tuples are marked by parentheses with elements delimited by commas. Let's look at some sample tuples:
{{Haskell/Example|1=Some tuples|2=<syntaxhighlight lang="haskell">
(True, 1)
("Hello world", False)
(4, 5, "Six", True, 'b')
</syntaxhighlight>}}
The first example is a tuple containing two elements: True and 1. The next example again has two elements: "Hello world" and False. The third example is a tuple consisting of ''five'' elements: 4 (a number), 5 (another number), "Six" (a string), True (a boolean value), and 'b' (a character).
A quick note on nomenclature: In general you use ''n-tuple'' to denote a tuple of size ''n''. Commonly, we call 2-tuples (that is, tuples with 2 elements) ''pairs'' and 3-tuples ''triples''. Tuples of greater sizes aren't actually all that common, but we can logically extend the naming system to ''quadruples'', ''quintuples'', and so on.
{{Exercises|
# Write down the 3-tuple whose first element is 4, second element is "hello" and third element is True.
# Which of the following are valid tuples?
## <code>(4, 4)</code>
## <code>(4, "hello")</code>
## <code>(True, "Blah", "foo")</code>
## <code>()</code>
# Lists can be built by consing new elements onto them. Cons a number onto a list of numbers, you will get back a list of numbers. There is no such way to build up tuples.
## Why do you think that is?
## For the sake of argument, say that there was such a function. What would you get if you "consed" something on a tuple?
}}
Tuples are handy when you want to return more than one value from a function. In many languages, returning two or more things at once often requires wrapping them up in a single-purpose data structure, maybe one that only gets used in that function. In Haskell, we would return such results as a tuple.
=== Tuples within tuples (and other combinations) ===
We can apply the same reasoning to tuples about storing lists within lists. Tuples are things too, so you can store tuples within tuples (within tuples up to any arbitrary level of complexity). Likewise, you could also have lists of tuples, tuples of lists, and all sorts of related combinations.
{{Haskell/Example|1=Nesting tuples and lists|2=<syntaxhighlight lang="haskell">
((2,3), True)
((2,3), [2,3])
[(1,2), (3,4), (5,6)]
</syntaxhighlight>}}
The type of a tuple is defined not only by its size, but, like lists, by the types of objects it contains. For example, the tuples <code>("Hello",32)</code> and <code>(47,"World")</code> are fundamentally different. One is of type <code>(String,Int)</code>, whereas the other is <code>(Int,String)</code>. This has implications for building up lists of tuples. We could very well have lists like <code>[("a",1),("b",9),("c",9)]</code>, but Haskell cannot have a list like <code>[("a",1),(2,"b"),(9,"c")]</code>.
{{Exercises|1=
# Which of these are valid Haskell, and why?
#* <code>1:(2,3)</code>
#* <code>(2,4):(2,3)</code>
#* <code>(2,4):[]</code>
#* <code>[(2,4),(5,5),('a','b')]</code>
#* <code>([2,4],[2,2])</code>
}}
== Retrieving values ==
For lists and tuples to be useful, we will need to access the internal values they contain.
Let's begin with pairs (i.e. 2-tuples) representing the (''x'', ''y'') coordinates of a point. Imagine you want to specify a specific square on a chess board. You could label the ranks and files from 1 to 8. Then, a pair <code>(2, 5)</code> could represent the square in rank 2 and file 5. Say we want a function for finding all the pieces in a given rank. We could start with the coordinates of all the pieces and then look at the rank part and see whether it equals whatever row we want to examine. Given a coordinate pair <code>(x, y)</code> of a piece, our function would need to extract the <code>x</code> (the rank coordinate). For this sort of goal, there are two standard functions, <code>fst</code> and <code>snd</code>, that retrieve<ref>Or, more technically, "... ''projections'' that ''project'' the elements..." In math-speak, a function that gets some data out of a structure is called a projection.</ref> the first and second elements out of a pair, respectively. Let's see some examples:
{{Haskell/GHCiExample|1=Using <code>fst</code> and <code>snd</code>|2=
Prelude> fst (2, 5)
2
Prelude> fst (True, "boo")
True
Prelude> snd (5, "Hello")
"Hello"
}}
Note that these functions, by definition, ''only'' work on pairs.<ref>Yes, a function could be designed to extract the first thing from any size tuple, but it wouldn't be as simple as you might think, and it isn't how the fst and snd functions from the standard libraries work.</ref>
For lists, the functions <code>head</code> and <code>tail</code> are ''roughly'' analogous to <code>fst</code> and <code>snd</code>. They disassemble a list by taking apart what <code>(:)</code> joined. <code>head</code> evaluates to the first element of the list, while <code>tail</code> gives the rest of the list.
{{Haskell/GHCiExample|1=Using <code>head</code> and <code>tail</code>|2=
Prelude> 2:[7,5,0]
[2,7,5,0]
Prelude> head [2,7,5,0]
2
Prelude> tail [2,7,5,0]
[7,5,0]
}}
{{body note|1=
Unfortunately, we have a serious problem with <code>head</code> and <code>tail</code>. If we apply either of them to an empty list...
{{Haskell/GHCi|1=
Prelude> head []
*** Exception: Prelude.head: empty list
}}
... it blows up, as an empty list has no first element, nor any other elements at all. Outside of GHCi, attempting to run <code>head</code> or <code>tail</code> on the empty list will crash a program.
We will play with <code>head</code> and <code>tail</code> for the moment, but we want to avoid any risk of such malfunctions in our real code, so we will learn later about better options. One might ask "What is the problem? Using <code>head</code> and <code>tail</code> works fine if we are careful and never pass them an empty list, or if we somehow test whether a list is empty before calling them." But that way lies madness.
As programs get bigger and more complicated, the number of places in which an empty list could end up being passed to <code>head</code> and <code>tail</code> grows quickly as does the number of places in which we might make a mistake. As a rule of thumb, you should avoid functions that might fail without warning. As we advance through the book, we will learn better ways to avoid these risks.
}}
=== Pending questions ===
The four functions introduced here do not appear to fully solve the problem we started this section with. While <code>fst</code> and <code>snd</code> provide a satisfactory solution for pairs, what about tuples with three or more elements? And with lists, can we do any better than just breaking them after the first element? For the moment, we will have to leave these questions pending. Once we do some necessary groundwork, we will return to this subject in future chapters on list manipulation. For now, know that separating head and tail of a list will allow us to do anything we want.
{{Exercises|
# Use a combination of <code>fst</code> and <code>snd</code> to extract the 4 from the tuple <code>(("Hello", 4), True)</code>.
# Normal chess notation is somewhat different to ours: it numbers the rows from 1-8 and the columns a-h; and the column label is customarily given first. Could we label a specific point with a character and a number, like <code>('a', 4)</code>? What important difference with lists does this illustrate?
# Write a function which returns the head and the tail of a list as the first and second elements of a tuple.
# Use <code>head</code> and <code>tail</code> to write a function which gives the fifth element of a list. Then, make a critique of it, pointing out any annoyances and pitfalls you notice.
}}
== Polymorphic types ==
Recall that the type of a list depends on the types of its elements and is denoted by enclosing it in square brackets:
{{Haskell/GHCi|1=
Prelude> :t [True, False]
[True, False] :: [Bool]
Prelude> :t ["hey", "my"]
["hey", "my"] :: [[Char]]
}}
Lists of <code>Bool</code> are a different type than lists of <code>[Char]</code> (which is the same as a list of <code>String</code> because <code>[Char]</code> and <code>String</code> are synonyms). Since functions only accept arguments of the types specified in the type of the function, that might lead to some complications. For example, consider the case of <code>head</code>. Given that <code>[Int]</code>, <code>[Bool]</code> and <code>[String]</code> are different types, it seems we would need separate functions for every case – <code>headInt :: [Int] -> Int</code>, <code>headBool :: [Bool] -> Bool</code>, <code>headString :: [String] -> String</code>, and so on… That, however, would be not only very annoying but also rather senseless. After all, lists are assembled in the same way regardless of the types of the values they contain, and so we would expect the procedure to get the first element of the list would remain the same in all cases.
Fortunately, we do have a single function <code>head</code>, which works on all lists:
{{Haskell/GHCi|1=
Prelude> head [True, False]
True
Prelude> head ["hey", "my"]
"hey"
}}
How can that possibly work? As usual, checking the type of <code>head</code> provides a good hint:
{{Haskell/GHCiExample|1=Our first polymorphic type|2=
Prelude> :t head
head :: [a] -> a
}}
The <code>a</code> in the signature is ''not'' a type – remember that type names always start with uppercase letters. Instead, it is a '''type variable'''. When Haskell sees a type variable, it allows any type to take its place. In type theory (a branch of mathematics), this is called ''polymorphism'': functions or values with only a single type are called ''monomorphic'', and things that use type variables to admit more than one type are ''polymorphic''. The type of <code>head</code>, for instance, tells us that it takes a list (<code><nowiki>[a]</nowiki></code>) of values of an arbitrary type (<code>a</code>) and gives back a value of that same type (<code>a</code>).
Note that within a single type signature, all cases of the same type variable must be of the same type. For example,
<syntaxhighlight lang = "haskell">
f :: a -> a
</syntaxhighlight>
means that <code>f</code> takes an argument of ''any'' type and gives something of the ''same'' type as the result, as opposed to
<syntaxhighlight lang = "haskell">
f :: a -> b
</syntaxhighlight>
which means that <code>f</code> takes an argument of ''any'' type and gives a result of ''any'' type which ''may or may not'' match the type of whatever we have for <code>a</code>. The different type variables do not specify that the types must be different, it only says that they can be different.
=== Example: <code>fst</code> and <code>snd</code> ===
As we saw, you can use the <code>fst</code> and <code>snd</code> functions to extract parts of pairs. By now, you should already be building the habit of wondering "what type is this?" for every function you come across. Let's consider the cases of <code>fst</code> and <code>snd</code>. These two functions take a pair as their argument and return one element of this pair. As with lists, the type of a pair depends on the type of its elements, so the functions need to be polymorphic. Also remember that pairs (and tuples in general) don't have to be homogeneous with respect to internal types. So if we were to say:
<syntaxhighlight lang="haskell">fst :: (a, a) -> a</syntaxhighlight>
That would mean <code>fst</code> would only work if the first and second part of the pair given as input had the same type. So the correct type is:
{{Haskell/Example|1=The types of <code>fst</code> and <code>snd</code>|2=<syntaxhighlight lang="haskell">
fst :: (a, b) -> a
snd :: (a, b) -> b
</syntaxhighlight>}}
If you knew nothing about <code>fst</code> and <code>snd</code> other than the type signatures, you might still guess that they return the first and second parts of a pair, respectively. Although that is correct, other functions may have this same type signature. All the signatures say is that they just have to return something ''with the same type'' as the first and second parts of the pair, respectively.
{{Exercises|
Give type signatures for the following functions:
# The solution to the third exercise of the previous section ("... a function which returns the head and the tail of a list as the first and second elements of a tuple").
# The solution to the fourth exercise of the previous section ("... a function which gives the fifth element of a list").
# <code><nowiki>h x y z = chr (x - 2)</nowiki></code> (remember we discussed chr in the previous chapter).
}}
== Summary ==
This chapter introduced lists and tuples. The key similarities and differences between them are:
# Lists are defined by square brackets and commas : <code>[1,2,3]</code>.
#* Lists can contain ''anything'' as long as all the elements of the list are of the same type.
#* Lists can also be built by the cons operator, <code>(:)</code>, but you can only cons things onto lists.
# Tuples are defined by parentheses and commas : <code>("Bob",32)</code>
#* Tuples can contain ''anything'', even things of different types.
#* The length of a tuple is encoded in its type; tuples with different lengths will have different types.
# Lists and tuples can be combined in any number of ways: lists within lists, tuples within lists, etc, but their criteria must still be fulfilled for the combinations to be valid.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Haskell Basics}}
{{BookCat}}
ljaw0q7ow7ud2evrfzx2fkwmrhkn191
Haskell/Higher-order functions
0
87471
4675951
4324584
2026-10-14T00:36:00Z
~2026-54868-50
3628373
4675951
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Elementary Haskell}}
At the heart of functional programming is the idea that functions are ''just like any other value''. The power of functional style comes from handling functions themselves as regular values, i.e. by passing functions to other functions and returning them from functions. A function that takes another function (or several functions) as an argument is called a ''higher-order function''. They can be found pretty much anywhere in a Haskell program, and indeed we have already met some of them, such as <code>map</code> and the various folds. We saw commonplace examples of higher-order functions when discussing <code>map</code> in [[Haskell/Lists II|Lists II]]. Now, we are going to explore some common ways of writing code that manipulates functions.
== A sorting algorithm ==
For a concrete example, we will consider the task of sorting a list. ''Quicksort'' is a well-known recursive sorting algorithm. To apply its sorting strategy to a list, we first choose one element and then divide the rest of the list into (A) those elements that should go before the chosen element, (B) those elements equal to the chosen one, and (C) those that should go after. Then, we apply the same algorithm to the unsorted (A) and (C) lists. After enough recursive sorting, we concatenate everything back together and have a final sorted list. That strategy can be translated into a Haskell implementation in a very simple way.
<syntaxhighlight lang="haskell">
-- Type signature: any list with elements in the Ord class can be sorted.
quickSort :: (Ord a) => [a] -> [a]
-- Base case:
-- If the list is empty, there is nothing to do.
quickSort [] = []
-- The recursive case:
-- We pick the first element as our "pivot", the rest is to be sorted.
-- Note how the pivot itself ends up included in the middle part.
quickSort (x : xs) = (quickSort less) ++ (x : equal) ++ (quickSort more)
where
less = filter (< x) xs
equal = filter (== x) xs
more = filter (> x) xs
</syntaxhighlight>
It should be pointed out that our <code>quickSort</code> is rather naïve. A more efficient implementation would avoid the three passes through <code>filter</code> at each recursive step and not use <code>(++)</code> to build the sorted list. Furthermore, unlike our implementation, the ''original'' quicksort algorithm does the sorting in-place using mutability.<ref>The "true", in-place quicksort ''can'' be done in Haskell, but it requires some rather advanced tools that we will not discuss in the Beginners' Track.</ref> We will ignore such concerns for now, as we are more interested in the usage patterns of sorting functions, rather than in exact implementation.
=== The <code>Ord</code> class ===
Almost all the basic data types in Haskell are members of the <code>Ord</code> class, which is for ordering tests what <code>Eq</code> is for equality tests. The <code>Ord</code> class defines which ordering is the "natural" one for a given type. It provides a function called <code>compare</code>, with type:
<syntaxhighlight lang="haskell">
compare :: (Ord a) => a -> a -> Ordering
</syntaxhighlight>
<code>compare</code> takes two values and compares them, returning an <code>Ordering</code> value, which is <code>LT</code> if the first value is ''less than'' the second, <code>EQ</code> if it is ''equal'' and <code>GT</code> if it is ''greater than''. For an <code>Ord</code> type, <code>(<)</code>, <code>(==)</code> from <code>Eq</code> and <code>(>)</code> can be seen as shortcuts to <code>compare</code> that check for one of the three possibilities and return a <code>Bool</code> to indicate whether the specified ordering is true according to the <code>Ord</code> specification for that type. Note that each of the tests we use with <code>filter</code> in the definition of <code>quickSort</code> corresponds to one of the possible results of <code>compare</code>, and so we might have written, for instance, <code>less</code> as <code>less = filter (\y -> y `compare` x == LT) xs</code>.
== Choosing how to compare ==
With <code>quickSort</code>, sorting any list with elements in the <code>Ord</code> class is easy. Suppose we have a list of <code>String</code> and we want to sort them; we just apply <code>quickSort</code> to the list. For the rest of this chapter, we will use a pseudo-dictionary of just a few words (but dictionaries with thousands of words would work just as well):
<syntaxhighlight lang="haskell">
dictionary = ["I", "have", "a", "thing", "for", "Linux"]
</syntaxhighlight>
<code>quickSort dictionary</code> returns:
<syntaxhighlight lang="haskell">
["I", "Linux", "a", "for", "have", "thing"]
</syntaxhighlight>
As you can see, capitalization is considered for sorting by default. Haskell <code>String</code>s are lists of Unicode characters. Unicode (and almost all other encodings of characters) specifies that the character code for capital letters are less than the lower case letters. So "Z" is less than "a".
To get a proper dictionary-like sorting, we need a case insensitive <code>quickSort</code>. To achieve that, we can take a hint from the discussion of <code>compare</code> just above. The recursive case of <code>quickSort</code> can be rewritten as:
<syntaxhighlight lang="haskell">
quickSort compare (x : xs) = (quickSort compare less) ++ (x : equal) ++ (quickSort compare more)
where
less = filter (\y -> y `compare` x == LT) xs
equal = filter (\y -> y `compare` x == EQ) xs
more = filter (\y -> y `compare` x == GT) xs
</syntaxhighlight>
While this version is less tidy than the original one, it makes it obvious that the ordering of the elements hinges entirely on the <code>compare</code> function. That means we only need to replace <code>compare</code> with an {{nowrap|1=<code>(Ord a) => a -> a -> Ordering</code>}} function of our choice. Therefore, our updated <code>quickSort'</code> is a higher-order function which takes a comparison function along with the list to sort.
<syntaxhighlight lang="haskell">
quickSort' :: (Ord a) => (a -> a -> Ordering) -> [a] -> [a]
-- No matter how we compare two things the base case doesn't change,
-- so we use the _ "wildcard" to ignore the comparison function.
quickSort' _ [] = []
-- c is our comparison function
quickSort' c (x : xs) = (quickSort' c less) ++ (x : equal) ++ (quickSort' c more)
where
less = filter (\y -> y `c` x == LT) xs
equal = filter (\y -> y `c` x == EQ) xs
more = filter (\y -> y `c` x == GT) xs
</syntaxhighlight>
We can reuse our <code>quickSort'</code> function to serve many different purposes.
If we wanted a ''descending'' order, we could just reverse our original sorted list with <code>reverse (quickSort dictionary)</code>. Yet to actually do the initial sort descending, we could supply <code>quickSort'</code> with a comparison function that returns the opposite of the usual <code>Ordering</code>.
<syntaxhighlight lang="haskell">
-- the usual ordering uses the compare function from the Ord class
usual = compare
-- the descending ordering, note we flip the order of the arguments to compare
descending x y = compare y x
-- the case-insensitive version is left as an exercise!
insensitive = ...
-- How can we do case-insensitive comparisons without making a big list of all possible cases?
</syntaxhighlight>
{{body note|<code>Data.List</code> offers a <code>sort</code> function for sorting lists. It does not use quicksort; rather, it uses an efficient implementation of an algorithm called ''mergesort''. <code>Data.List</code> also includes <code>sortBy</code>, which takes a custom comparison function just like our <code>quickSort'</code>}}
{{Exercises | Write <code>insensitive</code>, such that <code>quickSort' insensitive dictionary</code> gives <code>["a", "for", "have", "I", "Linux", "thing"]</code>.}}
== Higher-Order Functions and Types ==
{{Confusing}}
The concept of ''currying'' (the generating of intermediate functions on the way toward a final result) was first introduced in the earlier chapter "Lists II". This is a good place to revisit how currying works.
Our <code>quickSort'</code> has type <code>(a -> a -> Ordering) -> [a] -> [a]</code>.
Most of the time, the type of a higher-order function provides a guideline about how to use it. A straightforward way of reading the type signature would be "<code>quickSort'</code> takes, as its first argument, a function that gives an ordering of two <code>a</code>s. Its second argument is a list of <code>a</code>s. Finally, it returns a new list of <code>a</code>s". This is enough to correctly guess that it uses the given ordering function to sort the list.
Note that the parentheses surrounding <code>a -> a -> Ordering</code> are mandatory. They specify that <code>a -> a -> Ordering</code> forms a single argument that happens to be a function.
Without the parentheses, we would get <code>a -> a -> Ordering -> [a] -> [a]</code> which accepts four arguments (none of which are themselves functions) instead of the desired two, and that wouldn't work as desired.
Remember that the <code>-></code> operator is right-associative. Thus, our erroneous type signature <code>a -> a -> Ordering -> [a] -> [a]</code> means the same thing as <code>a -> (a -> (Ordering -> ([a] -> [a])))</code>.
Given that <code>-></code> is right-associative, the explicitly grouped version of the correct <code>quickSort'</code> signature is actually <code>(a -> a -> Ordering) -> ([a] -> [a])</code>. This makes perfect sense. Our original <code>quickSort</code> lacking the adjustable comparison function argument was of type <code>[a] -> [a]</code>. It took a list and sorted it. Our new <code>quickSort'</code> is simply a function that generates <code>quickSort</code> style functions! If we plug in <code>compare</code> for the <code>(a -> a -> Ordering)</code> part, then we just return our original simple <code>quickSort</code> function. If we use a different comparison function for the argument, we generate a ''different'' variety of a <code>quickSort</code> function.
Of course, if we not only give a comparison function as an argument but also feed in an actual list to sort, then the final result is not the new <code>quickSort</code>-style function; instead, it continues on and passes the list to the new function and returns the sorted list as our final result.
{{Exercises|1=
''(Challenging)'' The following exercise combines what you have learned about higher order functions, recursion and I/O. We are going to recreate what is known in imperative languages as a ''for loop''. Implement a function
<pre>for :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO ()
for i p f job = -- ???</pre>
An example of how this function would be used might be
<pre>for 1 (<10) (+1) print</pre>
which prints the numbers 1 to 9 on the screen.
The desired behaviour of <code>for</code> is: starting from an initial value <code>i</code>, <code>for</code> first checks <code>p i</code>, if it evaluates to true it then executes <code>job i</code>, else it stops and does nothing. If <code> job i</code> was executed, it then uses <code>f</code> to modify this value and checks to see if the modified value <code>f i</code> satisfies some condition <code>p</code>. If it doesn't, it stops; otherwise, the for loop continues, using the modified <code>f i</code> in place of <code>i</code>.
# Implement the for loop in Haskell.
# The paragraph just above gives an imperative description of the for loop. Describe your implementation in more functional terms.
Some more challenging exercises you could try
# Consider a task like "print the list of numbers from 1 to 10". Given that <code>print</code> is a function, and we want to apply it to a list of numbers, using <code>map</code> sounds like the natural thing to do. But would it actually work?
# Implement a function <code>sequenceIO :: [IO a] -> IO [a]</code>. Given a list of actions, this function runs each of the actions in order and returns all their results as a list.
# Implement a function <code>mapIO :: (a -> IO b) -> [a] -> IO [b]</code> which given a function of type <code>a -> IO b</code> and a list of type <code>[a]</code>, runs that action on each item in the list, and returns the results.
This exercise was inspired from a blog post by osfameron. No peeking!
}}
== Function manipulation ==
We will close the chapter by discussing a few examples of common and useful general-purpose higher-order functions. Familiarity with these will greatly enhance your skill at both writing and reading Haskell code.
=== Flipping arguments ===
<code>flip</code> is a handy little Prelude function. It takes a function of two arguments and returns a version of the same function with the arguments swapped.
<syntaxhighlight lang="haskell">flip :: (a -> b -> c) -> b -> a -> c</syntaxhighlight>
<code>flip</code> in use:
{{Haskell/GHCi|1=
Prelude> (flip (/)) 3 1
0.3333333333333333
Prelude> (flip map) [1,2,3] (*2)
[2,4,6]
}}
We could have used flip to write a point-free version of the <code>descending</code> comparing function from the quickSort example:
<syntaxhighlight lang="haskell">descending = flip compare</syntaxhighlight>
<code>flip</code> is particularly useful when we want to pass a function with two arguments of different types to another function and the arguments are in the wrong order with respect to the signature of the higher-order function.
=== Composition ===
The <code>(.)</code> composition operator is another higher-order function. It has the signature:
<syntaxhighlight lang="haskell">(.) :: (b -> c) -> (a -> b) -> a -> c</syntaxhighlight>
<code>(.)</code> takes two functions as arguments and returns a new function which applies the second function to the argument and then the first. (Writing the type of <code>(.)</code> as <code>(b -> c) -> (a -> b) -> (a -> c)</code> can make that easier to see.)
Composition and higher-order functions provide a range of powerful tricks. For a tiny sample, first consider the
<code>inits</code> function, defined in the module <code>Data.List</code>. Quoting the documentation, it "returns all initial segments of the argument, shortest first", so that:
{{Haskell/GHCi|1=
Prelude Data.List> inits [1,2,3]
[[],[1],[1,2],[1,2,3]]
}}
We can provide a one-line implementation for <code>inits</code> (written point-free for extra dramatic effect) using only the following higher-order functions from Prelude: <code>flip</code>, <code>scanl</code>, <code>(.)</code> and <code>map</code>:
<syntaxhighlight lang="haskell">
myInits :: [a] -> [[a]]
myInits = map reverse . scanl (flip (:)) []
</syntaxhighlight>
Swallowing a definition so condensed may look daunting at first, so analyze it slowly, bit by bit, recalling what each function does and using the type signatures as a guide.
The definition of <code>myInits</code> is super concise and clean with use of parentheses kept to a bare minimum. Naturally, if one goes overboard with composition by writing mile-long <code>(.)</code> chains, things will get confusing; but, when deployed reasonably, these point-free styles shine. Furthermore, the implementation is quite "high level": we do not deal explicitly with details like pattern matching or recursion; the functions we deployed — both the higher-order ones and their functional arguments — take care of such plumbing.
=== Application ===
<code>($)</code> is a curious higher-order operator. Its type is:
<syntaxhighlight lang="haskell">
($) :: (a -> b) -> a -> b
</syntaxhighlight>
It takes a function as its first argument, and ''all'' it does is to apply the function to the second argument, so that, for instance, <code>(head $ "abc") == (head "abc")</code>.
You might think that <code>($)</code> is completely useless! However, there are two interesting points about it. First, <code>($)</code> has very low precedence,<ref>As a reminder, precedence here is meant in the same sense that <code>*</code> has higher precedence (i.e. is evaluated first) than <code>+</code> in mathematics.</ref> unlike regular function application which has the highest precedence. In effect, that means we can avoid confusing nesting of parentheses by breaking precedence with <code>$</code>. We write a non-point-free version of <code>myInits</code> without adding new parentheses:
<syntaxhighlight lang="haskell">
myInits :: [a] -> [[a]]
myInits xs = map reverse . scanl (flip (:)) [] $ xs
</syntaxhighlight>
Furthermore, as <code>($)</code> is just a function which happens to apply functions, and functions are just values, we can write intriguing expressions such as:
<syntaxhighlight lang="haskell">
map ($ 2) [(2*), (4*), (8*)]
</syntaxhighlight>
(Yes, that is a list of functions, and it is perfectly legal.)
=== <code>uncurry</code> and <code>curry</code> ===
As the name suggests, <code>uncurry</code> is a function that undoes currying; that is, it converts a function of two arguments into a function that takes a pair as its only argument.
<syntaxhighlight lang="haskell">uncurry :: (a -> b -> c) -> (a, b) -> c</syntaxhighlight>
{{Haskell/GHCi|1=
Prelude> let addPair = uncurry (+)
Prelude> addPair (2, 3)
5
}}
One interesting use of <code>uncurry</code> occasionally seen in the wild is in combination with <code>($)</code>, so that the first element of a pair is applied to the second.
{{Haskell/GHCi|1=
Prelude> uncurry ($) (reverse, "stressed")
"desserts"
}}
There is also <code>curry</code>, which is the opposite of <code>uncurry</code>.
<syntaxhighlight lang="haskell">curry :: ((a, b) -> c) -> a -> b -> c</syntaxhighlight>
{{Haskell/GHCi|1=
Prelude> curry addPair 2 3 -- addPair as in the earlier example.
5
}}
Because most Haskell functions are already curried, <code>curry</code> is nowhere near as common as <code>uncurry</code>.
=== <code>id</code> and <code>const</code> ===
Finally, we should mention two functions which, while not higher-order functions themselves, are most often used as arguments to higher-order functions. <code>id</code>, the ''identity'' function, is a function with type {{nowrap|<code>a -> a</code>}} that returns its argument unchanged.
{{Haskell/GHCi|1=
Prelude> id "Hello"
"Hello"
}}
Similar in spirit to <code>id</code>, <code>const</code> is an {{nowrap|<code>a -> b -> a</code>}} function that works like this:
{{Haskell/GHCi|1=
Prelude> const "Hello" "world"
"Hello"
}}
<code>const</code> takes two arguments, discards the second and returns the first. Seen as a function of one argument, {{nowrap|<code>a -> (b -> a)</code>}}, it returns a constant function, which always returns the same value no matter what argument it is given.
<code>id</code> and <code>const</code> might appear worthless at first. However, when dealing with higher-order functions it is sometimes necessary to pass a dummy function, be it one that does nothing with its argument or one that always returns the same value. <code>id</code> and <code>const</code> give us convenient dummy functions for such cases.
{{Exercises|1=
# Write implementations for <code>curry</code>, <code>uncurry</code> and <code>const</code>.
# Describe what the following functions do without testing them:
#* <code>uncurry const</code>
#* <code>curry fst</code>
#* <code>curry swap</code>, where {{nowrap|<code>swap :: (a, b) -> (b, a)</code>}} swaps the elements of a pair. (<code>swap</code> can be found in <code>Data.Tuple</code>.)
# ''(Very hard)'' Use <code>foldr</code> to implement <code>foldl</code>. Hint: begin by reviewing the sections about <code>foldr</code> and <code>foldl</code> in [[Haskell/Lists III#foldr|Lists III]]. There are two solutions; one is easier but relatively boring and the other is truly interesting. For the interesting one, think carefully about how you would go about composing all functions in a list.
}}
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Elementary Haskell}}
{{BookCat}}
0qlmupn84v35ksrzgv7kp0015rvy2aq
Sexual Health/References
0
91491
4676006
3744604
2026-10-14T10:29:02Z
Jcb
90773
4676006
wikitext
text/x-wiki
{{Sexual Health}}
==Sex Cells==
#{{cite web | last = Krock | first = Lexi | title = Fertility Throughout Life | work = 18 Ways to Make a Baby | publisher = NOVA Online | date = October 2001 | url = http://www.pbs.org/wgbh/nova/baby/fert_text.html | accessdate = 2006-12-24 }}
#{{cite web | last = Haines | first = Cynthiac | title = Your Guide to the Female Reproductive System | work = The Cleveland Clinic Women's Health Center | publisher = WebMD | date = January 2006 | url = http://www.webmd.com/content/article/51/40619.htm | accessdate = 2006-12-24 }}
==Pregnancy==
#{{cite web | last = Reitzi | first = Cindy | title = The hardships of teen pregnancy | publisher = Wisconsin Education Association Council | date = April 2005 | url = http://www.weac.org/News/2004-05/april05/todaysclass.htm | accessdate = 2006-08-29 }}
#{{cite journal | author=Wilcox AJ, Baird DD, Weinberg CR | title=Time of implantation of the conceptus and loss of pregnancy. | journal=New England Journal of Medicine | volume=340 | issue=23 | pages=1796-1799 | year=1999 | id={{PMID|10362823}}}}
==Other Birth Control==
#{{cite journal | title = Researchers find no sperm in pre-ejaculate fluid | journal = Contraceptive Technology Update | volume = 14 | issue = 10 | pages = 154-156 | year = October 1993 | id = {{PMID|12286905}} }}
#{{cite journal | last = Zukerman | first = Z. | coauthors = Weiss D.B. Orvieto R.
| title = Short Communication: Does Preejaculatory Penile Secretion Originating from Cowper's Gland Contain Sperm? | journal = Journal of Assisted Reproduction and Genetics | volume = 20 | issue = 4 | pages = 157-159 | year = April 2003 | id = {{PMID|12762415}} }}
#Moore W. Searching for Dr Condom. BMJ 2008; 337:a1166.
in5k4x14r0zpcog55s3dcbcfx7hakr6
Adventist Youth Honors Answer Book/Health and Science/First Aid, Basic
0
91759
4675865
4627025
2026-10-13T16:15:01Z
~2026-55042-04
3628341
/* */
4675865
wikitext
text/x-wiki
{{honor_header|1|1951|Health and Science|General Conference}}
'''Note: The red oval on thhe patch designates “basic” level.'''
If residing in the United States or another country where Red Cross instruction is given,
satisfactorily pass the Red Cross Examination in Basic First Aid and receive your
certificate.
In British countries pass the examination in St. John Ambulance and receive certificate
for the same.
Or complete the following requirements:
==1. Know the causes of shock and demonstrate its proper treatment.==
{{:Adventist Youth Honors Answer Book/First aid/Shock}}
==2. Know the proper steps for rescue breathing.==
{{:Adventist Youth Honors Answer Book/First aid/Rescue_breathing}}
'''The following is in addition to the information above for review purposes. This teaches students how to handle live situations they may come upon.'''
In the next revision of the first aid honors the first aider needs to know what to do when they come across an accident of any type. They will need to know the correct procedures in their correct order. This is not currently addressed anywhere in any of the Basic, Standard, Advanced First Aid Honors.
It is important to check for a pulse before anyone attempts to carry out CPR. If the heart is beating you '''do not''' perform CPR. CPR is to maintain the blood flow in place of the beating heart in order to carry the air you are breathing into the victim to the victim's brain. Usually if the heart is not beating there is no breathing, but it is possible for breathing to stop while the heart is still beating.
Whenever an accident or emergency occurs and you are the first person to arrive at the scene, there is one important technique to follow first: Check Call Care (see below). Then use DRABC to care for the victim.
Oh No! There's been an accident! What do I do first?
'''Check Call Care'''
;Check: To Check for danger, you must first survey the scene to ensure ''your own safety;'' then, do a primary survey.
;Call: After checking the victim, call an ambulance, giving them a description of the emergency situation as well as the location of the scene.
;Care: After calling the ambulance, provide appropriate care based on your primary survey of the victim until an ambulance or other advance medical personnel arrives and takes over.
'''DRABC'''
;Danger:
Before you try to help the victim, you must determine if the scene is safe. If anything dangerous is present, such as a live wire, a vicious animal, deep water, or fire, you cannot endanger your own life to try to help the victim. Summon trained medical personnel immediately, and they will handle the situation. If you get hurt at the scene, you end up as just another victim for the ambulance to treat. Once you have called for help, you have done all you can in such a situation.
If the scene is safe, try to determine what may have happened or what caused the accident. Never move the victim to give treatment unless immediate life-threatening danger exists, such as a fire or an unstable structure ready to collapse.
;Response:
After determining that the scene is safe, you must check for a response in the victim. You will look, listen and feel to determine if the victim:
# Is conscious
# Has an open, unobstructed airway
# Is breathing
# Has a heartbeat
# Is not bleeding severely
To check for consciousness, gently tap the victim and ask, "Are you okay?" If the victim can speak or cry, he or she is conscious, breathing, and has a pulse. If the victim is unresponsive, he or she may be unconscious, indicating a possibly life-threatening condition. An unconscious person's tongue relaxes and may fall back to block the airway, stopping breathing and eventually the heartbeat.
Next, if the victim is unconscious, kneel next to the victim's head and check for the ABC's: Airway, Breathing and Circulation.
;Airway:
To open the airway of an unconscious victim, tilt the head back and lift the chin.
;Breathing:
To check for breathing, you must look, listen and feel. Place your face above the victim's mouth and nose, so that you can listen and feel for air being exhaled while watching the victim's chest for a gentle rise and fall that occurs when breathing. If the victim is not breathing, you must give 2 slow breaths. This is called rescue breathing. If the breaths do not go in, retilt the head and try again. If the breaths still do not go in, the victim has an obstructed airway, and you may try to clear the airway with a blow between the shoulder blades in the back, or with abdominal thrusts. If the breaths do go in, then continue with your DRABC.
;Circulation:
To check for circulation, you must check the victim's pulse at one of the carotid arteries, located in the neck on either side of the Adam's apple. Using your index and middle finger (Never use your thumb—it has its own pulse and you may mistake it for that of the victim!) find the Adam's apple and then slide your fingers toward the side of the neck facing you into the groove in the side of the neck. Take at least 5 to 10 seconds to feel for the pulse. If the victim is an infant, locate the pulse in the brachial artery, on the inside of the upper arm in between the elbow and the shoulder. If the victim has a pulse but is not breathing, you must go immediately do Rescue Breathing. If the victim is not breathing and does not have a pulse, go immediately to CPR (if you have been trained). Check the body for signs of any severe external bleeding (bleeding is severe when blood spurts from a wound, and it is life-threatening).
==3. Know the proper procedures to assist a choking victim.==
{{:Adventist Youth Honors Answer Book/First aid/Choking}}
==4. Know the proper procedures to assist a bleeding victim.==
{{:Adventist Youth Honors Answer Book/First aid/Bleeding}}
==5. Know the pressure points and how to correctly apply pressure at these points.==
{{:Adventist Youth Honors Answer Book/First aid/Pressure_points}}
==6. Know the proper procedure to assist a victim of poisoning.==
{{:Adventist Youth Honors Answer Book/First aid/Poison}}
==7. Demonstrate the proper procedure in splinting various broken bones in the body.==
'''Splints'''
{{:Adventist Youth Honors Answer Book/First aid/Splints}}
'''Forearm'''
{{:Adventist Youth Honors Answer Book/First aid/Forearm_splint}}
'''Upper Arm'''
{{:Adventist Youth Honors Answer Book/First aid/Upper_arm_splint}}
'''Kneecap'''
{{:Adventist Youth Honors Answer Book/First aid/Kneecap_splint}}
'''Ankle'''
{{:Adventist Youth Honors Answer Book/First aid/Ankle_splint}}
==8. Know the proper procedure to assist the burn victim.==
==9. Know the proper procedure to assist a victim of a chemical burn.==
{{:Adventist Youth Honors Answer Book/First aid/Chemical_burn}}
==10. Know what situations are likely to cause carbon monoxide poisoning and the rescue and treatment techniques for such poisoning.==
{{:Adventist Youth Honors Answer Book/First aid/Carbon_monoxide}}
==11. Know the proper procedure for giving assistance to the victim of a head injury.==
{{:Adventist Youth Honors Answer Book/First aid/Head_injury}}
==12. Know the proper procedure for giving aid to a victim of internal injuries.==
{{:Adventist Youth Honors Answer Book/First aid/Internal injuries}}
==13. Know the difference between a heart attack, stroke, epilepsy, and simple fainting, and the treatment for each.==
===Heart Attack===
{{:Adventist Youth Honors Answer Book/First aid/Heart_attack}}
===Stroke===
{{:Adventist Youth Honors Answer Book/First aid/Stroke}}
===Epilepsy===
{{:Adventist Youth Honors Answer Book/First aid/Epilepsy}}
===Fainting===
{{:Adventist Youth Honors Answer Book/First aid/Fainting}}
==14. Know how to prevent infection.==
Although infection may occur in any wound, it is a particular danger in wounds that do not bleed freely; in wounds in which torn tissue or skin falls back into place and prevents the entrance of air; and in wounds that involve the crushing of tissues. Incisions, in which there is a free flow of blood and relatively little crushing of tissues, are the least likely to become infected.
There are two types of bacteria commonly causing infection in wounds—aerobic and anaerobic. The former bacterial live and multiply in the presence of air or free oxygen, while the latter are bacterial that live and multiply only in the absence of air.
The principal aerobic bacteria that cause infection, inflammation, and blood poisoning are streptococci and staphylococci, some varieties of which destroy red blood cells. The staphylococci and streptococci may be introduced at the time of infliction, or they may be introduced to the wound later, at the time of first aid treatment or in the hospital if nonsterile instruments or dressings are employed.
Wash minor wounds immediately with soap and clean water; then dry and paint them with a mild, nonirritating antiseptic. Apply a dressing if necessary. In the first aid environment, do not attempt to wash or clean a large wound, and do not apply an antiseptic to it since it must be cleaned thoroughly at a medical treatment facility. Simply protect it with a large compress or dressing and transport the victim to a medical treatment facility. After an initial soap and water cleanup, puncture wounds must also be directed to a medical treatment facility for evaluation.
==15. What is the proper treatment for a snake bite?==
{{:Adventist Youth Honors Answer Book/First aid/Snake bite}}
Seek medical attention as quickly as possible.
Apply first aid treatment:
Remove any jewelry or watches, as these could cut into the skin if swelling occurs.
Keep the area of the bite below the level of the heart in order to slow the spread of venom through the bloodstream.
Remain still and calm. Moving around will make venom spread faster through the body.
Cover the bite with a clean, loose-fitting, dry bandage.
The main goal is to administer the correct antivenom as soon as possible. Knowing the size, color and shape of the snake can help determine the best treatment for a particular bite.
Antivenoms are made by immunizing a horse or sheep with the venom of a particular snake, then processing the animal's blood serum (the watery part of the blood), which will contain antibodies capable of neutralizing the effects of venom.
Monospecific antivenoms treat the bite of a specific type of snake, while polyspecific antivenoms can treat bites from a number of snakes found in a particular geographic region.
The following is a list of DO NOTs:
Do not pick up the snake or try to wrap it up or kill it, as this will increase the chance of getting another bite. Even a dead snake is able to bite.
Do not apply a tourniquet.
Do not cut across the site of the bite marks.
Do not try to suck out the venom.
Do not apply ice.
Do not immerse the wounded area in water.
Do not drink alcohol.
Do not drink beverages with caffeine.
==16. What is the proper treatment for animal bites?==
{{:Adventist Youth Honors Answer Book/First aid/Animal_bites}}
==17. What is the proper treatment for insect and spider bites?==
'''Insect Bites'''
{{:Adventist Youth Honors Answer Book/First aid/Insect_bites}}
'''Spider Bites'''
{{:Adventist Youth Honors Answer Book/First aid/Spider_bites}}
==18. What is the difference between heat exhaustion and heat stroke, and what is the treatment for each?==
===Heat stroke===
{{:Adventist Youth Honors Answer Book/First aid/Heat stroke}}
===Heat Exhaustion===
{{:Adventist Youth Honors Answer Book/First aid/Heat exhaustion}}
==19. What should you do if your clothes catch fire?==
{{:Adventist Youth Honors Answer Book/First aid/Clothes_on_fire}}
==20. What are the basic fire prevention principles for the home?==
* If your home lacks smoke detectors, install them
* Replace the batteries and test your smoke detectors on a regular basis (when adjusting your clocks for daylight savings time, for example).
* Do not smoke or allow anyone else to smoke in your home.
* Never overload circuits or extension cords. Do not place cords and wires under rugs, over nails or in high traffic areas. Immediately shut off and unplug appliances that sputter, spark or emit an unusual smell. Have them professionally repaired or replaced.
* When using appliances follow the manufacturer's safety precautions. Overheating, unusual smells, shorts and sparks are all warning signs that appliances need to be shut off, then replaced or repaired. Unplug appliances when not in use. Use safety caps to cover all unused outlets, especially if there are small children in the home.
* Portable heaters need their space. Keep anything combustible at least three feet away.
* Keep fire in the fireplace. Use fire screens and have your chimney cleaned annually. The creosote buildup can ignite a chimney fire that could easily spread.
* Kerosene heaters should be used only where approved by authorities. Never use gasoline or camp-stove fuel. Refuel outside and only after the heater has cooled.
* Practice an escape plan from every room in the house. Caution everyone to stay low to the floor when escaping from fire and never to open doors that are hot. Select a location where everyone can meet after escaping the house. Get out then call for help.
*
==21. What are the basic water safety principles?==
* Learn to swim.
* Swim in areas where a lifeguard is on duty
* Young children and weak swimmers should wear a personal floatation device (PFD) when they are around water.
* Set limits for inexperienced swimmers, such as not allowing them to enter water that is more than chest-deep.
* Inspect swimming areas for hazards such as underwater trees, holes, and swift currents.
* Swim parallel to the shore if caught in a rip tide.
* Get out of the water if there is a risk of a lightning strike.
==22. What are the ways to save a drowning victim without swimming?==
{{:Adventist Youth Honors Answer Book/First aid/Non-swimming rescue}}
==23. What are the basic electrical safety principles?==
* Do not overload circuits or extension cords.
* Only use an extension cord that is rated to handle the current an appliance will use. An appliance's amperage is listed on the outside of the appliance.
* Shut off the power before working on a circuit.
* Unplug an appliance before servicing it.
* Water and electricity do not mix. Do not use an electric appliance when standing in a puddle of water or while in a bathtub or shower.
* Do not use a land-line telephone or touch any "wired" appliance during an electrical storm.
* Do not insert anything into an electrical socket other than an electrical plug which is in good condition or an outlet safety cover.
* Replace broken or frayed electrical cords.
==24. How can you prevent food poisoning?==
Food poisoning is causes by eating food which is contaminated with any infectious or toxic agent such as bacteria or parasites. The two main ways food becomes contaminated is by improper storage, or by coming into contact with contaminated food (cross-contamination).
===Food Storage===
The basic rule for storing food is to pay attention to the temperature. Keep hot foods hot, and keep cold foods cold. Most bacteria will not grow in food that is hotter than 140 °F (60 °C), and bacterial growth is greatly slowed at temperatures below 40 °F (4 °C). It is unsafe to store foods susceptible to bacteria growth between these temperatures.
Food poisoning is often caused by eating left-overs that were not promptly refrigerated. As soon as the food temperature falls below 140 °F (60 °C), it should be refrigerated. The longer food is left in the "danger zone", the more bacteria will multiply in it. If it contains enough bacteria, it will overwhelm the body's immune system and sickness will result.
Be careful about refrigerating large quantities of hot food. For instance, the potato salad in the center of a two-gallon container can remain warm for ''hours'' after refrigeration - providing ample time for bacteria to multiply. Divide large quantities of food into smaller containers prior to refrigeration so that the food can cool throughout.
===Cross Contamination===
Cross contamination usually happens during food preparation. Raw meat and raw eggs should always be treated as if they were contaminated. Cooking them kills the bacteria and makes them safe to eat. Do not allow other food to come into contact with raw meat or eggs, or that food will become contaminated. Do not use the same utensils to handle raw meat and food that is ready to eat.
Wash your hands before you eat or cook, and always wash your hands after handling raw meat or eggs - before handling any other food.
Do not allow pets to walk on food preparation surfaces (i.e., don't let the cat walk on the counter top or dining table). Animals pick up many types of bacteria on their feet, and this is easily transferred to food. If you do catch your pet walking on the countertop, be sure to disinfect it before using it as a food preparation surface.
==References==
Wikipedia references:
*[[w:Abdominal thrusts|Abdominal Thrusts]]
Some material for this chapter was copied directly from the following public domain resources:
*[http://www.tpub.com/content/medical/10669-c/ U.S. Navy Training Manual, HOSPITAL CORPSMAN 3 & 2]
*[http://www.tpub.com/content/medical/14295/index.htm U.S. Navy Training Manual, Hospital Corpsman Revised Edition]
*[http://www.usfa.dhs.gov/safety/tips/ Department of Homeland Security, Fire Safety Tips]
{{reflist}}
[[{{BOOKCATEGORY|Adventist Youth Honors Answer Book}}|{{SUBPAGENAME}}]]
[[{{BOOKCATEGORY|Adventist Youth Honors Answer Book}}/Completed Honors|{{SUBPAGENAME}}]]
a294zf4niusyh52w1phg9npsco27u9e
Haskell/Print version
0
92072
4675941
4342276
2026-10-14T00:15:17Z
~2026-54868-50
3628373
4675941
wikitext
text/x-wiki
__NOTOC__ __NOEDITSECTION__
{{Print version notice|Haskell|Haskell/Print_version}}
<noinclude>
= Table Of Contents =
== Haskell Basics ==
:{{Haskell chapter/Haskell Basics|sep=
:}}
== Elementary Haskell ==
:{{Haskell/Elementary Haskell|sep=
:}}
== Intermediate Haskell ==
:{{Haskell/Intermediate Haskell|sep=
:}}
== Monads ==
:{{Haskell/Monads|firstsep=:|subsep=:|sep=
:}}
== Advanced Haskell ==
:{{Haskell/Advanced Haskell|sep=
:}}
== Fun with Types ==
:{{Haskell/Fun with Types|sep=
:}}
== Wider Theory ==
:{{Haskell/Wider Theory|sep=
:}}
== Haskell Performance ==
:{{Haskell/Haskell Performance|sep=
:}}
== Libraries Reference ==
:{{Haskell/Libraries|sep=
:}}
== General Practices ==
:{{Haskell/General Practices|sep=
:}}
== Specialised Tasks ==
:{{Haskell/Specialised Tasks|sep=
:}}
</noinclude>
----
= Haskell Basics =
----
= Getting set up =
{{:Haskell/Getting set up}}
= Variables and functions =
{{:Haskell/Variables and functions}}
= Truth values =
{{:Haskell/Truth values}}
= Type basics =
{{:Haskell/Type basics}}
= Lists and tuples =
{{:Haskell/Lists and tuples}}
= Type basics II =
{{:Haskell/Type basics II}}
= Building vocabulary =
{{:Haskell/Building vocabulary}}
= Next steps =
{{:Haskell/Next steps}}
= Simple input and output =
{{:Haskell/Simple input and output}}
----
= Elementary Haskell =
----
= Recursion =
{{:Haskell/Recursion}}
= Lists II =
{{:Haskell/Lists II}}
= Lists III =
{{:Haskell/Lists III}}
= Type declarations =
{{:Haskell/Type declarations}}
= Pattern matching =
{{:Haskell/Pattern matching}}
= Control structures =
{{:Haskell/Control structures}}
= More on functions =
{{:Haskell/More on functions}}
= Higher-order functions =
{{:Haskell/Higher-order functions}}
= Using GHCi effectively =
{{:Haskell/Using GHCi effectively}}
----
= Intermediate Haskell =
----
= Modules =
{{:Haskell/Modules}}
= Indentation =
{{:Haskell/Indentation}}
= More on datatypes =
{{:Haskell/More on datatypes}}
= Other data structures =
{{:Haskell/Other data structures}}
= Classes and types =
{{:Haskell/Classes and types}}
= The Functor class =
{{:Haskell/The Functor class}}
----
= Monads =
----
= Prologue: IO, an applicative functor =
{{:Haskell/Prologue: IO, an applicative functor}}
= Understanding monads =
{{:Haskell/Understanding monads}}
= The Maybe monad =
{{:Haskell/Understanding monads/Maybe}}
= The List monad =
{{:Haskell/Understanding monads/List}}
= <code>do</code> Notation =
{{:Haskell/do notation}}
= The IO monad =
{{:Haskell/Understanding monads/IO}}
= The State monad =
{{:Haskell/Understanding monads/State}}
= Alternative and MonadPlus =
{{:Haskell/Alternative and MonadPlus}}
= Monad transformers =
{{:Haskell/Monad transformers}}
----
= Advanced Haskell =
----
= Monoids =
{{:Haskell/Monoids}}
= Applicative functors =
{{:Haskell/Applicative functors}}
= Foldable =
{{:Haskell/Foldable}}
= Traversable =
{{:Haskell/Traversable}}
= Arrow tutorial =
{{:Haskell/Arrow tutorial}}
= Understanding arrows =
{{:Haskell/Understanding arrows}}
= Continuation passing style (CPS) =
{{:Haskell/Continuation passing style}}
= Zippers =
{{:Haskell/Zippers}}
= Lenses and functional references =
{{:Haskell/Lenses and functional references}}
= Mutable objects =
{{:Haskell/Mutable objects}}
= Concurrency =
{{:Haskell/Concurrency}}
----
= Fun with Types =
----
= Polymorphism basics =
{{:Haskell/Polymorphism}}
= Existentially quantified types =
{{:Haskell/Existentially quantified types}}
= Advanced type classes =
{{:Haskell/Advanced type classes}}
= Phantom types =
{{:Haskell/Phantom types}}
= Generalised algebraic data-types (GADT) =
{{:Haskell/GADT}}
<noinclude>
= Datatype algebra =
{{:Haskell/Datatype algebra}}
</noinclude>
= Type constructors & Kinds =
{{:Haskell/Kinds}}
----
= Wider Theory =
----
= Denotational semantics =
{{:Haskell/Denotational semantics}}
<noinclude>
= Equational reasoning =
{{:Haskell/Equational reasoning}}
</noinclude>
<noinclude>
= Program derivation =
{{:Haskell/Program derivation}}
</noinclude>
= Category theory =
{{:Haskell/Category theory}}
= The Curry-Howard isomorphism =
{{:Haskell/The Curry–Howard isomorphism}}
= fix and recursion =
{{:Haskell/Fix and recursion}}
----
= Haskell Performance =
----
= Introduction =
{{:Haskell/Performance introduction}}
= Step by Step Examples =
{{:Haskell/Performance examples}}
= Graph reduction =
{{:Haskell/Graph reduction}}
= Laziness =
{{:Haskell/Laziness}}
= Strictness =
{{:Haskell/Strictness}}
= Algorithm complexity =
{{:Haskell/Algorithm complexity}}
<noinclude>
= Data structures =
{{:Haskell/Data structures}}
</noinclude>
<noinclude>
= Parallelism =
{{:Haskell/Parallelism}}
</noinclude>
----
= Libraries Reference =
----
= The Hierarchical Libraries =
{{:Haskell/Libraries}}
= Lists =
{{:Haskell/Hierarchical libraries/Lists}}
= Arrays =
{{:Haskell/Libraries/Arrays}}
= Maybe =
{{:Haskell/Libraries/Maybe}}
= Maps =
{{:Haskell/Libraries/Maps}}
= IO =
{{:Haskell/Libraries/IO}}
= Random Numbers =
{{:Haskell/Libraries/Random}}
----
= General Practices =
----
= Building a standalone application =
{{:Haskell/Standalone programs}}
= Debugging =
{{:Haskell/Debugging}}
= Testing =
{{:Haskell/Testing}}
= Packaging your software (Cabal) =
{{:Haskell/Packaging}}
= Using the Foreign Function Interface (FFI) =
{{:Haskell/FFI}}
= Generic Programming : Scrap your boilerplate =
{{:Haskell/SYB}}
----
= Specialised Tasks =
----
= Graphical user interfaces (GUI) =
{{:Haskell/GUI}}
= Databases =
{{:Haskell/Database}}
= Web programming =
{{:Haskell/Web programming}}
= Working with XML =
{{:Haskell/XML}}
= Using Regular Expressions =
{{:Haskell/RegExp}}
= Parsing Mathematical Expressions =
{{:Haskell/ParseExps}}
o5iqx51x8zxzszsuqkp2tx86oytf8on
4675942
4675941
2026-10-14T00:19:07Z
~2026-54868-50
3628373
4675942
wikitext
text/x-wiki
__NOTOC__ __NOEDITSECTION__
{{Print version notice|Haskell|Haskell/Print_version}}
<noinclude>
= Table Of Contents =
== Haskell Basics ==
:{{Haskell/Haskell Basics|sep=
:}}
== Elementary Haskell ==
:{{Haskell/Elementary Haskell|sep=
:}}
== Intermediate Haskell ==
:{{Haskell/Intermediate Haskell|sep=
:}}
== Monads ==
:{{Haskell/Monads|firstsep=:|subsep=:|sep=
:}}
== Advanced Haskell ==
:{{Haskell/Advanced Haskell|sep=
:}}
== Fun with Types ==
:{{Haskell/Fun with Types|sep=
:}}
== Wider Theory ==
:{{Haskell/Wider Theory|sep=
:}}
== Haskell Performance ==
:{{Haskell/Haskell Performance|sep=
:}}
== Libraries Reference ==
:{{Haskell/Libraries|sep=
:}}
== General Practices ==
:{{Haskell/General Practices|sep=
:}}
== Specialised Tasks ==
:{{Haskell/Specialised Tasks|sep=
:}}
</noinclude>
----
= Haskell Basics =
----
= Getting set up =
{{:Haskell/Getting set up}}
= Variables and functions =
{{:Haskell/Variables and functions}}
= Truth values =
{{:Haskell/Truth values}}
= Type basics =
{{:Haskell/Type basics}}
= Lists and tuples =
{{:Haskell/Lists and tuples}}
= Type basics II =
{{:Haskell/Type basics II}}
= Building vocabulary =
{{:Haskell/Building vocabulary}}
= Next steps =
{{:Haskell/Next steps}}
= Simple input and output =
{{:Haskell/Simple input and output}}
----
= Elementary Haskell =
----
= Recursion =
{{:Haskell/Recursion}}
= Lists II =
{{:Haskell/Lists II}}
= Lists III =
{{:Haskell/Lists III}}
= Type declarations =
{{:Haskell/Type declarations}}
= Pattern matching =
{{:Haskell/Pattern matching}}
= Control structures =
{{:Haskell/Control structures}}
= More on functions =
{{:Haskell/More on functions}}
= Higher-order functions =
{{:Haskell/Higher-order functions}}
= Using GHCi effectively =
{{:Haskell/Using GHCi effectively}}
----
= Intermediate Haskell =
----
= Modules =
{{:Haskell/Modules}}
= Indentation =
{{:Haskell/Indentation}}
= More on datatypes =
{{:Haskell/More on datatypes}}
= Other data structures =
{{:Haskell/Other data structures}}
= Classes and types =
{{:Haskell/Classes and types}}
= The Functor class =
{{:Haskell/The Functor class}}
----
= Monads =
----
= Prologue: IO, an applicative functor =
{{:Haskell/Prologue: IO, an applicative functor}}
= Understanding monads =
{{:Haskell/Understanding monads}}
= The Maybe monad =
{{:Haskell/Understanding monads/Maybe}}
= The List monad =
{{:Haskell/Understanding monads/List}}
= <code>do</code> Notation =
{{:Haskell/do notation}}
= The IO monad =
{{:Haskell/Understanding monads/IO}}
= The State monad =
{{:Haskell/Understanding monads/State}}
= Alternative and MonadPlus =
{{:Haskell/Alternative and MonadPlus}}
= Monad transformers =
{{:Haskell/Monad transformers}}
----
= Advanced Haskell =
----
= Monoids =
{{:Haskell/Monoids}}
= Applicative functors =
{{:Haskell/Applicative functors}}
= Foldable =
{{:Haskell/Foldable}}
= Traversable =
{{:Haskell/Traversable}}
= Arrow tutorial =
{{:Haskell/Arrow tutorial}}
= Understanding arrows =
{{:Haskell/Understanding arrows}}
= Continuation passing style (CPS) =
{{:Haskell/Continuation passing style}}
= Zippers =
{{:Haskell/Zippers}}
= Lenses and functional references =
{{:Haskell/Lenses and functional references}}
= Mutable objects =
{{:Haskell/Mutable objects}}
= Concurrency =
{{:Haskell/Concurrency}}
----
= Fun with Types =
----
= Polymorphism basics =
{{:Haskell/Polymorphism}}
= Existentially quantified types =
{{:Haskell/Existentially quantified types}}
= Advanced type classes =
{{:Haskell/Advanced type classes}}
= Phantom types =
{{:Haskell/Phantom types}}
= Generalised algebraic data-types (GADT) =
{{:Haskell/GADT}}
<noinclude>
= Datatype algebra =
{{:Haskell/Datatype algebra}}
</noinclude>
= Type constructors & Kinds =
{{:Haskell/Kinds}}
----
= Wider Theory =
----
= Denotational semantics =
{{:Haskell/Denotational semantics}}
<noinclude>
= Equational reasoning =
{{:Haskell/Equational reasoning}}
</noinclude>
<noinclude>
= Program derivation =
{{:Haskell/Program derivation}}
</noinclude>
= Category theory =
{{:Haskell/Category theory}}
= The Curry-Howard isomorphism =
{{:Haskell/The Curry–Howard isomorphism}}
= fix and recursion =
{{:Haskell/Fix and recursion}}
----
= Haskell Performance =
----
= Introduction =
{{:Haskell/Performance introduction}}
= Step by Step Examples =
{{:Haskell/Performance examples}}
= Graph reduction =
{{:Haskell/Graph reduction}}
= Laziness =
{{:Haskell/Laziness}}
= Strictness =
{{:Haskell/Strictness}}
= Algorithm complexity =
{{:Haskell/Algorithm complexity}}
<noinclude>
= Data structures =
{{:Haskell/Data structures}}
</noinclude>
<noinclude>
= Parallelism =
{{:Haskell/Parallelism}}
</noinclude>
----
= Libraries Reference =
----
= The Hierarchical Libraries =
{{:Haskell/Libraries}}
= Lists =
{{:Haskell/Hierarchical libraries/Lists}}
= Arrays =
{{:Haskell/Libraries/Arrays}}
= Maybe =
{{:Haskell/Libraries/Maybe}}
= Maps =
{{:Haskell/Libraries/Maps}}
= IO =
{{:Haskell/Libraries/IO}}
= Random Numbers =
{{:Haskell/Libraries/Random}}
----
= General Practices =
----
= Building a standalone application =
{{:Haskell/Standalone programs}}
= Debugging =
{{:Haskell/Debugging}}
= Testing =
{{:Haskell/Testing}}
= Packaging your software (Cabal) =
{{:Haskell/Packaging}}
= Using the Foreign Function Interface (FFI) =
{{:Haskell/FFI}}
= Generic Programming : Scrap your boilerplate =
{{:Haskell/SYB}}
----
= Specialised Tasks =
----
= Graphical user interfaces (GUI) =
{{:Haskell/GUI}}
= Databases =
{{:Haskell/Database}}
= Web programming =
{{:Haskell/Web programming}}
= Working with XML =
{{:Haskell/XML}}
= Using Regular Expressions =
{{:Haskell/RegExp}}
= Parsing Mathematical Expressions =
{{:Haskell/ParseExps}}
5rd6rvq5rgyieyprio6j616z158f5am
Radiation Oncology/Rectum/Overview
0
93611
4675997
4533026
2026-10-14T09:31:35Z
Jcb
90773
4675997
wikitext
text/x-wiki
{{Radiation Oncology:TOC}}
==Epidemiology==
*40,000 cases annually in US
*Equal distribution among males and females
*Median age 7th decade
*Dietary risk: high fat, low residue, low antioxidants
*Presentation: BRBPR or change in BM, also narrowing of stools, pain
*Histology: adenocarcinoma
==Anatomy==
*Squamous mucosa ends at dentate line, approximately 2 cm above anal verge
*Internal anal sphincter muscles end another 3 cm cephalad, approximately 5 cm above anal verge
<br>
Relations to peritoneum: (see also at [[Radiation Oncology/Colon#Anatomy|Colon]])
*sigmoid colon: intraperitoneal
*rectum:
**upper third: covered by peritoneum on the anterior wall and both sides
**middle third: covered by peritoneum only on the anterior wall
**lower third: infraperitoneal
<br>
Margins and gross anatomy:
*Margins to assess:
**For tumor above the anterior peritoneal reflection: serosal margin and radial margin
**For tumor below the anterior reflection: circumferential radial margin
*see [https://www.cancercare.on.ca/common/pages/UserFile.aspx?fileId=130364 Cancer Care Ontario: Rectal Cancer Grossing Guideline]
**Images of mesorectal excision, showing:
***1) Anterior surface and posterior surface of rectal specimen, denoting peritoneal reflection and mesorectum. The peritoneal reflection is low anteriorly, high posteriorly. The resection margin of the mesorectum is non-circumferential above the reflection and is circumferential (the CRM) below the reflection.
***2) Cancers that are located below the posterior peritoneal reflection but above the anterior reflection have a serosal margin anteriorly as well as a non-circumferential radial margin posteriorly. Cancers below the anterior reflection have a circumferential resection margin (CRM).
'''Nodal drainage:'''
*At risk - internal iliac, presacral
**Include external iliac if tumor invades bladder, vagina, prostate, or cervix
**Include inguinal nodes if tumor extends to or is caudal to the dentate line
==Recurrence patterns==
*1 - Presacral space
*2 - Anastomosis, or perineum if APR
*3 - Pelvis, including posterior wall of bladder
*<10% involve common illiac or paraaortic LNs
*Metastatic - liver and lung. Inguinal LNs uncommon
{| border="1"
|+ '''Locoregional and Total Failures'''
! Stage N0 !! LR !! TR || Stage N+ || LR || TR
|-
|T1-2N0 || 10% || 15% || T1-2N+ || 50% || 70%
|-
|T3N0 || 25% || 40% || T3N+ || 40% || 70%
|-
|T4N0 || 50% || 70% || T4N+ || N/A || N/A
|}
TME excision may result in significantly lower LR (<10%)
Prevention of local recurrence is a major goal of radiotherapy
==Prognostic factors==
'''''Adjuvant treatment:'''''
*Gunderson pooled analyses
**{{PMID|12243812}}, 2002 — "Impact of T and N substage on survival and disease relapse in adjuvant rectal cancer: a pooled analysis." Gunderson LL et al. Int J Radiat Oncol Biol Phys. 2002 Oct 1;54(2):386-96.
**{{PMID|15067027}}, 2004 — "Impact of T and N stage and treatment on survival and relapse in adjuvant rectal cancer: a pooled analysis." Gunderson LL et al. J Clin Oncol. 2004 May 15;22(10):1785-96.
**Data pooled from several trials. Found 3 risk groups: intermediate (T1-2/N1, T3/N0), moderately high (T1-2/N2, T3/N1, T4/N0), high (T3/N2, T4/N1, T4/N2). For int risk, results of surgery+CT similar to surgery+RT/CT.
==Patterns of failure==
*Memorial Hospital (NY), 1984 (1968–76) - {{PMID|6692324}} — "Patterns of pelvic recurrence following definitive resections of rectal cancer." Pilipshen SJ et al. Cancer. 1984 Mar 15;53(6):1354-62.
**412 pts s/p APR or LAR. Evaluated first site of recurrence.
**182 recurrences (44.2%), of which 105/182 were pelvic (57.6%), with 55/103(?) pelvic as the only recurrence or 50/79 with pelvic recurrence as the predominant component with extra-pelvic failure also present.
**Pelvic recurrence rate 29.7% for B2 (T4N0) and 22.1% for C1 (T1-2N1), higher still for C2(T3-4N1).
'''''Local failure after surgery:'''''
*{{PMID|6192900}} (1983, Rich T et al., Mass.General)
**8% Dukes' A, 31% Dukes' B, 50% Dukes' C. For stage II, 17% for microscopic extension beyond the wall (MAC-B2m) vs 54% invading other organs (MAC-B3). For Stage III, 36% if confined to wall or with microscopic extension (MAC-C1/C2m) vs 67% MAC-C3.
*{{PMID|6863077}}, 1983 (U.Florida) — "Patterns of recurrence in adenocarcinoma of the rectum and rectosigmoid treated with surgery alone: implications in treatment planning with adjuvant radiation therapy." Mendenhall WM et al. Int J Radiat Oncol Biol Phys. 1983 Jul;9(7):977-85.
==Treatment overview==
Guidelines:
*Pre-op T1-2N0: treat with primary surgery.
**If N+ or pT3 on pathology then adjuvant chemo-RT
*Pre-op T3 or N+: treat with pre-op chemo-RT followed by surgery, then adjuvant 5-FU/LV or FOLFOX
*Metastatic (resectable): chemo-RT or chemo alone, followed by resection of rectal tumor and mets
*Metastatic (unresectable): enroll on protocol
Historical Overview:
*Initially, rectal cancer was treated with surgery alone, but high cure rates were observed only in early (T1-T2N0) stages. Local recurrence rates in advanced T3-4N0 or N+ were on average 30%.
*Addition of post-op RT improved 5-year local recurrence by 35% (15% vs. 23%) in an 8 trial meta-analysis, but did not impact disease-free survival, distant mets, or overall survival
*In the post-op setting, combined RT with concurrent 5-FU improved local control, distant mets, and overall survival. Continuous infusion 5-FU is superior in overall survival over bolus 5-FU
*However, many patients who need radiation and chemotherapy cannot receive it postoperatively, therefore interest grew in preoperative chemoradiation therapy.
*There is no significant survival difference between preoperative and postoperative RT with chemotherapy. Sauer and the German Rectal Cancer Study Group demonstrated a greater chance of sparing the anal sphinter and fewer side effects with preoperative chemoradiation.
*Therefore, many centers consider preoperative chemoradiation the standard of care in the treatment of T3-4, N1-2, rectal cancer.
*The debate continues, however... to be continued
==Surgical principles==
*85-90% of patients with newly diagnosed rectal CA are technically resectable with:
**Transanal excision for select small T1 tumors (see below).
**APR (abdominoperineal resection)
**LAR (low anterior resection)
**TME (total mesorectal excision) reduces rate of positive radial margins
*In the West, extended lymph node dissection not necessary if clinically negative nodes. Should have at least 14 LN to be considered N0.
*In Japan, lateral lymph node dissection with pelvic autonomic nerve preservation (LLND + PANP) is becoming more popular. Complete PANP is defined as complete preservation of the superior hypogastric plexus, the hypogastric nerves, the sacral nerves, and the pelvic plexuses
Local recurrence rates:
*"Standard" surgery - >20% failure rate (average of randomized prospective trials with surgery only as control arm was 29%)
*Lower figures can be achieved with dedicated well-trained surgeons, and more extensive resection (which of course carries greater surgical mortality)
===Transanal Excision===
*Per NCCN v1.2010
**T1 only
**<30% circumference
**<3 cm size
**SM- (>3 mm)
**Mobile (nonfixed)
**Within 8 cm of anal verge
**No LVI+ or PNI+
**No Grade 3
*If found to have high risk features (e.g. T2, SM+, LVI+, Grade 3), need to do full transabdominal resection. If further high risk features (e.g. T3, N+) then adjuvant chemo-RT
*'''RTOG 89-02''' (1989–1992) {{PMID|10661337}} -- "Anal sphincter conservation for patients with adenocarcinoma of the distal rectum: long-term results of radiation therapy oncology group protocol 89-02." (Russell AH, Int J Radiat Oncol Biol Phys. 2000 Jan 15;46(2):313-22.)
**Phase II. 65 patients with distal rectal CA, felt to be unsuitable for sphincter-preservation with LAR and requiring APR, <=4 cm diameter, <=40% of rectal circumference, below peritoneal reflection. Local excision using trans-anal or trans-sacral approach, with anal sphincter conservation. Based on T-size, grade and SM, assigned to observation vs 5-FU with RT 50-56 Gy vs. 5-FU with RT 59.4-65 Gy. Median F/U 6.1 years
**Outcome: Local failure (after surgery + adapted chemo-RT) by T-stage: T1 0%, T2 20%, T3 23%. Loco-regional failure 12%. By T-stage: T1 4%, T2 16%, T3 23%. By circumference: <20% 6%, 20-40% 18%. Distant mets 12% (T1 4%, T2 12%, T3 31%). 5-year pelvic control 88%.
**Conclusion: Conservative sphincter-sparing therapy is feasible, but relatively high local failure rate for T2 and T3 lesions
*'''CALGB 8984''' (1990–1995) {{PMID|18536973}} -- "Local excision of distal rectal cancer: an update of cancer and leukemia group B 8984" (Greenberg JH, et al. Dis Colon Rectum. 2008 Aug;51(8):1185-91; discussion 1191–4. Epub 2008 Jun 7.)
**Phase II. 110 patients with rectal lesions < 10 cm from dentate line, < 4 cm diameter, < 40% rectal circumference, and negative margins were included (Note no EUS or MRI). 59 patients found with T1 lesions were treated with local excision alone. 51 Pts found with T2 lesions treated with local excision plus adjuvant radiation (54Gy) + 5-FU (500 mg/m2 intravenously Days 1–3, Days 29–31).
**Outcome: Ten year rates of OS 84% vs 66% (T1 vs T2). DFS 75% vs 64%. LR 8% vs 18%
**Conclusion: Conservative sphincter-sparing therapy is feasible for well selected T1 lesions, but T2 lesions have relatively high LR even with adjuvant ChemoXRT.
===TME===
*{{PMID|7551328}}, 1995 — "Total mesorectal excision in the operative treatment of carcinoma of the rectum." Enker WE et al. J Am Coll Surg. 1995 Oct;181(4):335-46.
**246 pts, T3N0 or T(any)N+ treated by TME. At 5 yrs, pelvic recurrence 4% for Dukes' B and 8% for Dukes' C. Risk factors for recurrence were N2 disease and perineural invasion. Adjuvant RT did not prevent LR.
*{{PMID|9711965}}, 1998 (1978–97) — "Rectal cancer: the Basingstoke experience of total mesorectal excision, 1978-1997." Heald RJ et al. Arch Surg. 1998 Aug;133(8):894-9.
**DFS 78% at 10 yrs.
===Laparoscopic===
*'''National Taiwan University''' (1997–1999) -- medial-to-lateral vs lateral-to-medial laparoscopic dissection
**Randomized. 67 patients, rectosigmoid cancer, single surgeon performing laparoscopic dissection. Arm 1) medial-to-lateral dissection vs Arm 2) lateral-to-medial dissection
**'''2003''' {{PMID|12616435}} -- "Comparison of medial-to-lateral versus traditional lateral-to-medial laparoscopic dissection sequences for resection of rectosigmoid cancers: randomized controlled clinical trial." (Liang JT, World J Surg. 2003 Feb;27(2):190-6.)
***Outcome: No difference in LN harvest, intraop complications, conversion rate, postop complications, or disability. Improved OR time, C-RP and ESR in medial group
***Conclusion: Medial-to-lateral dissection may be most appropriate for laparoscopic rectection of rectosigmoid cancers
==Intraoperative RT (IORT)==
*'''Kyorin University; 2008''' (2000–2007) {{PMID|18172677}} -- "Intraoperative radiotherapy for oncological and function-preserving surgery in patients with advanced lower rectal cancer." (Masaki T, Langenbecks Arch Surg. 2008 Jan 3 [Epub ahead of print])
**Randomized. 41 patients with advanced lower rectal CA. Arm 1) TME + bilateral lateral LND + limited PANP vs. Arm 2) TME + bilateral lateral LND + complete PANP + IORT to preserved pelvic nerve plexuses
**Outcome: No difference in LR, DFS, OS. Improved time with indwelling catheter and voiding function
**Conclusion: Complete pelvic autonomic nerve preservation with IORT may be useful
==Radiation technique==
'''''Radiation fields:'''''
<br>Generally 45 Gy to pelvis using 4-field box followed by boost of 5.4 - 9 Gy, to bring total dose to 50.4-54 Gy.
*AP/PA - ''Superior border'' at L5/S1 junction or mid-L5 body. ''Inferior border'' depends on surgical technique: After APR, include perineum with 1.5 cm margin. After LAR, place border 3–5 cm below anastomosis. For pre-op RT, 4 cm inferior to tumor extent or to anal verge. 2 cm lateral to bony pelvis.
*Laterals - ''Posterior border'' 1.5–2 cm behind anterior edge of sacrum (or 1 cm behind sacrum if T4 tumor). ''Anterior border'' should cover internal iliac LNs (generally placed 2–3 cm anterior to sacrum promontory, includes 2/3 of femoral heads). At least 3 cm margin on tumor.
'''''CTV delineation'''''
*'''Leuven; 2006''' {{PMID|16750329}} -- "Definition and delineation of the clinical target volume for rectal cancer." (Roels S, Int J Radiat Oncol Biol Phys. 2006 Jul 15;65(4):1129-42. Epub 2006 Jun 5.)
**Guidelines for CTV delineation for pelvic subsites and LN groups at risk
'''''Elective para-aortic irradiation'''''
*'''EORTC''' 1983-1992 {{PMID|11578723}} -- "Postoperative pelvic radiotherapy with or without elective irradiation of para-aortic nodes and liver in rectal cancer patients. A controlled clinical trial of the EORTC Radiotherapy Group." (Bosset JF, Radiother Oncol. 2001 Oct;61(1):7-13.)
**Randomized. 484 patients with Gunderson-Sosin (modified Aster-Coller) stages B2-B3, C1-C3, age <70. Treated with 1) pelvic RT 50/25 (Lim-RT) vs 2) extended RT to pelvic RT (50/25) plus para-aortic LNs and liver to 25 Gy in 19 fractions (Ext-RT)
**10-year intrapelvic failure: ~30% in both. 10-year DFS: 31% in both. 10-year OS: 40% vs. 37% (NS)
**Conclusion: Low dose RT to para-aortic nodes and liver doesn't help
==Radiotherapy and inflammatory bowel disease==
*'''Mt. Sinai''', 1999 (1960–94) - {{PMID|10386640}} — "Rectal cancer and inflammatory bowel disease: natural history and implications for radiation therapy." Green S et al. Int J Radiat Oncol Biol Phys. 1999 Jul 1;44(4):835-40.
**Retrospective. 47 pts with IBD (35 with ulcerative colitis and 12 with Crohn's) and rectal cancer. Most were treated with RT in an adjuvant fashion.
**Grade 3 or higher acute complications in 20%. 13% developed small bowel obstruction.
**Conclusion: Treatment results are comparable to those with pts treated with non-IBD rectal cancer.
==Non-surgical treatment==
'''Primary radiotherapy or chemoradiotherapy for medically inoperable pts or pts who refuse surgery'''
*'''Australia''', 2007 (1998–2005)- {{PMID|17896138}} — "Long-Term Outcomes of Patients with Localized Rectal Cancer Treated with Chemoradiation or Radiotherapy Alone Because of Medical Inoperability or Patient Refusal." Lim L et al. Dis Colon Rectum. 2007 Sep 26 [Epub ahead of print]
**48 pts (50% medically inoperable, 50% refused surgery). ChemoRT in 36 pts, RT alone in 12.
**Median f/u 49 mo. 18 pts w/ disease progression. 16 pts dead with disease, 9 dead from other causes.
**Chemo/RT or RT results in good PFS and OS times in pts who do not undergo surgery. Many pts, however, progress.
*'''Princess Margaret''', 1995 (1978–87) - {{PMID|7836077}} -- "Adenocarcinoma of the rectum treated by radical external radiation therapy." (Brierley JD, Int J Radiat Oncol Biol Phys. 1995 Jan 15;31(2):255-9.)
**229 pts, medically unfit or refused surgery. Various RT regimens; most commonly 52 Gy in 20 fx. No chemo-RT.
**Pt population: Tumor was mobile: 97, partially fixed: 37, fixed: 77, unknown: 18.
**Mean f/u 5.8 yrs. 5 yr OS 27% (OS for pts with mobile tumors: 48%, partially fixed: 27%, fixed: 4%). cCR in 50% / 30% / 9% (mobile / p.fixed / fixed). Time to cCR 3–6 months (from start of RT). Local failure: 69% / 87% / 97%. 50 pts had salvage surgery.
**Conclusion: RT can cure some pts with mobile or partially fixed tumors, although local failure is common
'''Non-surgical treatment strategy in operable patients'''
*'''Netherlands''', 2011 - [http://jco.ascopubs.org/content/early/2011/11/03/JCO.2011.37.7176 Abstract] -- "Wait-and-See Policy for Clinical Complete Responders After Chemoradiation for Rectal Cancer" (Maas M, J Clin Oncol Published online before print November 7, 2011.)
**Pts with a clinical CR after neoadjuvant chemo-RT were selected for close observation rather than surgery. Compared this patients with a cohort of pts with a pCR after chemo-RT.
**21 pts had cCR after chemo-RT (11% of pts). Mean f/u 25 months. 20 of 21 pts alive without disease; 1 pt had LR, with surgical salvage.
**Conclusion: a wait-and-see policy for patients achieving a CR is feasible, and early results suggest the outcome is favorable
*'''Brazil (São Paulo)''', 2004 (1991–2002) - {{PMID|15383798}} -- "Operative versus nonoperative treatment for stage 0 distal rectal cancer following chemoradiation therapy: long-term results." (Habr-Gama A, Ann Surg. 2004 Oct;240(4):711-7)
**265 pts with resectable distal rectal ca (within 7 cm of the anal verge) received 50.4 Gy + 5-FU/LV. Those with clinical complete response at 8 weeks (with negative biopsy) were not immediately operated on but had intensive follow-up; while those with incomplete response had surgery. Compared the patients with complete clinical response (non-operative treatment) vs those with initial incomplete response who had complete pathologic response at the time of surgery. Neither group received adjuvant chemotherapy. Preop staging: T3-T4 in 80-95%, N+ in 22-27%.
**Patients must have had a sustained complete response for 12 months to be considered "stage 0" and in the observation group.
**71 pts had cCR (26.8%) and formed the Observation group, whereas 194 made up the incomplete responders. 22 pts (8.3%) of the incomplete responders had pCR at the time of surgery and made up the Resection group.
**For all 93 pts (35%) with "stage 0" (OB group + R group), 10-yr OS and DFS 97% and 84%; no significant difference between groups; local recurrence in 2 pts
**Conclusion: "Stage 0" rectal cancer (pCR or cCR after chemo-RT) is associated with excellent long-term results irrespective of treatment strategy.
==Squamous cell carcinoma==
*'''MSKCC; 2007''' (1983–2005) {{PMID|17661147}} -- "Squamous-cell carcinoma of the rectum: a rare but curable tumor." (Nahas CS, Dis Colon Rectum. 2007 Sep;50(9):1393-400.)
**12 pts. Treated with chemotherapy only (n=1), chemo/RT (n=2), induction chemo then chemo/RT and surgery (n=2), chemo/RT then surgery (n=5), surgery then chemo/RT (n=2). (Surgery in 9 of 12). RT 50.4 Gy.
**Of those treated with upfront chemo and/or RT (n=10): 2 had CR with chemo/RT and did not receive surgery; 7 partial responders went on to have surgery and 6 of 7 had pCR.
**All pts alive and NED at median f/u 2.6 yr.
**Conclusion: "Our data suggest that most patients treated with upfront chemoradiation therapy followed by surgery did well. Sphincter-preserving surgery is usually feasible. Clinical judgment of tumor response after chemoradiation is not completely reliable. Immunohistochemistry suggests a common cellular origin for rectal squamous-cell carcinoma and rectal adenocarcinoma, which is different from anal squamous-cell carcinoma."
==Follow-up exams==
Per NCCN guidelines, physical exam every 3 months for 2 years then every 6m for 5 yrs total; CEA every 3 months (same as physical exam) if T2 or greater; CT scan if at high risk for recurrence (perineural invasion, lymphovascular invasion, poorly differentiated); colonoscopy in 1 year, then repeat at least every 2–3 years.
==Other Resources==
*[https://astro.webex.com/ec0606l/eventcenter/recording/recordAction.do?theAction=poprecord&AT=pb&renewticket=0&isurlact=true&recordID=17600002&apiname=lsr.php&rKey=9b804b62b2903414&format=short&needFilter=false&&SP=EC&rID=17600002&siteurl=astro&actappname=ec0606l&actname=%2Feventcenter%2Fframe%2Fg.do&rnd=7730042249&entappname=url0108l&entactname=%2FnbrRecordingURL.do ASTRO/ARRO Journal Club Webinar 2011 - "The Changing Management of Rectal Cancer" with Christopher Willett, MD]
er9va4he9rel463p34zr83ji230vpbq
Radiation Oncology/Rectum/RT Salvage
0
93614
4675999
2257251
2026-10-14T09:58:31Z
Jcb
90773
4675999
wikitext
text/x-wiki
{{Radiation Oncology:TOC}}
'''Reviews:'''
*1998: {{PMID|9457833}} - "In search of a dose-response relationship with radiotherapy in the management of recurrent rectal carcinoma in the pelvis: a systematic review." Wong R et al. Int J Radiat Oncol Biol Phys. 1998 Jan 15;40(2):437-46.
**Optimal dose fractionation remains undefined.
==Recurrence (no prior RT)==
*'''Peter MacCallum, 1997''' (1981-90) {{PMID|9276368}} -- "Radiotherapy treatment for isolated loco-regional recurrence of rectosigmoid cancer following definitive surgery: Peter MacCallum Cancer Institute experience, 1981-1990." (Guiney MJ,Int J Radiat Oncol Biol Phys. 1997 Jul 15;38(5):1019-25.)
**Retrospective, 135 pts. Pts without prior RT treated to 1) 50-60 Gy / 2 Gy fractions ("radical" group), 2) 45 Gy / 3 Gy fractions w/ 1 week break ("high-dose palliative"), or 3) <45 Gy ("low-dose palliative").
**Symptom relief rate of 85%, 81%, and 56%. Median survival 17.9, 14.8, and 9 months.
**Conclusion: Similar response rate for 50-60 Gy radical group and 45 Gy hypofractionated group.
==Reirradiation==
*'''MDACC, 2010''' (2001-2005) {{PMID|19695792}} -- "Hyperfractionated accelerated radiotherapy for rectal cancer in patients with prior pelvic irradiation." (Das P, Int J Radiat Oncol Biol Phys. 2010 May 1;77(1):60-5.)
**50 pts. Treated 150 cGy BID to 39 Gy (if interval >= 1 yr since prior RT; n=47) or 30 Gy (if <1 yr; n=3). 96% received concurrent chemo. 36% underwent surgical resection following RT.
**3-yr freedom from local progression 33% (47% for pts having surgery vs 21% for those without). 3-yr OS 39% (66%-surgery;27%-without).
**Toxicity: 3-yr rate of gr3-4 late toxicity 35%.
**Conclusion: hyperfractionated accelerated reirradiation was well tolerated with low rates of acute toxicity and moderate rates of late toxicity.
*'''Italy (STORM)''' (1997-2001) -- Phase II
**59 pts. Multicenter study (STORM = Study Group for Therapies of Rectal Malignancies). RT to GTV + 4 cm radial margin to 30 Gy (1.2 Gy BID) plus boost (2 cm margin) to 10.8 Gy (1.2 BID), total dose 40.8 Gy in 34 fx. Concomitant 5-FU (225 mg/m2/d). Surgery performed 6-8 wks after chemo/RT. Adjuvant chemo with raltitrexed (antimetabolite) given after surgery.
**'''2006''' {{PMID|16414206}} -- "Preoperative hyperfractionated chemoradiation for locally recurrent rectal cancer in patients previously irradiated to the pelvis: A multicentric phase II study." (Valentini V, Int J Radiat Oncol Biol Phys. 2006 Mar 15;64(4):1129-39.)
***Median 27 months interval between prior RT and re-RT. 86% completed treated without interruption. Overall response rate to chemo/RT 44.1%. 66% of pts completed surgery; R0 resection in 35%, R0-R1 in 35%. 5 pts (8.5%) had pCR. Sphincter-sparing operation in 7 of 24 (29%) with R0-R1 resection. 15 pts had macroscopic residual (R2 resection). Pain relief in 20/24 pt (83%). Despite 87% of pts having tumor in contact with the pelvic sidewall, 35% achieved R0 resections.
***Tox: No gr4-5 acute tox. Late toxicity was infrequent. 6/39 (15%) operated pts had post-op complications.
***Median f/u 36 mo. 5-yr LC 38%, DMFS 42%, DFS 29%. In R0 pts: 69%, 69%, 50%. MS 42 mo. 5-yr OS 39% (65% in R0-R1 pts, 22% in pts treated w/o surgery or with R2 resection). 3-yr LC 17% in pts without R0 resection
***Conclusion: hyperfractionated chemoradiation was associated with a low rate of acute toxicity and acceptable late complication rate.
*'''University of Kentucky, 2002''' (1987-2000) -
**'''2002''' (1987-2000) {{PMID|12209702}} -- "Long-term results of reirradiation for patients with recurrent rectal carcinoma." Mohiuddin M et al. Cancer. 2002 Sep 1;95(5):1144-50.
***103 pts who developed locoregional recurrence after surgery with pre-op or post-op RT. Previously treated to median dose of 50.4 Gy. Time to recurrence 2 to 86 months (Median: 19m). Reirradiation with concurrent 5-FU continuous infusion. Treated with opposed laterals or posterior field and 2 laterals. Treated presacral area and GTV (with 2-4 cm margin) to either 30 Gy (1.2 Gy BID) or 30.6 Gy (1.8 Gy QD) followed by a boost of 6-20 Gy to GTV (2 cm margin). Median reirradiation dose 34.8 Gy.
***41 pts were surgically explored after treatment, and 34 underwent resection (6 pts with sphincter sparing). Median f/u 24 months. 5-yr OS 19%. Higher survival for those undergoing resection. Acute and late toxicity was tolerable. Bleeding palliated in 100% of pts.
**'''1997''' (1987-1992) {{PMID|9336144}} -- "Curative surgical resection following reirradiation for recurrent rectal cancer." (Mohiuddin M, Int J Radiat Oncol Biol Phys. 1997 Oct 1;39(3):643-9.)
***39 pts.
*'''Thomas Jefferson University''' (1987-93) - Phase I/II
**'''1993''' (1987-91) {{PMID|8262842}} -- "Reirradiation for rectal cancer and surgical resection after ultra high doses." (Mohiuddin M, Int J Radiat Oncol Biol Phys. 1993 Dec 1;27(5):1159-63.)
***32 pts, treated with curative intent after surgical resection.
**'''1997''' (1987-93) {{PMID|9240647}} -- "Palliative reirradiation for recurrent rectal cancer." (Lingareddy V, Int J Radiat Oncol Biol Phys. 1997 Jul 1;38(4):785-90.)
***52 pts, palliative reirradiation without surgery.
r67yogwr0j6jofl5rfatlf4xmwlsr1c
Radiation Oncology/Rectum/Adjuvant RT
0
93615
4675987
4091326
2026-10-14T06:08:54Z
Jcb
90773
4675987
wikitext
text/x-wiki
{{Radiation Oncology:TOC}}
<big>'''Adjuvant Therapy for Rectal Cancer'''</big>
==Adjuvant RT Overview==
*Local recurrence after surgery alone for Dukes T3-T4 or N+ is >50%, and can be symptomatically devastating
*Most adjuvant trials were done in patients with Dukes B and C (T3-4N0 or N+)
*Outcomes with adjuvant chemotherapy alone have been disappointing
*8 prospective randomized trials evaluated surgery alone vs. post-op RT. RT alone improves local control, but not survival
*Combined RT + 5-FU improved local control, distant control, as well as survival in two randomized trials
*RT plus continued infusion of 5-FU improves survival over bolus 5-FU. Other concurrent drugs have so far not shown additional benefit over C.I. 5-FU
*For postop T3-4 or N+: Adjuvant chemotherapy (5-FU/LV), followed by continuous infusion 5-FU + RT, then additional 5-FU/LV
==Surgery +/- Adjuvant RT==
*Post-op RT alone improves local control, and in one trial increases time-to-local failure
*There is no impact on distant mets, disease-free survival, or overall survival
*At this time, RT alone is considered inadequate. It should be given concurrently with chemotherapy
*'''Meta-analysis, 2001''' {{PMID|11684209}} -- "Adjuvant radiotherapy for rectal cancer: a systematic overview of 8,507 patients from 22 randomised trials." (Colorectal Cancer Collaborative Group, Lancet. 2001 Oct 20;358(9290):1291-304.). Note: following data abstracted for post-op RT only (8 trials):
**5-year OS: observation 58.6% vs. RT 57.5% (NS). Annual death rate 4.6% lower with RT
**5-year risk of any recurrence: observation 54% vs. RT 50% (NS)
**5-year risk of isolated local recurrence: observation 23% vs. RT 15% (SS). This was driven by 2 trials (UK MRC 3 and NSABP R-01)
**Few recurrences >5 years out.
**No subgroup benefit
*'''MRC 3''' (1984-1989) {{PMID|8961990}} -- "Randomised trial of surgery alone versus surgery followed by radiotherapy for mobile cancer of the rectum. Medical Research Council Rectal Cancer Working Party." (No Authors Listed, Lancet. 1996 Dec 14;348(9042):1610-4.)
**Randomized. 469 patients with Dukes B and C (T3-4N0, N+) treated with 1) surgery alone vs. 2) surgery followed 4-6 weeks later by RT 40/20. Minimum F/U 5 years
**5-year OS: 46% vs. 52% (NS), trend toward RT arm (HR 0.84)
**Local recurrence: 34% surgery alone vs. 21% RT (SS). No difference in distant mets.
**Side effects: well tolerated, late events rare
*'''ANZ 8202''' (1982-1985) {{PMID|1907128}} -- "Adjuvant post-operative radiotherapy in rectal cancer: results from the ANZ Bowel Cancer Trial (Protocol 8202)." (Mameghan H, Australas Radiol. 1991 Feb;35(1):61-5.)
**Randomized. 70 patients randomized; trial terminated early due to slow accrual. 33 patients. Resection +/- RT 45 Gy. In RT group 13/36 patients did not receive RT. Average F/U 4.3 years
**OS: 33% observation vs. 18% RT (NS). No difference in time-to-recurrence
**Side effects: complications comparable. Grade 3-4 diarrhea: 1/21 RT patients
**Critique: early termination, very small numbers, high noncompliance
*'''Rotterdam B''' {{PMID|2004322}} -- "Postoperative radiation therapy for rectal cancer. An interim analysis of a prospective, randomized multicenter trial in The Netherlands." (Treurniet-Donker AD, Cancer. 1991 Apr 15;67(8):2042-8.)
**Randomized. 172 patients. Resection +/- RT 50 Gy
**LR lower but NS. No impact on disease-free or OS
*'''EORTC 40811''' (1981-?) - Information from {{PMID|11684209}}
**Randomized. 172 patients. Surgery +/- RT 46/23
**OS: 40% vs. 37% (NS)
*'''Denmark''' (1979-?)
**Randomized. 494/861 patients with Dukes B and C. Surgery with observation vs. post-op RT 50 Gy
**'''1992''' {{PMID|1733432}} -- "Time to loco-regional recurrence after resection of Dukes' B and C colorectal cancer with or without adjuvant postoperative radiotherapy. A multivariate regression analysis." (Bentzen SM, Br J Cancer. 1992 Jan;65(1):102-7.)
***No OS benefit, no improvement in 5-year LR rate with RT
***In high-risk patients, RT benefit in LR, but not OS
***High risk: PNI, LVI, tumor <10cm from anal verge, large tumor size, necessity to resect neighbour organs
**'''1988''' {{PMID|3166910}} -- "A regression analysis of prognostic factors after resection of Dukes' B and C carcinoma of the rectum and rectosigmoid. Does post-operative radiotherapy change the prognosis?" (Bentzen SM, Br J Cancer. 1988 Aug;58(2):195-201.)
***Dukes B: poor prognosis with age >60, PNI, LVI, tumor <10cm from anal verge, CEA >3.2 ng/ml
***Dukes C: poor prognosis with male gender, PNI, LVI, tumor <10cm from anal verge, CEA >3.2 ng/ml
***No survival benefit of RT
**'''1986''' {{PMID|3518912}} -- "Postoperative radiotherapy in Dukes' B and C carcinoma of the rectum and rectosigmoid. A randomized multicenter study." (Balslev I, Cancer. 1986 Jul 1;58(1):22-8.)
***Dukes B: no benefit from RT
***Dukes C: improved local control at 2 years; time to LR delayed by 1 year
***Plasma CEA levels influenced by RT
*'''NSABP R-01''' (1977-86) - {{PMID|3276900}} — "Postoperative adjuvant chemotherapy or radiation therapy for rectal cancer: results from NSABP protocol R-01." Fisher B et al. J Natl Cancer Inst. 1988 Mar 2;80(1):21-9.
**Randomized 3 arms. 555 pts. Dukes' B and C after curative resection. Treated with 1) observation, 2) MOF (5-FU, semustine, vincristine) only, or 3) RT 46-47 Gy
**Improvement in OS and DFS for chemotherapy only group, but benefit restricted to males.
**RT resulted in decreased LR from 25% to 16% (p=0.06), but no change in DFS or OS.
**Surg vs surg + chemo showed no difference in LRR
**Conclusion: No role for post-op RT; chemo benefit for males.
**Critique: large non-compliance in RT arm
==Adjuvant Chemo +/- RT
___________________________________________
*'''NSABP R-02''' (1987-92) - {{PMID|10699069}} [http://jncicancerspectrum.oxfordjournals.org/cgi/content/full/jnci;92/5/388 Full text] — "Randomized trial of postoperative adjuvant chemotherapy with or without radiotherapy for carcinoma of the rectum: National Surgical Adjuvant Breast and Bowel Project Protocol R-02." Wolmark N et al. J Natl Cancer Inst. 2000 Mar 1;92(5):388-96.
**694 pts. Dukes' B and C after curative resection. Randomized to adjuvant chemotherapy alone or chemotherapy plus RT. All females received 5-FU/LV, whereas males were randomized to MOF vs 5-FU/LV. Median f/u 93 months.
**Post-op RT resulted in lower LR (13% vs 8%) but did not improve DFS or OS. For male pts, 5-FU/LV resulted in better DFS than MOF but not better OS.
**Conclusion: No role for post-op RT, although benefit with local control.
*'''GITSG GI-7175''' (1975-80)
**''See [[#Adjuvant RT +/- Chemo|below]] for details''
**Randomized 4 arms. 227 patients. Dukes B and C. (T3-4N0 or N+). Treated with 1) Surgery alone, 2) post-op Chemo (5-FU/MCCNU), 3) post-op RT 40-48 Gy, 4) post-op Chemo-RT 40-44 Gy + 5-FU
**Significant benefit between chemo-RT arm and observation; please see details below
==Adjuvant RT +/- Chemo==
*GITSG GI-7175 demonstrated the superiority of post-op chemo-RT over chemo alone, RT alone, or observation.
*NCCTG 79-47-51 demonstrated superiority of post-op Chemo-RT over RT alone.
*ECOG 4276 (negative trial) was only published as abstract.
*Some form of adjuvant chemo-RT is considered standard of care (in patients who already underwent surgical resection, and were found T3-4 or N+ on pathology)
*'''ECOG EST 4276''' (1986-?) - <u>Abstract Only</u> -- "A comparison of post-operative chemotherapy, radiotherapy or combination therapy in potentially curable rectal carcinoma: an ECOG study EST 4276." (Mansour E, Proc ASCO 1991; 10: 154 (A484).)
**Randomized 3 arms. 237/248 patients. Treated post-op with RT 45/25 vs. 2) chemo (MF) vs. 3) RT + sequential chemo
**No difference in either local control or OS
*'''NCCTG 79-47-51''' (1980-1986) -- postop RT vs postop chemo-RT
**Randomized. 204 patients, rectal CA T3-4 or N+, within 12 cm of anal verge. Arm 1) post-op RT vs. Arm 2) post-op chemo-RT. RT given 45/25 + 5.4/3 Gy boost to tumor bed and adjacent LN. Chemo bolus 5-FU bolus + semustine x1 month, then bolus 5-FU 500 mg/m2 concurrent with RT, then 2 months consolidative 5-FU/semustine. Major deviations 9%
**'''7-years; 1991''' {{PMID|1997835}} — "Effective surgical adjuvant therapy for high-risk rectal carcinoma." (Krook JE et al. N Engl J Med. 1991 Mar 14;324(11):709-15.). Median F/U 7 years
***Outcome: 5-year recurrence RT 63% vs. chemo-RT 41% (decreased by 34%, SS). LR 25% vs. 13% (decreased by 47%, SS), DM 46% vs. 29% (SS). 5-year OS ~40% vs. ~55% (decreased by 29%, SS). Reduction in death rate highly significant for LAR (52%), not significant for APR (10%)
***Toxicity: SBO 5%, median time-to-complication 10 months; overall severe late toxicity 7% (comparable between 45 and 50.4 Gy)
***Conclusion: Adjuvant chemo-RT superior to RT alone; confirms prior GITSG 7175 results
**Comment: CRT generally well tolerated, unlike GITSG GI-7175. Adjuvant chemo 1 month first, consolidation 2 months vs 1.5 years in GITSG. On the basis of this study and GITSG 7175, NIH consensus conference [http://www.nlm.nih.gov/databases/alerts/rectal_cancer.html recommended] chemo-RT as standard of care for T3-T4 or N+ patients
*'''GITSG GI-7175''' (1975-1980) -- surgery alone vs postop chemo vs postop RT vs postop chemo-RT
**Randomized, 4 arms. ''Terminated early due to significant benefit of chemo-RT arm''. 227/520 patients. Dukes B and C (T3-4 or N+), distal edge within 12 cm from anal verge. Only R0 resection allowed. Treated with 1) Surgery alone, 2) post-op Chemo (bolus IV 5-FU/M-CCNU), 3) post-op RT 40 or 48 Gy standard fraction, 4) post-op Chemo-RT 40 or 44 Gy standard fraction + 5-FU 500 mg/m2 followed by adjuvant 5-FU/M-CCNU as in chemo alone arm. RT given AP/PA, superior border L4/L5, inferior border included perineum; major deviations in 39%. Consolidative chemo given x1.5 years or until disease progression
**'''7-years, 1985''' {{PMID|2859523}}, 1985 — "Prolongation of the disease-free interval in surgically treated rectal carcinoma. Gastrointestinal Tumor Study Group." [No authors]. N Engl J Med. 1985 Jun 6;312(23):1465-72. Median F/U 6.7 years.
***Outcome: Recurrence surgery 55% vs. chemo 46% vs. RT 48% vs. chemo-RT 33% (SS). Benefit of chemo-RT (p=0.009) due to both RT (, better LRC p=0.06) and chemo (better DM p=0.06) components. Initial LRR overall 21%; by arm 24% vs. 27% vs. 20% vs. 11%; initial DM overall 25%. LR in perineum 21%, vagina/uterus 17%, anastomosis 12%, sacrum/coccyx 12%, bladder/prostate 12%. Actuarial OS 36% vs. 46% vs. 46% vs. 56% (p=0.07)
***Toxicity: Severe nonhematological chemo 15% vs. RT 16% vs. chemo-RT 35%
***Conclusion: Postoperative chemo-RT significantly better for disease-free survival, with trend to overall survival benefit
**'''8-years, 1986''' {{PMID|3773947}}, 1986 (No abstract) — "Survival after postoperative combination treatment of rectal cancer." Douglass HO et al. N Engl J Med. 1986 Nov 13;315(20):1294-5. Median F/U 7.8 years
***Outcome: No new recurrences. Now overall survival benefit for chemo-RT over surgery alone (SS)
***Conclusion: Postoperative chemo-RT improves overall survival over surgery alone in T3-4 or N+ patients
**'''GITSG overview, 1988''' {{PMID|3064191}}, 1988 — "Adjuvant postoperative radiotherapy and chemotherapy in rectal carcinoma: a review of the Gastrointestinal Tumor Study Group experience." Thomas PR et al. Radiother Oncol. 1988 Dec;13(4):245-52.
***Severe acute toxic side-effects, but late effects rare in arm 4. Three late deaths (2 enteritis in chemo-RT group, one acute leukemia in chemo group).
***Conclusions: Compared to surgery alone, postop Chemo-RT improved OS (45% v 27% @ 10yrs), prolonged Time-To-Recurrence, decreased Recurrence Rate (33% v 55%), and decreased LF Rate (10% v 25%).
**Critique: severely underpowered to show benefit, unequal randomization and not analyzed by intent to treat, semustine x1.5 years increases risk for leukemia
==Adjuvant chemo-RT schedules==
*Semustine (Methyl-CCNU) was a component of both trials demonstrating benefit, but is known to increase risk of leukemia (4% cummulative risk at 6 years). GITSG 7180 and NCCTG 86-47-51 demonstrated that semustine is not a necessary component of chemo-RT
*In the setting of metastatic CRC, continuous infusion 5-FU is superior to bolus 5-FU (7 PIII trials). Synergistic effects of 5-FU and RT are greatest when there is a continuous exposure to 5-FU for 24-48 hours after RT ({{PMID|6818194}}). INT 864751 demonstrated improved OS with infusional 5-FU (70% vs. 60% at 4 years). The improvement was due to increased control of distant mets, with no impact on local control.
*INT 0144 trial evaluated infusion 5-FU vs. bolus 5-FU sandwich around infusion 5-FU/RT. Results at 5 years suggest comparable outcomes
*'''Intergroup INT-0144''' (1994-2000) - bolus vs modulated bolus vs CI 5-FU
**Randomized. 1917 pts. T3-4 or N+. Follow-on to INT 864751. Randomized to: 1) bolus 5-FU then CI 5-FU/RT then bolus 5-FU vs. 2) CI 5-FU then CI 5-FU/RT then CI 5-FU, vs. 3) bolus 5-FU + LV + levimasole then CI 5-FU/RT then bolus 5-FU + LV + levimasole. RT given 45 Gy to field including presacral and internal illiac LN + 5.4 Gy boost with 2cm margin + optional 3.6 Gy boost to tumor bed if no small bowel in-field
**'''2006''' {{PMID|16877719}} -- "Phase III trial of fluorouracil-based chemotherapy regimens plus radiotherapy in postoperative adjuvant rectal cancer: GI INT 0144." (Smalley SR, J Clin Oncol. 2006 Aug 1;24(22):3542-7.). Median F/U 5.7 years
***5-year survival: no DFS difference (57-62%), no OS difference (68-71%).
***LR failure (tumor bed, anastomosis, regional LNs) at first relapse 8% vs. 5% vs. 7%. LR failure in non-T4 patients 5% vs. 3% vs. 5%, and primary surgical treatment without neoadjuvant can be appropriate
***Toxicity: GI Grade 3/4 41-44%; hematologic Grade 3/4 bolus arm 49-55% vs. CI arm 4%
***Conclusion: similar survival in all arms, different toxicity profiles and central catheter requirements. LAR reasonable initial resection, since local failure rates only 5% at first failure
**'''2002''' [http://www.asco.org/ac/1,1003,_12-002636-00_18-0023-00_19-00101048,00.asp ASCO Abstract] — "Intergroup 0144 - phase III trial of 5-FU based chemotherapy regimens plus radiotherapy (XRT) in postoperative adjuvant rectal cancer. Bolus 5-FU vs prolonged venous infusion (PVI) before and after XRT + PVI vs bolus 5-FU + leucovorin (LV) + levamisole (LEV) before and after XRT + bolus 5-FU + LV." Smalley SR et al. Proc Am Soc Clin Oncol 22:251, 2003 (abstr 1006)
***Median f/u 4.6 yrs. No difference in RFS or OS. 5-year estimated OS 72% CI vs. 67% bolus
***Similar toxicity profiles; less GI toxicity in bolus group, less hematologic toxicity in CI group
*'''Intergroup INT-0114''', 1997 (1990-92) - different modulations of 5-FU
**1695 pts. T3-T4 or N+. 2 cycles of infusional 5-FU -> RT + chemo -> 2 cycles of chemo. Randomized to: 1) 5-FU alone, 2) 5-FU + LV, 3) 5-FU + levamisole (levamisole not given during RT), 4) 5-FU + LV + levamisole (levamisole not given during RT). RT dose was 45 Gy + 5.4-9 Gy boost, total 50.4 - 54 Gy.
**'''1997''' {{PMID|9164215}} — "Adjuvant postoperative fluorouracil-modulated chemotherapy combined with pelvic radiation therapy for rectal cancer: initial results of intergroup 0114." Tepper JE et al. J Clin Oncol. 1997 May;15(5):2030-9.
**'''2002''' {{PMID|11919230}} — "Adjuvant therapy in rectal cancer: analysis of stage, sex, and local control--final report of intergroup 0114." Tepper JE et al. J Clin Oncol. 2002 Apr 1;20(7):1744-50. Median f/u 7.4 yrs.
***No difference in OS or DFS between groups. 5-yr OS 76% for low risk (T1-2N+ or T3N0), 55% for high risk (T3N+ or Any T4).
**''Other publications:'' {{PMID|14701779}}, 2004 (Impact of hospital procedure volume); {{PMID|14966087}}, 2004 (Impact of body mass index); {{PMID|14512393}}, 2003 (Analysis of surgical salvage)
*'''INT/NCCTG 86-47-51''', 1994 (1986-90) - {{PMID|8041415}} [http://content.nejm.org/cgi/content/full/331/8/502 Full text] — "Improving adjuvant therapy for rectal cancer by combining protracted-infusion fluorouracil with radiation therapy after curative surgery." O'Connell MJ et al. N Engl J Med. 1994 Aug 25;331(8):502-7.
**660 pts. Stage II-III. 2x2 randomization: type of systemic chemotherapy (5-FU + Semustine or 5-FU) and type of 5-FU infusion with RT (bolus or continuous infusion). Treated with 9 weeks of systemic chemotherapy -> RT with 5-FU -> 2nd cycle of chemotherapy. Higher dose of 5-FU used when given alone than with semustine. RT dose 45 Gy to the pelvis + boost 5.4 - 9 Gy, total 50.4 - 54 Gy. Bolus 5-FU was 500 mg/m2 days 1-3, weeks 1+5 of RT. C.I. 5-FU was 225 mg/m2 daily during RT.
**Median f/u 46 mo. For C.I., less tumor relapse (37% vs 47%), distant mets (31% vs 40%), time to relapse, and overall survival compared to bolus 5-FU. Decreased tumor relapse by 27%, death by 31%. 4-yr relapse-free survival 63% vs 53%, OS 70% vs 60%. No difference in LR. Increased rate of severe diarrhea for C.I.; higher rate of leukopenia for bolus. No benefit seen for semustine.
**Conclusion: C.I. 5-FU is superior to bolus 5-FU. Improves DM (extra-pelvic disease) but not LC. Much higher doses of 5-FU were given by continuous infusion than by bolus. No benefit to semustine in addition to 5-FU.
===Semustine (M-CCNU)===
*'''NCCTG 86-47-51''', 1994 (1986-90) - {{PMID|8041415}}
**Please see above in continuous infusion section.
**No benefit to semustine in addition to 5-FU.
*'''GITSG 7180''', 1992 (1981-85) - {{PMID|1548520}} — "Radiation therapy and fluorouracil with or without semustine for the treatment of patients with surgical adjuvant adenocarcinoma of the rectum. Gastrointestinal Tumor Study Group." [No authors]. J Clin Oncol. 1992 Apr;10(4):549-57.
**210 pts. Pts treated with adjuvant RT/5-FU followed by 12 months of 5-FU +/- Methyl-CCNU (Semustine).
**Conclusion: Semustine is not an essential component of combined modality therapy.
hiuiaphp5t93r36ebko6c4mv5mt3edh
Radiation Oncology/Rectum/Neoadjuvant RT
0
93616
4675994
4366957
2026-10-14T09:23:28Z
Jcb
90773
4675994
wikitext
text/x-wiki
{{Radiation Oncology:TOC}}
<big>'''Neoadjuvant Therapy for Rectal Cancer'''</big>
==Preop vs Postop RT==
Recommend T3-T4 or N+ pts receive pre-op chemo/RT
*RTOG 94-01 /INT 0147 - concurrent 5-FU (closed due to poor accrual)
*NSABP R-03 - concurrent 5-FU (closed due to poor accrual, see summary below)
===Chemo-RT===
Chemoradiotherapy Regimens in Rectal Cancer
*'''Polish II''' (2008-2014) -- cT3 or cT4 rectal cancer, neoadjuvant short-course sequential chemoradiation vs. long-course concurrent chemoRT
**Randomized 541 patients to short course radiation (5 Gy x 5 fractions) followed by 3 cycles FOLFOX or long-course concurrent ChRT (50.4 Gy with bolus 5FU and leucovorin)
**'''2016''' {{PMID|26884592}} -- "Long-course oxaliplatin-based preoperative chemoradiation versus 5 x 5 Gy and consolidation chemotherapy for cT4 or fixed cT3 rectal cancer." (Bujko K, Annals of Oncology, May;27(5):834-842).
***Outcome: Local failure: short-course 22%, long-course 21% (NS); any-grade toxicity short-course 75% long-course 83% (SS) but difference mostly in grade 1-2 toxicity.
****3-yr OS short-course 73%, long-course 65% (SS)
***Author's conclusions: differences in local efficacy, but differences in 3-year OS and toxicity favor short-course radiation and sequential chemotherapy.
**'''2019''' {{PMID|31192355}} -- "Long-course preoperative chemoradiation versus 5 x 5 Gy and consolidation chemotherapy for clinical T4 and fixed clinical T3 rectal cancer: long-term results of the randomized Polish II study." (Cisel B, Annals of Oncology, Augs1;30(8):1298-1303)
***Outcome: 8-year OS 49% in both groups. Late toxicity: short-course 11%, long-course 9%. No difference in local failure or development in distant metastases.
***Author's conclusions: The superiority of short course RT was not demonstrated.
*'''MRC CR07 and NCIC C016''' (1998-2005) -- preop RT 25/5 vs. selective postop chemo-RT 45/25
**Randomized. 1350 patients, operable carcinoma of rectum, <15cm from anal verge, TME encouraged but not mandated (done in 92%). Arm 1) RT 25/5 vs. Arm 2) surgery + selective postop chemo-RT if SM+ (RT 45/25 + concurrent 5-FU and leucovorin). RT sacral promontory superiorly, 3–5 cm below the inferior tumor extent, 2–3 cm anterior to the sacral promontory, 1 cm posterior to the anterior sacrum, and 1 cm lateral to the most lateral aspect of the bony true pelvis. Primary outcome LR. In postop arm, SM+ was in 12% as trigger for postop chemo-RT vs 10% in preop group. Adjuvant chemo in 40% of preop arm and 45% of postop arm
**'''2009''' {{PMID|19269519}} -- "Preoperative radiotherapy versus selective postoperative chemoradiotherapy in patients with rectal cancer (MRC CR07 and NCIC-CTG C016): a multicentre, randomised trial." (Sebag-Montefiore D, Lancet. 2009 Mar 7;373(9666):811-20.) Median F/U 4 years
***Outcome: LR preop RT 4% vs. postop RT 11% (SS), DFS 77% vs. 71% (SS), no difference in OS. By SM status: SM+ 14% vs. 21% (NS), SM- 4% vs. 9% (SS). Upper 1/3 tumors lower LRR than lower 1/3, preop RT 1% vs. 5%, postop chemo-RT 6% vs. 10%
***Conclusion: Short-course RT more effective than selective postop chemo-RT
**Editorial ({{PMID|19269501}}): Preop RT appears to benefit both good-prognosis and bad-prognosis tumors, so need a good way to select, and patient preference likely to play a role. Nevertheless, short preop RT is an excellent option
**'''2009; Plane of surgery''' {{PMID|19269520}} -- "Effect of the plane of surgery achieved on local recurrence in patients with operable rectal cancer: a prospective study using data from the MRC CR07 and NCIC-CTG CO16 randomised clinical trial." (Quirke P, Lancet. 2009 Mar 7;373(9666):821-8.)
***Negative CRM and good surgical plane associated with low LR. 3-yr LR 6% vs 17% for negative vs positive resection margin. LR 4% (mesorectal plane), 7% (intramesorectal), and 13% (muscularis propria). Pts with mesorectal excision who had pre-op RT had only a 1% LR.
***Conclusion: the plane of surgery is an important prognostic indicator for local recurrence. Short-course pre-op RT reduced the rate of LR in all groups
*'''German Rectal Cancer Study''' CAO/ARO/AIO-94 (1995-2002) -- preop chemo-RT vs. postop chemo-RT
**Randomized. 823 patients, clinical stage T3-4 or N+, inferior margin within 16cm from anal verge. Arm 1) ''post-op regimen:'' surgery (TME) -> chemo/RT (55.8 Gy) -> 4 cycles bolus 5-FU, or 2) ''pre-op regimen:'' chemo/RT (50.4 Gy) -> surgery (TME) -> 4 cycles bolus 5-FU. In both arms, chemo was 5-FU C.I. 1000 mg/m2/d on days 1-5, weeks 1+5.
**'''2004''' {{PMID|15496622}} [http://content.nejm.org/cgi/content/full/351/17/1731 Full text] "Preoperative versus postoperative chemoradiotherapy for rectal cancer." (Sauer R, N Engl J Med. 2004 Oct 21;351(17):1731-40.) Median F/U 3.8 years
***Outcome: 5-year OS preop 76% vs postop 74% (NS); 5-year DFS 68% vs. 65% (NS); LR 6% vs. 13% (SS); DM 36% vs. 38% (NS). Preop downstaging: pCR 8%, 25% (vs 40%) were Stage III/LN+. TNM Stage I disease found in 18% of post-op group (vs. 25% in pre-op). Increased rate of sphincter-preserving surgery (39% vs 19%) in preoperative-treatment group among patients thought to need it preoperatively; overall rates of sphincter preservation same 69% vs 71%.
***Toxicity: Fewer acute (27% vs 40%) and late toxicities (14% vs 24%) in preoperative-treatment group.
***Conclusion: Preop chemo-RT improved local control and improved toxicity, but did not impact overall survival
**Critique (and clinical reality): only 54% of adjuvant patients vs. 92% of neoadjuvant patients received full RT dose
**'''2012''' {{PMID|22529255}} -- "Preoperative Versus Postoperative Chemoradiotherapy for Locally Advanced Rectal Cancer: Results of the German CAO/ARO/AIO-94 Randomized Phase III Trial After a Median Follow-Up of 11 Years." (Sauer R, J Clin Oncol online ahead of print April 23, 2012)
***Median f/u 134 mo. 10-yr OS preop 59.6% vs postop 59.9% (NS). Local Recurrence: 7.1% vs 10.1% (SS). DM: 29.8% vs 29.6% (NS). DFS: NS.
***Conclusion: "There is a persisting significant improvement of pre- versus postoperative CRT on local control; however, there was no effect on overall survival. "
*'''NSABP R-03''' (1993-1999) -- Preop vs postop chemo-RT
**Randomized. ''Trial closed prematurely due to poor accrual''. 267/900 expected patients. Clinical T3-T4 or N+ rectal cancer. Arm 1) Preop chemo-RT 50.4/28 + 5-FU 500 mg/m2 and leucovorin 500 mg/m2 vs Arm 2) Postop chemo-RT (same as preop). Surgery APR, LAR, or local excision; TME not mandated. Both groups adjuvant 3 cycles of 5-FU/leucovorin
**'''2009''' {{PMID|19770376}} [http://jco.ascopubs.org/cgi/reprint/27/31/5124 Full text] — "Preoperative multimodality therapy improves disease-free survival in patients with carcinoma of the rectum: NSABP R-03." (Roh M et al. J Clin Oncol. 2009 Nov 1;27(31):5124-30. Epub 2009 Sep 21.)
***Outcome: 5-year DFS was improved for pre-op over post-op (64.7% v 53.4%, SS). Nonsignificant trend in 5-year OS (74.5% v 65.6%, p=0.065). No difference in locoregional recurrence, 11% in each group. pCR in 15%. Significant reduction in N+ (67% vs. 52%, SS)
***Toxicity: Grade 4 diarrhea preop 24% vs. postop 13%; Grade 5 toxicity 5% vs 3%
***Conclusion: Pre-op chemoradiotherapy, compared with post-op chemoradiotherapy, significantly improved DFS and showed a trend toward improved OS
===RT Alone===
*'''Sweden (Uppsala)''' (1980-1985)
**Randomized. Multicenter. 471 patients with rectal and rectosigmoid CA. Treated with 1) preop RT 25.5/5 in one week or 2) postop RT 60/30 (Modified Dukes' stage B2 or C only, equivalent to Dukes B-C, T3-T4 or N+).
***''Technique:'' Treated prone. Target volume was from the anus up to L4. Three field - PA + 2 angled dorsal beams.
**'''1990''' {{PMID|2405793}} (Full-text on Pubmed Central) — "Pre- or postoperative radiotherapy in rectal and rectosigmoid carcinoma. Report from a randomized multicenter trial." Pahlman L et al. Ann Surg. 1990 Feb;211(2):187-95.
***Minimum F/U 3 years; The early results are as follows
***LR: preop RT 12% vs. postop RT 21% (SS, p<0.02). No difference in OS
***Toxicity: Pre-op vs Post-op RT [ Mortality-3% vs 5% (NS); Post-op perineal sepsis-33% vs 18% (SS,p<0.01)
**'''1993''' {{PMID|8500374}} — "Preoperative or postoperative irradiation in adenocarcinoma of the rectum: final treatment results of a randomized trial and an evaluation of late secondary effects." (Frykholm GJ, Dis Colon Rectum. 1993 Jun;36(6):564-72.)
***Minimum F/U 5 years
***LR: preop RT 13% vs. postop RT 22% (SS). No difference in OS
***Toxicity: SBO rate - preop RT 5% vs. postop RT 11% vs. surgery alone 6%
**Conclusion: Preop RT better, late morbidity comparable after 5-10 year follow-up
==Preop RT vs. surgery alone==
*Goal is sphincter preservation
*On meta-analysis, 5-year decrease in local recurrence from 22% with surgery alone to 12% with pre-op RT
*No impact on overall survival. Rectal cancer survival was significantly better with pre-op RT (50% vs. 45%), but early mortality was significantly higher as well (8% vs. 4%), for no difference in OS
===Total Mesorectal Excision===
*'''Dutch''' (1996-1999)
**Randomized. 1805 patients treated with 1) Preop RT 25/5 or 2) TME alone. If surgery-only patients had SM+ (<=1mm), mandatory post-op RT
**'''2-years; 2001''' {{PMID|11547717}} -- "Preoperative radiotherapy combined with total mesorectal excision for resectable rectal cancer." (Kapiteijn E, N Engl J Med. 2001 Aug 30;345(9):638-46.)
***2-year OS: RT 82% vs. TME alone 82%
***2-year LR: RT 2.4% vs. TME alone 8.2% (SS)
***Conclusion: Short-term preop RT reduces risk of LR with TME
**'''2003''' {{PMID|12654443}} -- "Radiotherapy does not compensate for positive resection margins in rectal cancer patients: report of a multicenter randomized trial." (Marinjen CA, Int J Radiat Oncol Biol Phys. 2003 Apr 1;55(5):1311-20.)
***LR as a function of surgical margins:
****Wide SM: preop RT 1% vs. 6% (SS)
****Narrow SM: preop RT 0% vs. 15% (SS)
****Positive SM: preop RT 9% vs. 16% (NS)
***120 patients in surgery-only group with SM+; 47% received post-op RT; LR: Post-op RT 17% vs. surgery only 16% (NS)
***Conclusion: Preop RT beneficial with wide or narrow SM, but not in positive SM.
**'''5-years; 2007''' {{PMID|17968156}} -- "The TME Trial After a Median Follow-up of 6 Years: Increased Local Control But No Survival Benefit in Irradiated Patients With Resectable Rectal Carcinoma." (Peeters KC, Ann Surg. 2007 Nov;246(5):693-701.). Median F/U 6.1 years
***Outcome: 5-year LR TME 11% vs. RT + TME 6% (SS); OS 63% vs. 64% (NS)
***Subgroup benefit: N+, tumors 5-10 cm from anal verge, negative radial margins
***Conclusion: Preop short-term RT improves local control; no effect on survival
**'''Local Recurrence; 2010''' {{PMID|20096534}} -- "Patterns of local recurrence in rectal cancer; a study of the Dutch TME trial." (Kusters M, Eur J Surg Oncol. 2010 Jan 20. [Epub ahead of print])
***Outcome: 5-year LR rate RT+ 5% vs RT- 11%. Most common location presacral failure (43% and 33%). RT significantly reduced anastomotic LR (from 2.7% to 0.7%)
***Conclusion: RT reduces LR in all subsites, and is especially effective in preventing anastomotic LR after LAR
**'''12-years; 2011''' {{PMID|21596621}} -- "Preoperative radiotherapy combined with total mesorectal excision for resectable rectal cancer: 12-year follow-up of the multicentre, randomised controlled TME trial." (van Gijn W, Lancet Oncol. 2011 Jun;12(6):575-82.)
***10-yr incidence of LR 5% RT+ vs 11% RT-. No difference in OS.
***Conclusion: LR reduced by more than 50% with RT compared to TME alone.
===Non-TME Surgical Technique===
*'''Swedish Rectal Cancer Trial''' (1987-1990)
**Randomized. 1168 patients, 908 curative intent (included 316 patients from Stockholm II). Treated with 1) preop RT 25/5, surgery within 1 week or 2) surgery alone. RT given as AP/PA, 3-field, or 4-field; superior border at L4
**'''1993''' {{PMID|8242317}} — "Initial report from a Swedish multicentre study examining the role of preoperative irradiation in the treatment of patients with resectable rectal carcinoma. Swedish Rectal Cancer Trial." [No authors]. Br J Surg. 1993 Oct;80(10):1333-6.
***Postop mortality comparable (4% vs. 3%); but much higher if 2F rather than 3F or 4F technique (15% vs. 3%)
***No difference in anastomotic dehiscence or other complications; more wound infections with RT
**'''1995''' {{PMID|8781922}} — "Local recurrence rate in a randomised multicentre trial of preoperative radiotherapy compared with operation alone in resectable rectal carcinoma. Swedish Rectal Cancer Trial." [No authors]. Eur J Surg. 1996 May;162(5):397-402.
***Local recurrence at 2 years: RT 9% vs. surgery alone 24% (SS); significant for all Dukes stages
**'''1997''' {{PMID|9091798}} — "Improved survival with preoperative radiotherapy in resectable rectal cancer. Swedish Rectal Cancer Trial." Pahlman L et al. [No authors listed] N Engl J Med. 1997 Apr 3;336(14):980-7.
***Local recurrence at 5 years: RT 11% vs surgery alone 27% (SS)
***Overall survival: RT 58% vs 48% (SS)
**'''Cost-effectiveness; 2002''' {{PMID|12377315}} -- "Cost-effectiveness of preoperative radiotherapy in rectal cancer: results from the Swedish Rectal Cancer Trial." (Dahlberg M, Int J Radiat Oncol Biol Phys. 2002 Nov 1;54(3):654-60.)
***8 year F/U. 98/1168 randomly selected patients from main trial from single region.
***Total costs: RT USD 35,300 vs. surgery alone USD 30,000
***Survival benefit 21 months - cost of year saved USD 3,654. Sensitivity analysis worst case USD 15,228
**'''13-years; 2005''' {{PMID|16110023}} — "Swedish Rectal Cancer Trial: long lasting benefits from radiotherapy on survival and local recurrence rate." Folkesson J et al. J Clin Oncol. 2005 Aug 20;23(24):5644-50. Median F/U 13 years
***Overall survival: RT 38% vs. surgery alone 30% (SS); cancer-specific 72% vs. 62% (SS)
***Local recurrence: RT 9% vs. surgery alone 26% (SS)
**'''Late toxicity; 2005''' {{PMID|16314629}} — "Adverse effects of preoperative radiation therapy for rectal cancer: long-term follow-up of the Swedish Rectal Cancer Trial." Birgisson H et al. J Clin Oncol. 2005 Dec 1;23(34):8697-705.
***Side effects: RT group more likely to be admitted <6 months after treatment (mostly GI related); no difference >6 months out
***Bowel obstruction: more common long term in RT patients
**'''Late GI toxicity; 2008''' {{PMID|17849380}} -- "Late gastrointestinal disorders after rectal cancer surgery with and without preoperative radiation therapy." (Birgisson H, Br J Surg. 2008 Feb;95(2):206-13.)
***Outcome: RT increased risk of SBO (RR 2.5), surgically managed SBO (RR 7.4). Difference seen after 7-8 years for conservatively managed SBO, after 1-2 years for surgically managed SBO. No impact of RT technique
***Conclusion: Small bowel obstruction more common in preop RT
**<u>Conclusion</u>: 8% survival benefit, 10% cancer specific benefit, 17% local recurrence benefit long term
**<u>Criticism</u>: high recurrence rate in surgery-alone arm (26%)
*'''Stockholm 1''' (1980-1987)
**Randomized. 849 patients, 679 curative intent. Treated with 1) preop RT 25/5 vs. 2) surgery alone. Median F/U 4.4 years
**'''1995''' {{PMID|7712435}} -- "The Stockholm I trial of preoperative short term radiotherapy in operable rectal carcinoma. A prospective randomized trial. Stockholm Colorectal Cancer Study Group." (Cedermark B, Cancer. 1995 May 1;75(9):2269-75.). Median F/U 8.9 years
***Curative intent: LR (SS) better with RT. Time-to-failure (SS) better with RT. No difference in DM or OS
***Toxicity: postop mortality 8% with RT vs. 2% surgery only (SS)
**'''1990''' {{PMID|2191763}} -- "Preoperative short-term radiation therapy in operable rectal carcinoma. A prospective randomized trial. Stockholm Rectal Cancer Study Group." (No Authors, Cancer. 1990 Jul 1;66(1):49-55.)
***RT fields to pelvis and para-aortic LN to L2. AP/PA portals permitted.
***Curative intent: LR (SS) better with RT. Time-to-failure (SS) better with RT. No difference in DM or OS
***Toxicity: postop mortality 8% with RT vs. 2% surgery only (SS)
**Conclusion: preop RT better, but at high periop mortality cost. RT fields need to be adjusted, see Stockholm 2
*'''Stockholm 2'''
**Randomized. 557 patients from 12 centers. Treated with 1) preop RT 25/5, or 2) surgery alone. RT fields to pelvis only, mandated 3F or 4F plans (no AP/PA only). Median F/U 4.2 years
**'''1996''' {{PMID|8876883}} -- "Randomized study on preoperative radiotherapy in rectal carcinoma. Stockholm Colorectal Cancer Study Group." (No Authors, Ann Surg Oncol. 1996 Sep;3(5):423-30.)
***Outcome: LR: preop RT 10% vs. surgery only 21% (SS). Distant mets 19% vs. 26% (SS); OS improved with preop RT
**Conclusion: Preop RT reduces LR and DM, and improves OS
*'''Stockholm 3'''
**Randomized. 303 patients were randomized to either short-course RT (5 x 5 Gy) and surgery within 1 week (group 1), short-course RT and surgery after 4-8 weeks (group 2) or long-course RT (25 x 2 Gy) and surgery after 4-8 weeks (group 3). No Chemotx allowed in this trial.
**'''2010''' {{PMID|20155787}} -- "Interim analysis of the Stockholm III trial of preoperative radiotherapy regimens for rectal cancer." (Pettersson D, Br J Surg. 2010 Apr;97(4):580-7)
***Outcome: Patients receiving short-course RT with surgery 11-17 days after the start of RT had the highest complication rate (~65% of patients).
**Conclusion: 4-8 week delay after short-course RT decreases complication rate.
*'''MRC''' (1981-1989) {{PMID|8961989}} -- "Randomised trial of surgery alone versus radiotherapy followed by surgery for potentially operable locally advanced rectal cancer. Medical Research Council Rectal Cancer Working Party." (No Authors, Lancet. 1996 Dec 14;348(9042):1605-10.)
**Randomized. 279 patients from 20 centers. Treated with 1) surgery alone, or 2) preop RT 40/20. Minimum F/U 5 years
**Median OS: 24 months vs. 31 months (NS). But benefit on DFS
**LR: surgery 46% vs. preop RT 36% (SS). DM surgery 48% vs. preop RT 35%
**Conclusion: Preop RT reduces LR, but survival equivocal
*'''UK Multicentre''' {{PMID|7530469}} -- "Long-term results of a randomised trial of short-course low-dose adjuvant pre-operative radiotherapy for rectal cancer: reduction in local treatment failure." (Goldberg PA, Eur J Cancer. 1994;30A(11):1602-6.)
**Randomized. 468 patients with rectal CA <=12 cm from anal verge. RT 15/3 within 2 days of surgery vs. surgery alone. Minimum F/U 5 years
**Perioperative mortality: RT 9% vs. surgery alone 4% (SS)
**LR: RT 17% vs. surgery alone 24% (SS)
**No difference in OS
*'''Northwest Rectal Cancer Group''' (UK) (1982-1986) {{PMID|7995145}} -- "Adjuvant preoperative radiotherapy for locally advanced rectal carcinoma. Results of a prospective, randomized trial." (Marsh PJ, Dis Colon Rectum. 1994 Dec;37(12):1205-14.)
**Randomized. 284 patients. Preop RT 20/4 to 10x10x10cm volume in posterior pelvic vs surgery alone. Minimum F/U 8 years
**No difference in overall or cancer-specific survival, but survival benefit for subset considered to receive curative operation
**LR: RT 13% vs. surgery alone 36% (SS). 10 recurrences infield, 6 recurrences out of field. DM same
**Conclusion: Recommend to all patients who will undergo curative surgery
*'''Western Norway''' (1976-1985) {{PMID|2245382}} -- "Low-dose preoperative radiation postpones recurrences in operable rectal cancer. Results of a randomized multicenter trial in western Norway." (Dahl O, Cancer. 1990 Dec 1;66(11):2286-94.)
**Randomized. 309 patients. Randomized to preop RT 31.5/18 with radical surgery 2-3 weeks later, or surgery alone
**No tumor in 5% patients. No increased morbidity or mortality at surgery
**5-year OS: surgery alone 57% vs. RT 57%
**Recurrence: surgery alone 13 months vs. RT 27 months (SS); LR 21% vs. 14%
**Conclusion: should use higher RT dose
*'''Sao Paulo''' (1978-1980) {{PMID|2752859}} -- "A comparison of nonoperative vs. preoperative radiotherapy in rectal carcinoma. A 10-year randomized trial." (Reis Neto JA, Dis Colon Rectum. 1989 Aug;32(8):702-10.)
**Randomized. 68 patients (26% in group 1 were Dukes C, 47% in group 2 were Dukes C). Randomized to 1) preoperative RT 40/20 + surgery within 1 week, or 2) surgery alone. Minimum F/U 8 years
**5-year OS: RT 80% vs. 34%
**Local recurrence: RT 3% vs. 23%
*'''EORTC''' (1976-1981) {{PMID|3056288}} -- "Preoperative radiotherapy as adjuvant treatment in rectal cancer. Final results of a randomized study of the European Organization for Research and Treatment of Cancer (EORTC)." (Gerard A, Ann Surg. 1988 Nov;208(5):606-14.)
**Randomized. 466 patients. Treated with 1) surgery alone, or 2) preop RT 34.5/15 in 2.3 Gy/fx
**5-year OS: no difference (59% vs. 69%) (p=0.08)
**5-year LR: surgery 30% vs. 15% (SS)
*'''Meta-analysis, 2001''' {{PMID|11684209}} -- "Adjuvant radiotherapy for rectal cancer: a systematic overview of 8,507 patients from 22 randomised trials." (Colorectal Cancer Collaborative Group, Lancet. 2001 Oct 20;358(9290):1291-304.)
**22 randomized trials comparing pre- and post-op RT with surgery alone. Centrally analysed individual patient data from 14 preop (6,350 patients) and 8 postop (2,157 patients)
**5-year OS: marginally better with RT (62% vs. 63%, p=0.06)
**Curative resection: not improved by RT (86% vs. 85%)
**Annual risk of recurrence: preop RT 46% lower, postop RT 37% lower
**Preop RT: fewer deaths from rectal CA (45% vs. 50%, SS), but more early deaths (8% vs. 4%, SS)
**Conclusion: Preop RT reduces risk of LR and death from rectal cancer, but due to high early mortality has no impact on overall survival. Post-op RT also reduces LR.
==Preop RT vs Preop Chemo-RT==
*'''Cochrane Meta-analysis'''--
**'''2013''' {{PMID|23450565}} -- "Preoperative chemoradiation versus radiation alone for stage II and III resectable rectal cancer." (Laura De Caluwé et al.Cochrane Database Syst Rev. 2013 Feb 28;2)
***Five trials were identified and included in the meta-analysis. From one of the included trials only preliminary data are reported.
***Outcome:
****Response rate: CRT significantly increased the rate of complete pathological response (OR 2.12-5.84, P < 0.00001)
****Sphincter Preservation: did not translate into a higher sphincter preservation rate (OR 0.92-1.30, P = 0.32)
****Post-op Morbidity: marginally affected postoperative overall morbidity (OR 0.67-1.00, P = 0.05)
****Anastomotic leak: No differences were observed in anastomotic leak rate
****Post-op Mortality: No differences were observed in postoperative mortality
****Local recurrence: at five years was significantly lower in the CRT group compared to RT alone (OR 0.39-0.72, P < 0.001).
****Survival: No statistically significant differences in DFS (OR 0.92-1.34, P = 0.27) or OS (OR 0.79-1.14,P = 0.58) at five years.
***Toxicity: increased grade III and IV acute toxicity (OR 1.68-10, P = 0.002)
***Conclusion: CRT results in SS improved pCR and LC but this does not translate into either improved sphincter preservation or OS/DFS benefit.
*'''TROG 01.04''' (Trans-Tasman Radiation Oncology Group) -- RT 25/5 Short Course vs Chemo-RT 50.4/28 with C.I. 5-FU
**Randomized. 326 pts. Staged with ultrasound or MRI as T3N0-2. Short course (SC): RT 25/5 followed by early surgery and 6 courses of adjuvant chemo. Long course (LC): 50.4/28 with 5-FU, followed by surgery in 4-6 weeks, then 4 courses of adjuvant chemotherapy.
**'''2012''' {{PMID|23008301}} -- "Randomized Trial of Short-Course Radiotherapy Versus Long-Course Chemoradiation Comparing Rates of Local Recurrence in Patients With T3 Rectal Cancer: Trans-Tasman Radiation Oncology Group Trial 01.04" (Ngan SY, J Clin Oncol. 2012 -- online before print, 9/24/12)
***No significant differences in LR, DR, or OS. 3-yr LR: 7.5% for SC vs 4.4% for LC (NS). 5-yr distant recurrence: 27% vs 30% (NS). 5-yr OS: 74% vs 70% (NS). Late toxicity rates not different.
***Distal tumors (< 5 cm): LR in 6 of 48 pts (SC) vs 1 of 31 (LC) (NS).
***Conclusion: "Three-year LR rates between SC and LC were not statistically significantly different." "LC may be more effective in reducing LR for distal tumors. No differences in rates of distant recurrence, relapse-free survival, overall survival, or late toxicity were detected."
*'''French FFCD 9203''' (1993-2003)
**733 pts. Resectable T3-T4, Nx. Randomized to: 1) 45 Gy RT alone vs 2) RT with concurrent bolus 5-FU (350 mg/m2) + leucovorin on days 1-5, weeks 1,5. Both groups followed by surgery and 4 cycles of adjuvant 5-FU/Leucovorin.
**'''2006''' {{PMID|17008704}} -- "Preoperative radiotherapy with or without concurrent fluorouracil and leucovorin in T3-4 rectal cancers: results of FFCD 9203." (Gerard JP, J Clin Oncol. 2006 Oct 1;24(28):4620-5.)
***5-year OS (primary endpoint): no difference. Sphincter preservation: no difference
***5-year LR: CRT 8% vs. 16% RT alone (SS)
***Grade 3+ toxicity: CRT 15% vs. 3% RT alone (SS)
***Conclusion: chemoradiation recommended for improved local control
**'''2005''' ASTRO Plenary #4 - [http://progressive.playstream.com/astro/progressive/index.html Webcast] — "Preoperative Chemoradiotherapy (CT-RT) Improves Local Control in T3-4 Rectal Cancers: Results of the FFCD 9203 Randomized Trial." Gerard J et al. IJROBP Volume 63, Supplement 1, 1 October 2005, Pages S2-S3.
***Median f/u 69 mo. Equivalent rate of sphincter-sparing surgery, 51%. Chemo/RT led to improved pCR 11.7% vs 3.7%, 5-yr LF 8% vs 16.5%. No diff in OS.
***Conclusion: less tumor recurrence after chemo/RT compared to RT alone
*'''EORTC 22921'''
**Randomized. 2x2 design. 1011 patients with T3 or T4 resectable rectal CA. Treated with 1) Preop RT, 2) Preop CRT, 3) Preop RT + postop CT, or 4) Preop CRT + postop CT. RT given 45/25 to posterior pelvis. 5-FU given 350 mg/m2/day
**'''2007''' {{PMID|17906203}} -- "Patients with curative resection of cT3-4 rectal cancer after preoperative radiotherapy or radiochemotherapy: does anybody benefit from adjuvant fluorouracil-based chemotherapy? A trial of the European Organisation for Research and Treatment of Cancer Radiation Oncology Group." (Collette L, J Clin Oncol. 2007 Oct 1;25(28):4379-86.)
***Data from 785 patients with adjuvant chemo
***Outcome: No benefit in entire group. However, ypT0-2 benefit (SS), while ypT3-4 no benefit
***Conclusion: Only good-prognosis patients (T0-2 on surgery) benefit from adjuvant chemo
**'''2006''' {{PMID|16971718}} -- "Chemotherapy with preoperative radiotherapy in rectal cancer." (Bosset JF, N Engl J Med. 2006 Sep 14;355(11):1114-23.)
***5-year OS: overall 65% (no difference among the 4 groups)
***5-year LR: preop RT 17% vs. CRT 9% (preop CRT 9% vs. preop RT + postop CT 10% vs. preop CRT + postop CT 8%)
***Adherence: 82% for preop CT vs. 43% for postop CT
**'''2005''' {{PMID|16009958}}, 2005 — "Enhanced tumorocidal effect of chemotherapy with preoperative radiotherapy for rectal cancer: preliminary results--EORTC 22921." Bosset JF et al. J Clin Oncol. 2005 Aug 20;23(24):5620-7.
***Tumors after preop CRT vs RT alone: smaller, lower pT, lower pN, fewer examined nodes, less LVN, increase in mucinous tumors
***Conclusion: Significant downstaging with CRT over RT alone
**'''Dose Escalation; 1993''' {{PMID|8398268}} -- "Determination of the optimal dose of 5-fluorouracil when combined with low dose D,L-leucovorin and irradiation in rectal cancer: results of three consecutive phase II studies. EORTC Radiotherapy Group." (Bosset JF, Eur J Cancer. 1993;29A(10):1406-10.)
***Three Phase II 5-FU dose escalation trials. Locally extended rectal CA. Preop RT 45/25 + concurrent 5-FU.
***Dose: 425 mg/m2/day + 370 mg/m2/day => 370 mg/m2/day + 370 mg/m2/day => 350 mg/m2/day + 350 mg/m2/day
***Conclusion: 350 mg/m2/day best tolerated; used in EORTC 22921
**<u>Overall conclusion:</u> chemo adds significant benefit to RT alone, regardless if it's before or after surgery
==Preop Chemo-RT vs Preop Chemo Only==
*'''PROSPECT / Alliance N1048''' (2012 - 2018) -- 1) FOLFOX vs 2) CRT
**Randomized. T2N+ or T3, candidate for sphincter-sparing surgery. 1128 patients. Arm 1) FOLFOX x6 cycles Q2W (RT permitted if primary tumor decrease <20% or FOLFOX discontinued for side effects), vs Arm 2) RT 50.4 Gy in 28 fractions with 5FU. Primary endpoint DFS
**'''Outcome; 2023''' {{PMID|37272534}} -- "Preoperative Treatment of Locally Advanced Rectal Cancer" (Schrag D, N Engl J Med. 2023 Jul 27;389(4):322-334. doi: 10.1056/NEJMoa2303269. Epub 2023 Jun 4.
***Outcome: 5-year DFS FOLFOX 81% vs CRT 79% (NS), no difference in OS or LR
***Conclusion: Preop FOLFOX non-inferior to CRT
**'''Patient Reported Outcomes; 2023''' {{PMID|37270691}} -- "Patient-Reported Outcomes During and After Treatment for Locally Advanced Rectal Cancer in the PROSPECT Trial (Alliance N1048)" (Basch E, J Clin Oncol. 2023 Jul 20;41(21):3724-3734. doi: 10.1200/JCO.23.00903. Epub 2023 Jun 4.)
***FOLFOX better: diarrhea, overall bowel function
***CRT better: anxiety, appetite, constipation, depression, dysphagia, dyspnea, edema, fatigue, mucositis, nausea/vomiting, neuropathy
***No difference: bladder function
***Conclusion: Distinctive side effect profiles for shared decision making
==Preop Chemo-RT/adjuvant chemo vs. Total Neoadjuvant Therapy==
*'''RAPIDO''' (2011-2016) -- 1) Total Neoadjuvant Therapy 25 Gy in 5 fx, then CAPOX or FOLFOX4, then TME; or 2) Conventional ChRT 50.4 Gy in 28 fx with concurrent 5FU or capecitabine, TME, then CAPOX or FOLFOX4
**Randomized 920 - "high-risk on pelvic MRI" including cT4a or cT4b, extramural vascular invasion, cN2, involved mesorectal fascia or enlarged lateral lymph nodes, multicenter Europe and USA
**'''2021''' {{PMID|33301740}} -- "Short-course radiotherapy followed by chemotherapy before total mesorectal excision (TME) versus preoperative chemoradiotherapy, TME and optional adjuvant chemotherapy in locally advanced rectal cancer (RAPIDO)" (Bahadoer RR, Lancet Oncol 2021)
***Outcome: 3-yr recurrence rate TNT 23.7%, conventional 30.4%; Grade 3 diarrhea TNT 18%, conventional 9%
***Conclusions: Decrease in disease-related treatment failure "probably indicative of the increased efficacy of preoperative chemotherapy."
**'''2023''' {{PMID|36661037}} -- "Locoregional failure during and after short-course radiotherapy followed by chemotherapy and surgery compared with long-course chemoradiotherapy and surgery: A 5-year follow up of the RAPIDO trial." (Dijkstra EA, Ann Surg 2023)
***Outcome: At 5-yr median f/u, LRR Short-course RT 10%, conventional 6% (SS)
***Conclusions: Short-course radiation (in TNT arm) associated with increase in locorgeional recurrence. Refinement of TNT needed.
==Preop Chemo-RT: Chemotherapy Regimen==
<big>'''Randomized studies:'''</big>
* '''STELLAR (China)''' (2015-2018) -- RT 25/5 + chemo vs RT 50/25 + chemo
**Randomized. 599 patients, distal/middle rectal cancer, Stage III-IV or N+. Arm 1) RT 25/5 over 1 week followed by chemo x4 cycles (TNT) vs RT 50/25 over 5 weeks with concurrent capecitabine (CRT). Total mesorectal excision 6-8 weeks later. Followed by Arm 1) CAPOX x 2 cycles or Arm 2) CAPOX x6 cycles. Primary endpoint 3-year DFS
**'''2022''' {{PMID|35263150}} -- "Multicenter, Randomized, Phase III Trial of Short-Term Radiotherapy Plus Chemotherapy Versus Long-Term Chemoradiotherapy in Locally Advanced Rectal Cancer (STELLAR)" (Jin J, J Clin Oncol. 2022 Mar 9;JCO2101667.doi: 10.1200/JCO.21.01667. Online ahead of print.) Median F/U 2.9 years
***Outcome: 3-year DFS TNT 64% vs CRT 62% (NS). 3-year OS 86% vs 75% (p=0.03)
***Toxicity: Acute G3+ 26% vs 12% (p<0.001)
***Conclusion: Short term RT with chemo efficacious, acceptable toxicity, can be used as alternative to CRT
<p>'''''+/- Oxaliplatin:'''''</p>
*'''STAR-01''' -- 5-FU +/- Oxali
**Randomized. 747 pt, T3-T4 or N+. RT 50.4 Gy. Randomized to: Arm A) C.I. 5-FU alone (225 mg/m2/d), or B) 5-FU plus oxaliplatin (60 mg/m2 weekly).
**'''2011''' {{PMID|21606427}} -- "Primary Tumor Response to Preoperative Chemoradiation With or Without Oxaliplatin in Locally Advanced Rectal Cancer: Pathologic Results of the STAR-01 Randomized Phase III Trial." (Aschele C, J Clin Oncol. 2011 May 23. [Epub ahead of print])
***No difference in pCR rate (16% in both arms), pN+ (26% vs 29%), pT3 (46% vs 44%), or positive circumferential resection margins (7% v 4%).
***Grade 3-4 toxicity more frequent with oxali (8% v 24%). Higher rate of completing RT (>45 Gy) in control arm: 97% vs 91%.
***Conclusion: Adding oxaliplatin to 5-FU - RT increases toxicity without affecting tumor response.
*'''ACCORD 12/0405-Prodige 2''' (2005-2008) -- Cap 45 vs Capox 50
**Randomized. 598 patients, resectable T3-T4 rectal adenoca, T2 tumors in anterior/lower rectum also included. Arm 1) RT 45/25 with concurrent capecitabine 800 mg/m2 BID (Cap 45) vs Arm 2) RT 50/25 with concurrent capecitabine 800 mg/m2 BID and oxaliplatin 50 mg/m2 QW (Capox 50). RT excluded external/common illiac, in Capox 50 group boost after 44 Gy. Primary endpoing ypCR to get quick answer, as follow up to FFCD 9203
**'''2010''' {{PMID|20194850}} -- "Comparison of two neoadjuvant chemoradiotherapy regimens for locally advanced rectal cancer: results of the phase III trial ACCORD 12/0405-Prodige 2." (Gerard JP, J Clin Oncol. 2010 Apr 1;28(10):1638-44. Epub 2010 Mar 1.)
***Outcome: ypCR Cap45 14% vs Capox 50 19% (NS). SM+ (0-2mm) 19% vs 10% (SS)
***Toxicity: Preop G3+ Cap 45 1% vs Capox 50 25% (SS). No difference in surgery (75%) or postop deaths (0.3%).
***Conclusion: Benefit of oxaliplatin not demonstrated. Suggest Cap 50 as the next regimen to test
**'''2012''' {{PMID|23109696}} -- "Clinical Outcome of the ACCORD 12/0405 PRODIGE 2 Randomized Trial in Rectal Cancer." (Gerard JP, J Clin Oncol -- online before print, Oct 29 2012.)
***At 3 yrs, no sig difference in LR (Cap45 6.1% vs Capox50 4.4%), OS (87.6% vs 88.3%), or DFS (67.9% vs 72.7%).
***On multivariate analysis, the main prognostic factor was the pCR rate
***Conclusion: "At 3 years, no significant difference in clinical outcome was achieved with the intensified CAPOX regimen. When compared with other recent randomized trials, these results indicate that concurrent administration of oxaliplatin and RT is not recommended. "
<p>'''''+/- Cetuximab'''''</p>
*'''EXPERT-C''' [http://clinicaltrials.gov/ct2/show/NCT00383695 Clinicaltrials] - Randomized Phase II -- Preop chemo/RT and adjuvant chemo +/- Cetuximab
**165 pts. Operable tumors, MRI defined high risk (1 or more of following: tumors within 1 mm of mesorectal fascia, T3 tumors at or below levators, extending >= 5 mm into perirectal fat, T4 tumors, extramural venous invasion).
**Randomized to: 1) Neoadjuvant oxali + capecitabine (CAPOX) x 4 cycles; followed by neoadjuvant chemo/RT with concurrent capecitabine; surgery / TME; adjuvant chemotherapy CAPOX x 4 cycles; or 2) same regimen plus cetuximab (given weekly during neoadj chemo and chemo/RT x 17 weeks, adjuvant x 12 weeks)
**'''2012''' {{PMID|22473163}} -- "Multicenter Randomized Phase II Clinical Trial Comparing Neoadjuvant Oxaliplatin, Capecitabine, and Preoperative Radiotherapy With or Without Cetuximab Followed by Total Mesorectal Excision in Patients With High-Risk Rectal Cancer (EXPERT-C)" (Dewdney A, J Clin Oncol. 2012 Apr 2. [Epub ahead of print])
***60% of tumors were KRAS or BRAF wild-type. In tumors that were wild-type, addition of cetuximab did not improve pCR: 9% (CAPOX) vs 11% (CAPOX+C); PFS not improved. Cetuximab improved RR (51 vs 71% after chemo, 75 vs 93% after RT); improved OS (HR 0.27). Increased skin toxicity and diarrhea.
***Conclusion: "Cetuximab led to a significant increase in RR and OS in patients with KRAS/BRAF wild-type rectal cancer, but the primary end point of improved CR was not met."
<BR><big>'''Single-arm studies:'''</big>
<p>'''''Capecitabine + Irinotecan:'''''</p>
*'''North Wales''' -- phase II
**110 pts. MRI staged, tumor involving or within 2mm of mesorectal fascia. RT 45 Gy / 25 f. Concurrent oral capecitabine daily, IV irinotecan weekly x 4 weeks.
**'''2011''' {{PMID|21263095}} -- "Preoperative Chemoradiotherapy Using Concurrent Capecitabine and Irinotecan in Magnetic Resonance Imaging-Defined Locally Advanced Rectal Cancer: Impact on Long-Term Clinical Outcomes." (Gollins S, J Clin Oncol. 2011 Mar 10;29(6):1042-1049.)
***pCR 22%. 67% with T-stage downstaging, 80% with N-stage downstaging. Negative circumferential resection margin in 92%. 3-yr LRFS 96.9%, MFS 71.1%, DFS 63.5%, OS 88.2%.
==Clinical stage T3 N0==
*'''Multicenter; 2008''' {{PMID|18202411}} -- "cT3N0 rectal cancer: potential overtreatment with preoperative chemoradiotherapy is warranted." (Guillem JG, J Clin Oncol. 2008 Jan 20;26(3):368-73.)
**Retrospective. 188 pts. Multicenter, international, 6 institutions. Purpose: Analysis of preoperatively staged cT3N0 (by EUS or MRI) pts to look at accuracy of staging lymph nodes. All pts treated with neoadjuvant chemo/RT.
**Rate of pathologically positive lymph nodes after chemo/RT in cT3N0 pts was 22%. The true rate of positive lymph nodes may be higher, due to downstaging by chemo/RT.
**Conclusion: Recommend that preoperative chemo/RT should remain the standard of care for T3N0 patients.
==RT Dose Escalation==
*'''Princess Margaret''', 2006 (1998-2002) - {{PMID|16242252}} — "Preoperative radiation with concurrent chemotherapy for resectable rectal cancer: Effect of dose escalation on pathologic complete response, local recurrence-free survival, disease-free survival, and overall survival." Wiltshire KL et al. Int J Radiat Oncol Biol Phys. 2006 Mar 1;64(3):709-16.
**Review of 3 Phase II studies of preoperative chemo/RT. T2 N1-2 or T3-4 N0-2. The 3 cohorts were treated to 40 Gy/20 fx, 46 Gy/23 fx, or 50 Gy/25 fx. Continuous infusion 5-FU 7 days/wk.
**pCR in 15%, 23%, and 33%. 2-yr LRFS 72%, 90%, 89%. DFS 62%, 84%, 78%. OS 72%, 94%, 92%.
**Conclusion: increase in LRFS, DFS, and OS with doses 46 Gy and higher, but no difference between 46 and 50 Gy.
*'''RTOG 00-12''', 2006 (2001-2003)
**{{PMID|16446336}}, 2006 — "Randomized Phase II Study of Neoadjuvant Combined-Modality Chemoradiation for Distal Rectal Cancer: Radiation Therapy Oncology Group Trial 0012." Mohiuddin M et al. J Clin Oncol, Vol 24, No 4 (February 1), 2006: pp. 650-655.
**Objectives: determine pCR rate of preoperative chemo/RT
**Randomized Phase II. 103 pts. T3 or T4 distal rectum (<9cm from dentate line). Randomized to: 1) CVI 5-FU + HF-RT 55.2 - 60 Gy (1.2 Gy BID), or 2) CVI 5-FU + irinotecan + CF-RT 50.4-54 Gy (1.8 Gy/d).
**Response rate similar between the two arms. pCR 28% (higher than in other studies).
*'''Lyon R96-02''' (1996-2001) -- RT 39/13 or RT 39/13 + boost 85/3
**Randomized. 88 patients. Low rectum tumors, T2-T3Nx, involving <2/3 circumference. Treated with 1) preop RT 39/13 or 2) same RT + endocavitary boost of 85/3
**'''2004''' {{PMID|15197202}} -- "Improved sphincter preservation in low rectal cancer with high-dose preoperative radiotherapy: the lyon R96-02 randomized trial." (Gerard JP, J Clin Oncol. 2004 Jun 15;22(12):2404-9.)
***Response: CR 2% vs. 24% boost; sterilization 34% vs. 57%. Median F/U 2.8 years
***2-year outcome: no difference in morbidity, LR, or OS. Significant benefit for sphincter preservation (76% vs 44%, SS) in boost group
***Conclusion: dose escalation feasible, improved tumor response in early follow-up
==Interval between neoadjuvant RT and surgery==
*'''Lyon R90-01''' (1991-1995) -- 2 week interval vs 6-8 week interval between neoadjuvant RT (39/13) and surgery
**Randomized. 29 French centers. 201 patients with T2-T2Nx. Neoadjuvant RT 39/13, followed by Arm 1) surgery in 2 weeks vs Arm 2) surgery in 6-8 weeks. Sphincter preservation (primary endpoint) per surgeon
**'''17-years''' {{PMID|26723110}} -- "Pathologic Response, When Increased by Longer Interval, Is a Marker but Not the Cause of Good Prognosis in Rectal Cancer: 17-year Follow-up of the Lyon R90-01 Randomized Trial." (Cotte E, Int J Radiat Oncol Biol Phys. 2016 Mar 1;94(3):544-53. doi: 10.1016/j.ijrobp.2015.10.061. Epub 2015 Nov 4.) Median F/U 17 years
***Outcome: ypCR short 10% vs long 26% (SS). LR 14% vs 12% (NS). 5-year OS short 67% vs long 67%, 10-year OS 49% vs 53%, 15-year OS 40% vs 42%, 17-year OS 34% vs 34% (NS). Most recurrences (83%) within first 2 years, 96% within 5 years. Second malignancies 9.4% (4% were prostate/bladder)
***Conclusion: Increasing interval between neoadjuvant RT and surgery did not effect survival, but it did not have a detrimental effect on local control.
*'''Krakow''' (1999 - 2006) -- 1 week interval vs 4 week interval between neoadjuvant RT (25/5) and surgery
**Randomized. 154 patients. Stage I-III (stage II 58%, stage III 25%). Neoadjuvant RT 25/5, followed by Arm 1) surgery 7-10 days vs Arm 2) surgery in 4-5 weeks. Surgery was TME and D3-lymphadenectomy
**'''5-years; 2012''' {{PMID|22170083}} -- "Randomized clinical trial on preoperative radiotherapy 25 Gy in rectal cancer--treatment results at 5-year follow-up." (Pach R, Langenbecks Arch Surg. 2012 Jun;397(5):801-7. doi: 10.1007/s00423-011-0890-8. Epub 2011 Dec 15.)
***Outcome: No difference between type of surgery or sphincter preservation. LR short 1% vs long 7% (NS), all recurrences 14% vs 13% (NS). 5-year OS 63% vs 73% (NS). However, if downstaging after RT, survival 90% vs 60% (SS). Longer time interval resulted in higher downstaging 44% vs 13% (SS) but no effect on sphincter-sparing surgery or R0 resection (NS).
***Conclusion: Longer time interval after neoadjuvant RT does not improve sphincter preservation. Improved 5-year OS seen only in patients with downstaging
==Induction Chemo vs Adjuvant Chemo==
*Neoadjuvant chemo-RT followed by surgery, with either induction chemo strategy or adjuvant chemo strategy
*'''Grupo Cancer De Recto 3, Spain''' (2006-2007) -- Induction chemo vs adjuvant chemo, with chemo-RT -> surgery
**Randomized, Phase II. 108 patients, locally advanced rectal cancer, <12 cm from verge, LAR disease based on high-res MRI. Treated with chemo-RT followed by surgery. Randomized to Arm 1) Induction capecitabine 2000 mg/m2 and oxaliplatin 130 mg/m2 (CAPOX) x4 cycles vs Arm 2) Adjuvant CAPOX x4 cycles. Primary endpoint pCR
**'''2010''' {{PMID|20065174}} -- "Phase II, randomized study of concomitant chemoradiotherapy followed by surgery and adjuvant capecitabine plus oxaliplatin (CAPOX) compared with induction CAPOX followed by concomitant chemoradiotherapy and surgery in magnetic resonance imaging-defined, locally advanced rectal cancer: Grupo cancer de recto 3 study." (Fernandez-Martos C, J Clin Oncol. 2010 Feb 10;28(5):859-65. Epub 2010 Jan 11.)
***Outcome: pCR induction 13% vs adjuvant 14% (NS), no difference in downstaging, tumor regression, R0 resection.
***Toxicity: Higher during adjuvant arm. No difference during chemo-RT.
***Conclusion: No difference in outcomes, but less toxicity with induction chemo compared with adjuvant chemo
*Royal Marsden Hospital (abstract 163 at 2005 Gastrointestinal Cancers Symposium) - Chau I et al. - poor risk pts by MRI
**77 pts. MRI-staged poor risk (tumor within 1 mm of mesorectal fascia, T3 tumors at or below levators, T3c or T3d (??) at any other level, T4 tumors, or any tumor with 4 or more LN +).
**12 weeks neoadjuvant chemotherapy with Xeloda 1000 mg/m2 BID x 14 days q3w and oxaliplatin 130 mg/m2 q3w. At week 13, Xeloda 825 mg/m2 BID concurrent with XRT 45 Gy in 25 fractions + 9 Gy boost. TME planned at 6 weeks after chemo/RT. 12 weeks post-op Xeloda 1250 mg/m2 BID x 14 days q3w.
**88% response rate after chemo. 97% after chemo/RT. At surgery, 79% had primary tumor downstaged. 98% had R0 resection. 24% had pCR and in 42% only microscopic tumor foci. Median f/u 15.9 months.
==Adjuvant Chemotherapy==
*'''Warsaw; 2010''' {{PMID|20231300}} -- "Does adjuvant fluoropyrimidine-based chemotherapy provide a benefit for patients with resected rectal cancer who have already received neoadjuvant radiochemotherapy? A systematic review of randomised trials." (Bujko K, Ann Oncol. 2010 Mar 15. [Epub ahead of print])
**Systematic review. 4 trials
**Outcome: No statistically significant benefit in patients undergoing preoperative radio(chemo) therapy for adjuvant chemo found
**Conclusion: New trials should be launched
==Organ Preservation==
*'''OPRA (Organ Preservation in Patients with Rectal Adenocarcinoma)''' Phase II trial - randomized to 1) FOLFOX then chemoradiation, or 2) chemoradiation then FOLFOX; then both groups got either TME or watch-and-wait based on tumor response
**Randomized 324 patients, Stage II or III rectal adenocarcinoma, multi-center, USA
**'''2022''' {{PMID|35483010}} -- "Organ preservation in patients with rectal adenocarcinoma treated with total neoadjuvant therapy," (Garcia-Aguilar J, J Clin Oncol 2022)
***Outcomes: 3-yr DFS 76% for both arms, 3-yr TME-free survival chemo-first 46%, ChRT 53%. DFS similar for TME at restaging or TME at recurrence.
***Conclusion: "Organ preservation is achievable in half of patients with rectal cancer treated with total neoadjuvant therapy..."
==Prognostic Factors==
*'''Meta-analysis; 2008''' {{PMID|18182672}} -- "What is the role for the circumferential margin in the modern treatment of rectal cancer?" (Nagtegaal ID, J Clin Oncol. 2008 Jan 10;26(2):303-12.)
**17,500 patients; importance of CRM. CRM predictor for local recurrence, distant mets, and overall survival
**Conclusion: CRM involvement is one of key factors in rectal cancer treatment
*'''Mt. Vernon, 2005''' (UK) {{PMID|16199310}} -- "Can histopathologic assessment of circumferential margin after preoperative pelvic chemoradiotherapy for T3-T4 rectal cancer predict for 3-year disease-free survival?" (Mawdsley S, Int J Radiat Oncol Biol Phys. 2005 Nov 1;63(3):745-52.)
**Retrospective. 150 patients, treated with neoadjuvant CRT (5-FU/folinic acid), 6-12 weeks later excision. Median follow-up 25 months
**Of 150, 122 patients (81%) curative resection, 98 patients (65%) negative margins R0.
**Local recurrence: R0 10% vs. R1-R2 62%; DM: R0 29% vs. R1-R2 75%; DFS: R0 52% vs. R1-R2 9%
**3-year OS: R0 64% vs. R1-R2 25%
**<u>Conclusion</u>: "After 5-fluorouracil-based CRT, a positive CRM (margin) predicted for a high risk of subsequent local recurrence and a 3-year disease-free survival rate of only 9%."
==Side Effects==
*'''Swedish Rectal Cancer Trial'''
**'''1998''' {{PMID|9593234}} -- "Preoperative irradiation affects functional results after surgery for rectal cancer: results from a randomized study." (Dahlberg M, Dis Colon Rectum. 1998 May;41(5):543-9; discussion 549-51.)
***Patient questionnaire. 171/220 patients alive >5 years.
***Median BM frequency: RT 20/week vs. surgery alone 10/week (SS)
***Fecal incontinence: RT 62% vs. surgery alone 27% (SS)
***Impaired social life: RT 30% vs. surgery alone 10% (SS)
***Conclusion: High dose preop RT influences long-term bowel function
*'''Stockholm Trials'''
**'''2006''' {{PMID|16532369}} -- "Long-term effect of preoperative radiation therapy on anorectal function." (Pollack J, Dis Colon Rectum. 2006 Mar;49(3):345-52.)
***Patient questionnaire. 64 patients (21 preop RT, 43 surgery alone). Mean F/U 14 years
***Median BM frequency: RT 20/week vs. surgery alone 10/week (SS)
***Fecal incontinence: RT 57% vs. surgery alone 26% (SS). Significantly worse resting and squeeze pressures
***No difference in QOL between RT and surgery alone, but significantly worse for incontinent patients
***Conclusion: short-term RT including anal sphincters impairs permanently anorectal function
*'''German Rectal Cancer Study''' CAO/ARO/AIO (1995-2002) -- preop chemo-RT vs. postop chemo-RT
**{{PMID|15496622}} [http://content.nejm.org/cgi/content/full/351/17/1731 Full text], 2004 - "Preoperative versus postoperative chemoradiotherapy for rectal cancer." Sauer R et al. N Engl J Med. 2004 Oct 21;351(17):1731-40.
***823 pts. clinical stage T3-4 or N+. Randomized to 1) ''post-op regimen:'' surgery (TME) -> chemo/RT (55.8 Gy) -> 5 cycles bolus 5-FU, or 2) ''pre-op regimen:'' chemo/RT (50.4 Gy) -> surgery (TME) -> 4 cycles bolus 5-FU. In both arms, chemo was CVI 5-FU (1000 mg/m2/d) on days 1-5, weeks 1+5.
***Sphincter-preserving surgery performed: 39% in pre-op arm, 19% in post-op arm
***Grade 3-4 acute toxicity in 27% of pre-op arm, 40% of post-op arm (p=0.001)
***Grade 3-4 long-term toxicity in 14% of pre-op arm, 24% of post-op arm (p=0.01)
==Summary of results==
{| class="wikitable"
!Study !! pCR !! sphincter sparing !! LR !! DM !! DFS || OS
|-
!'''''No adjuvant treatment:'''''
!colspan=6 |
|-
|align=right|'''MRC 3'''
|n/a || - || 34% || - || - || 46% 5-yr
|-
!align=right|'''''Pre-op RT alone:'''''
!colspan=6 |
|-
!align=right|'''''Pre-op Chemo/RT:'''''
!colspan=6 |
|-
!align=right|'''''Adjuvant Chemo:'''''
!colspan=6 |
|-
|align=right|'''NSABP R-02'''
|n/a || - || 13% || - || - || -
|-
!align=right|'''''Adjuvant RT:'''''
!colspan=6 |
|-
|align=right|'''MRC 3'''
|n/a || - || 21% || - || - || 52% 5-yr
|-
!align=right|'''''Adjuvant Chemo/RT:'''''
!colspan=6 |
|-
|align=right|'''NSABP R-02'''
|n/a || - || 8% || - || - || -
|}
c1n17qz331056gd0ozq8uhg9ggcb46j
Template:Haskell/Minitoc
10
98715
4675889
4658478
2026-10-13T18:12:29Z
Luciérnaga de conocimiento
3401314
4675889
wikitext
text/x-wiki
<div class="noprint">
{| cellpadding="1" style="float: {{{side|right}}}; clear: {{{side|right}}}; border: 1px solid #8888aa; background: #f7f8ff;{{Text default color}}; padding: 5px; font-size: 95%; margin: 0 15px 0 15px;"
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{SUBPAGENAME}}''' {{#ifeq:{{{noexercises}}}|1||([[../Solutions/{{SUBPAGENAME}}|Solutions]])}}
|-
||__TOC__
|-
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}'''
|-
||
{{Haskell/{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}}}
|}
</div><noinclude>
{{BookCat}}</noinclude>
59x9ww05c6qywmuvr8920njitjo8a44
4675891
4675889
2026-10-13T18:18:35Z
Luciérnaga de conocimiento
3401314
4675891
wikitext
text/x-wiki
<div class="noprint">
{| cellpadding="1" style="float: {{{side|right}}}; clear: {{{side|right}}}; border: 1px solid #8888aa; background: #f7f8ff;{{Text default color}}; padding: 5px; font-size: 95%; margin: 0 15px 0 15px;"
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{SUBPAGENAME}}''' {{#ifeq:{{{noexercises}}}|1||([[../Solutions/{{SUBPAGENAME}}|Solutions]])}}
|-
||__TOC__
|-
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}'''
|-
||
{{Haskell/{{:{{PAGENAME}}/Chapter}}}}}
|}
</div><noinclude>
{{BookCat}}</noinclude>
ki1t5hy19q3o8gz09wacew8s272u5tt
4675892
4675891
2026-10-13T18:19:00Z
Luciérnaga de conocimiento
3401314
4675892
wikitext
text/x-wiki
<div class="noprint">
{| cellpadding="1" style="float: {{{side|right}}}; clear: {{{side|right}}}; border: 1px solid #8888aa; background: #f7f8ff;{{Text default color}}; padding: 5px; font-size: 95%; margin: 0 15px 0 15px;"
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{SUBPAGENAME}}''' {{#ifeq:{{{noexercises}}}|1||([[../Solutions/{{SUBPAGENAME}}|Solutions]])}}
|-
||__TOC__
|-
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{{chapter|{{:{{PAGENAME}}}}}}}'''
|-
||
{{Haskell/{{:{{PAGENAME}}/Chapter}}}}}
|}
</div><noinclude>
{{BookCat}}</noinclude>
1lvv98lcl4u7viwobon8j0kkbrkfat0
4675893
4675892
2026-10-13T18:19:28Z
Luciérnaga de conocimiento
3401314
4675893
wikitext
text/x-wiki
<div class="noprint">
{| cellpadding="1" style="float: {{{side|right}}}; clear: {{{side|right}}}; border: 1px solid #8888aa; background: #f7f8ff;{{Text default color}}; padding: 5px; font-size: 95%; margin: 0 15px 0 15px;"
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{SUBPAGENAME}}''' {{#ifeq:{{{noexercises}}}|1||([[../Solutions/{{SUBPAGENAME}}|Solutions]])}}
|-
||__TOC__
|-
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{{chapter|{{:{{PAGENAME}}}}}}}'''
|-
||
{{Haskell/{{:{{PAGENAME}}}}}}}
|}
</div><noinclude>
{{BookCat}}</noinclude>
n80evhq6f85b9e1h4vzl14mdv22li2y
4675894
4675893
2026-10-13T18:19:57Z
Luciérnaga de conocimiento
3401314
4675894
wikitext
text/x-wiki
<div class="noprint">
{| cellpadding="1" style="float: {{{side|right}}}; clear: {{{side|right}}}; border: 1px solid #8888aa; background: #f7f8ff;{{Text default color}}; padding: 5px; font-size: 95%; margin: 0 15px 0 15px;"
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{SUBPAGENAME}}''' {{#ifeq:{{{noexercises}}}|1||([[../Solutions/{{SUBPAGENAME}}|Solutions]])}}
|-
||__TOC__
|-
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}'''
|-
||
{{Haskell chapter/{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}}}
|}
</div><noinclude>
{{BookCat}}</noinclude>
2al02kt4w1pl7d7ify8vzq6uagw5pn2
4675895
4675894
2026-10-13T18:22:16Z
Luciérnaga de conocimiento
3401314
4675895
wikitext
text/x-wiki
<div class="noprint">
{| cellpadding="1" style="float: {{{side|right}}}; clear: {{{side|right}}}; border: 1px solid #8888aa; background: #f7f8ff;{{Text default color}}; padding: 5px; font-size: 95%; margin: 0 15px 0 15px;"
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{SUBPAGENAME}}''' {{#ifeq:{{{noexercises}}}|1||([[../Solutions/{{SUBPAGENAME}}|Solutions]])}}
|-
||__TOC__
|-
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}'''
|-
||
{{Haskell/{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}}}
|}
</div><noinclude>
{{BookCat}}</noinclude>
59x9ww05c6qywmuvr8920njitjo8a44
4675899
4675895
2026-10-13T18:40:13Z
Luciérnaga de conocimiento
3401314
4675899
wikitext
text/x-wiki
<div class="noprint">
{| cellpadding="1" style="float: {{{side|right}}}; clear: {{{side|right}}}; border: 1px solid #8888aa; background: #f7f8ff;{{Text default color}}; padding: 5px; font-size: 95%; margin: 0 15px 0 15px;"
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{SUBPAGENAME}}''' {{#ifeq:{{{noexercises|}}}|1||([[../Solutions/{{SUBPAGENAME}}|Solutions]])}}
|-
||__TOC__
|-
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}'''
|-
||
{{Haskell/{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}}}
|}
</div><noinclude>
{{BookCat}}</noinclude>
nsawv3bfy3puyb683o3tsalcssro8ot
Template:Haskell/Navigation
10
98719
4675905
4658486
2026-10-13T19:01:11Z
Luciérnaga de conocimiento
3401314
4675905
wikitext
text/x-wiki
<div class="noprint">
{{center/top}}
{| cellpadding="1" style="border: 1px solid #8888aa; background: #f7f8ff;{{Text default color}}; padding: 5px; font-size: 95%; margin: 0 15px 0 15px;"
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{SUBPAGENAME}}'''
|-
| style="text-align:center" |{{#ifeq:{{{noexercises}}}|1||[[../Solutions/{{SUBPAGENAME}}|Solutions to exercises]]}}
|-
| style="background: #ccf;{{Text default color}}; text-align: center;" | '''{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}'''
|-
| style="text-align:center" |
{{Haskell/{{{chapter|{{:{{PAGENAME}}/Chapter}}}}}|sep= >> |subsep= >> }}<br>
|-
|style="background: #ccf;{{Text default color}}; text-align: center;" | '''[[Haskell]]'''
|-
| style="text-align:center" |
[[Haskell/Haskell Basics|Haskell Basics]]
>> [[Haskell/Elementary Haskell|Elementary Haskell]]
>> [[Haskell/Intermediate Haskell|Intermediate Haskell]]
>> [[Haskell/Monads|Monads]]<br>
[[Haskell/Advanced Haskell|Advanced Haskell]]
>> [[Haskell/Fun with Types|Fun with Types]]
>> [[Haskell/Wider Theory|Wider Theory]]
>> [[Haskell/Haskell Performance|Haskell Performance]]<br>
----
[[Haskell/Libraries Reference|Libraries Reference]]
>> [[Haskell/General Practices|General Practices]]
>> [[Haskell/Specialised Tasks|Specialised Tasks]]
<div style="float:right;" class="noprint"><small>[{{fullurl:Template:Haskell/Navigation|action=edit}} edit book structure]</small></div>
|}
{{center/end}}
</div>
{{BookCat}}
m4oh2t91u7gfwfsu5euxm9982dd1tu3
Template:Haskell/Elementary Haskell
10
98765
4675937
3292305
2026-10-14T00:00:24Z
~2026-54868-50
3628373
4675937
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/Recursion|Recursion]]
{{{sep|<br>}}}[[Haskell/Lists II|Lists II (map)]]
{{{sep|<br>}}}[[Haskell/Lists III|Lists III (folds, comprehensions)]]
{{{sep|<br>}}}[[Haskell/Type declarations|Type declarations]]
{{{sep|<br>}}}[[Haskell/Pattern matching|Pattern matching]]
{{{sep|<br>}}}[[Haskell/Control structures|Control structures]]
{{{sep|<br>}}}[[Haskell/More on functions|More on functions]]
{{{sep|<br>}}}[[Haskell/Higher-order functions|Higher-order functions]]
{{{sep|<br>}}}[[Haskell/Using GHCi effectively|Using GHCi effectively]]
{{Haskell/Chapter navbar|Elementary Haskell}}<noinclude>{{BookCat}}</noinclude>
t3412ottrp5q6ed8metkxo148715rmp
Template:Haskell/Intermediate Haskell
10
98771
4675938
3292347
2026-10-14T00:01:36Z
~2026-54868-50
3628373
4675938
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/Modules|Modules]]
{{{sep|<br>}}}[[Haskell/Standalone programs|Standalone programs]]
{{{sep|<br>}}}[[Haskell/Indentation|Indentation]]
{{{sep|<br>}}}[[Haskell/More on datatypes|More on datatypes]]
{{{sep|<br>}}}[[Haskell/Other data structures|Other data structures]]
{{{sep|<br>}}}[[Haskell/Classes and types|Classes and types]]
{{{sep|<br>}}}[[Haskell/The Functor class|The Functor class]]
{{Haskell/Chapter navbar|Intermediate Haskell}}<noinclude>{{BookCat}}</noinclude>
rt7nszs23k4w74pm7gyi4e6pfv0kpl5
Template:Haskell/Monads
10
98799
4675939
3292356
2026-10-14T00:01:55Z
~2026-54868-50
3628373
4675939
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/Prologue: IO, an applicative functor|Prologue: IO, an applicative functor]]
{{{sep|<br>}}}[[Haskell/Understanding monads|Understanding monads]]
{{{breaksep|{{{subsep|<br>}}}}}}[[Haskell/Understanding monads/Maybe|Maybe]]{{{subsep|<br>}}}[[Haskell/Understanding monads/List|List]]
{{{breaksep|{{{subsep|<br>}}}}}}[[Haskell/do notation|<code>do</code> notation]]
{{{breaksep|{{{subsep|<br>}}}}}}[[Haskell/Understanding monads/IO|IO]]{{{subsep|<br>}}}[[Haskell/Understanding monads/State|State]]
{{{sep|<br>}}}[[Haskell/Alternative and MonadPlus|Alternative and MonadPlus]]
{{{sep|<br>}}}[[Haskell/Monad transformers|Monad transformers]]
{{Haskell/Chapter navbar|Monads}}<noinclude>{{BookCat}}</noinclude>
dehrd6a7sxfawklzzi50g9r66ibwd4w
Template:Haskell/Advanced Haskell
10
98802
4675943
3448594
2026-10-14T00:25:13Z
~2026-54868-50
3628373
4675943
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/Monoids|Monoids]]
{{{sep|<br>}}}[[Haskell/Applicative functors|Applicative functors]]
{{{sep|<br>}}}[[Haskell/Foldable|Foldable]]
{{{sep|<br>}}}[[Haskell/Traversable|Traversable]]
{{{sep|<br>}}}[[Haskell/Arrow tutorial|Arrow tutorial]]
{{{sep|<br>}}}[[Haskell/Understanding arrows|Understanding arrows]] {{stage|75%}}
{{{sep|<br>}}}[[Haskell/Continuation passing style|Continuation passing style]]
{{{sep|<br>}}}[[Haskell/Zippers|Zippers]] {{stage|75%}}
{{{sep|<br>}}}[[Haskell/Lenses and functional references|Lenses]]
{{{sep|<br>}}}[[Haskell/Comonads|Comonads]] {{stage|0%}}
{{{sep|<br>}}}[[Haskell/MonadFix|Value recursion (MonadFix)]]
{{{sep|<br>}}}[[Haskell/Effectful streaming|Effectful streaming]]
{{{sep|<br>}}}[[Haskell/Mutable objects|Mutable objects]] {{stage|50%}}
{{{sep|<br>}}}[[Haskell/Concurrency|Concurrency]] {{stage|0%}}
{{{sep|<br>}}}[[Haskell/Template Haskell|Template Haskell]] {{stage|0%}}
{{{sep|<br>}}}[[Haskell/Type Families|Type Families]] {{stage|0%}}
{{Haskell/Chapter navbar|Advanced Haskell}}<noinclude>{{BookCat}}</noinclude>
9rforkbxulbco544sauym5878zenqil
Template:Haskell/Fun with Types
10
98803
4675944
3597514
2026-10-14T00:26:25Z
~2026-54868-50
3628373
4675944
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/Polymorphism|Polymorphism]] {{stage|25%}}
{{{sep|<br>}}}[[Haskell/Existentially quantified types|Existentially quantified types]] {{stage|50%}}
{{{sep|<br>}}}[[Haskell/Advanced type classes|Advanced type classes]] {{stage|50%}}
{{{sep|<br>}}}[[Haskell/Phantom types|Phantom types]] {{stage|25%}}
{{{sep|<br>}}}[[Haskell/GADT|Generalised algebraic data-types (GADT)]] {{stage|75%}}
{{{sep|<br>}}}[[Haskell/Datatype algebra|Datatype algebra]]
{{{sep|<br>}}}[[Haskell/Kinds|Type constructors & Kinds]] {{stage|0%}}
{{Haskell/Chapter navbar|Fun with Types}}<noinclude>{{BookCat}}</noinclude>
3nug5f7rsq1o98afj0tjvc51zssmbsm
Radiation Oncology/Radiobiology/Linear-Quadratic
0
101168
4675982
3305331
2026-10-14T06:03:46Z
Jcb
90773
4675982
wikitext
text/x-wiki
{{Radiation Oncology:TOC}}
<big>'''Linear-Quadratic Formalism'''</big>
==Linear-quadratic model==
*A model which describes cell killing, both for tumor control and for normal tissue complications
*Most common underlying biological rationale is that radiation produces a [[Radiation_Oncology/Radiobiology/DNA_Damage|double strand DNA break]] (DSB) using a single radiation track
*Individual DSB can be repaired, with first order kinetics and half-life T<sub>1/2</sub>
*If more than one unrepaired DSB is present in the cell at the same time (arising from two separate radiation tracks), a misjoining can produce a lethal lesion (e.g. dicentrics)
*The two separate DSB can happen at different times during treatment, allowing for repair of first DSB prior to misjoining with the second DSB
*A single radiation track can also give rise to a lethal lesion by itself (e.g. point mutation in vital gene, deletion eliminating vital gene, induced apoptosis, etc)
*In the LQ formalism, the yield of lethal lesions is the sum of lethal lesions produced from a single radiation track (which are linearly related to dose, αD) and lethal lesions produced from two radiation tracks (which are quadratically related to dose, βD<sup>2</sup>)
**Y = αD + βD<sup>2</sup>
*Because the two separate DSB can be repaired prior to resulting in a lethal event, the second component is modified by the Lea-Catcheside time factor (G) to show dependence on dose protraction. For single fractions, G=1
**Y = αD + GβD<sup>2</sup>
*Lethal lesions are thought to follow Poisson distribution from cell to cell. Therefore, the surviving fraction (SF) is
**SF = exp -(Y)
*This leads to the standardized LQ equation
**SF = exp -(αD + GβD<sup>2</sup>)
==Protracted Radiation==
<math>SF = \exp -(\alpha D + \beta D^2)</math>
:''SF'' = surviving fraction
*First proposed by Douglas and Fowler in 1972 ({{PMID|1265229}} - Douglas BG and Fowler JF. The effect of multiple small doses of X-rays on skin reactions in the mouse and a basic interpretation. Radiat Res 66, 401-26, 1976.)
E = -ln SF
:''E'' = biological radiation effect
<math>ETD = E/\alpha = D[1 + D(\beta/\alpha)] = D \times RE</math>
:''ETD'' = extrapolated tolerance dose
:''D'' = total dose (Gy)
:''RE'' = relative effectiveness per unit dose
For fractionated treatments:
<br><math>RE = 1 + dn(\beta/\alpha)</math>
:''d'' = dose per fraction (Gy)
:''n'' = the number of total fraction
For protracted irradiation (constant dose rate):
<br><math>RE = 1 + (2R/\mu)(\beta/\alpha)\left\{1 - (1/\mu)T\left[ 1 - \exp(-\mu T)\right]\right\}</math>
:''R'' = dose rate, LDR (Gy/hr)
:<math>\mu</math> = sublethal damage repair exponential time constant (1/hr).
::<math>\mbox{also, } \mu = \frac{\ln 2}{T_{\tfrac{1}{2}}} \mbox{, where } T_{\tfrac{1}{2}} \mbox{ is the half life of sublethal damage repair}</math>
:''T'' = treatment time (hr)
is approximately the same as,
:<math>RE = 1 + (2R/\mu)(\beta/\alpha)\left\{1 - (1/\mu)T\right\}</math>,
:for values of T: 10 hr > T > 100 hr.
*'''Glasgow; 1998''' {{PMID|9572622}} -- "The linear-quadratic transformation of dose-volume histograms in fractionated radiotherapy." (Wheldon TE, Radiother Oncol. 1998 Mar;46(3):285-95.)
**Radiobiological transformation of physical DVH to incorporate fraction size effects
**Outcome: "hot spots" and "cold spots" are further from mean than physical distributions indicate; particularly important in plans with significant dose heterogeneity
**Conclusion: LQ-DVH should be computed in parallel with conventional DVHs
==LQ and High Fractional Dose==
*'''Duke; 2008''' {{PMID|18725110}} -- "The linear-quadratic model is inappropriate to model high dose per fraction effects in radiosurgery." (Kirkpatrick JP, Semin Radiat Oncol. 2008 Oct;18(4):240-3.)
**Counterpoint argument to {{PMID|18725109}}.
**LQ model does not reflect vascular and stromal damage produced at high doses per fraction, it also ignores impact of radioresistant subpopulations of cells such as cancer stem cells
*'''Columbia; 2008''' {{PMID|18725109}} -- "The linear-quadratic model is an appropriate methodology for determining isoeffective doses at large doses per fraction." (Brenner DJ, Semin Radiat Oncol. 2008 Oct;18(4):234-9.)
**Point argument to {{PMID|18725110}}
**Linear quadratic model is reasonably well validated for doses up to 10 Gy/fraction, and could be reasonably used to about 18 Gy/fraction
==Extended LQ Models==
*'''Ohio State; 2010''' {{PMID|20610850}} -- "A generalized linear-quadratic model for radiosurgery, stereotactic body radiation therapy, and high-dose rate brachytherapy." (Wang JZ, Sci Transl Med. 2010 Jul 7;2(39):39ra48.)
**Generalized LQ model (gLQ) developed. Compared to in vitro data. Able to extrapolate up to 11-13 Gy from low dose data
*'''UT Southwestern; 2008''' {{PMID|18262098}} -- "Universal survival curve and single fraction equivalent dose: useful tools in understanding potency of ablative radiotherapy." (Park C, Int J Radiat Oncol Biol Phys. 2008 Mar 1;70(3):847-52.)
**Hybridization of two classic radiobiologic models: LQ model and multi-target model. LQ model good for conventionally fractionated therapy; multi-target model good for high (ablative) fractional doses seen in SBRT
**Allows for easier conversion of doses
==References==
*{{PMID|8631555}} - Liu WS et al. Determination of the appropriate fraction number and size of the HDR brachytherapy for cervical cancer.Gynecol Oncol. 1996 Feb;60(2):295-300.
17fgm9n508bey3db61vph6wbtwpq0r2
Template:Haskell/Haskell Performance
10
101780
4675945
3292340
2026-10-14T00:26:41Z
~2026-54868-50
3628373
4675945
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/Performance introduction|Introduction]] {{stage|50%}}
{{{sep|<br>}}}[[Haskell/Performance examples|Step by step examples]] {{stage|00%}}
{{{sep|<br>}}}[[Haskell/Graph reduction|Graph reduction]] {{stage|25%}}
{{{sep|<br>}}}[[Haskell/Laziness|Laziness]] {{stage|50%}}
{{{sep|<br>}}}[[Haskell/Time and space profiling|Time and space profiling]] {{stage|00%}}
{{{sep|<br>}}}[[Haskell/Strictness|Strictness]] {{stage|00%}}
{{{sep|<br>}}}[[Haskell/Algorithm complexity|Algorithm complexity]] {{stage|25%}}
{{{sep|<br>}}}[[Haskell/Data structures|Data structures]]
{{{sep|<br>}}}[[Haskell/Parallelism|Parallelism]]
{{Haskell/Chapter navbar|Haskell Performance}}<noinclude>{{BookCat}}</noinclude>
33nwpifjq8tjptve4cf2g8a3dpouuw1
Algorithm Implementation/Strings/Levenshtein distance
0
103231
4675992
4674649
2026-10-14T09:05:54Z
~2026-55159-62
3628391
Update outdated PHP 255-byte limit (removed in PHP 8.0), improve the Wagner–Fischer example with O(min(m,n)) auxiliary space, add verified test cases and clarify UTF-8 byte-level comparison.
4675992
wikitext
text/x-wiki
{{wikipedia|Levenshtein distance}}
The implementations of the Levenshtein algorithm on this page are illustrative only. Applications will, in most cases, use implementations which use heap allocations sparingly, in particular when large lists of words are compared to each other. The following remarks indicate some of the variations on this and related topics:
* Most implementations use one- or two-dimensional arrays to store the distances of prefixes of the words compared. In most applications the size of these structures is previously known. This is the case, when, for instance the distance is relevant only if it is below a certain maximally allowed distance (this happens when words are selected from a dictionary to approximately match a given word). In this case the arrays can be preallocated and reused over the various runs of the algorithm over successive words.
* Using a maximum allowed distance puts an upper bound on the search time. The search can be stopped as soon as the minimum Levenshtein distance between prefixes of the strings exceeds the maximum allowed distance.
* Deletion, insertion, and replacement of characters can be assigned different weights. The usual choice is to set all three weights to 1. Different values for these weights allows for more flexible search strategies in lists of words.
==Unicode considerations==
When Levenshtein distance is applied to Unicode text, an implementation should define what one element of the compared sequence represents. Depending on the programming language and string representation, an implementation may operate on bytes, encoding code units, Unicode code points, or user-perceived characters.
This distinction can change the resulting distance. A single visible character may be represented by more than one Unicode code point, and canonically equivalent strings may have different underlying code-point sequences.
For example, an accented character may be represented as a single precomposed code point or as a base character followed by a combining mark. If the raw sequences are compared directly, a Levenshtein implementation can count a representational difference even when the two strings are visually equivalent.
===Normalization===
For applications in which canonically equivalent Unicode strings should compare as the same text, the inputs can be normalized to the same Unicode normalization form before calculating the distance.
A typical processing sequence is:
input text
→ Unicode normalization
→ sequence segmentation
→ Levenshtein distance
Normalization does not change the Levenshtein recurrence itself. It changes the input sequence supplied to the algorithm.
===Code points and grapheme clusters===
A Unicode code point is not necessarily the same as a character perceived by a user. Combining marks, emoji sequences, and some writing systems can represent one visible character using several code points.
An implementation that iterates over Unicode code points is therefore more Unicode-aware than a byte-based implementation, but it can still produce a different result from an implementation operating on extended grapheme clusters.
If one visible character is intended to count as one edit operation, the text can first be segmented into extended grapheme clusters and those clusters can then be used as the sequence elements processed by the Levenshtein algorithm.
Conceptually:
raw Unicode text
→ normalization
→ grapheme segmentation
→ sequence of grapheme clusters
→ Levenshtein distance
===Unicode text transformations===
Unicode text transformations can affect edit distance because they change the sequence being compared.
Examples include normalization, transliteration, case conversion, width conversion, insertion of combining marks, and substitution with visually styled Unicode characters.
Consequently, the distance between two original strings and the distance between transformed versions of those strings are not necessarily equal.
The transformation and the distance calculation are separate operations: a transformation produces a new sequence, while Levenshtein distance measures the edit relationship between the sequences that are actually supplied to the algorithm.
==Action Script 3==
<syntaxhighlight lang="actionscript3">
function levenshtein(s1:String, s2:String):uint
{
const len1:uint = s1.length, len2:uint = s2.length;
var d:Vector.<Vector.<uint> >=new Vector.<Vector.<uint> >(len1+1);
for(i=0; i<=len1; ++i)
d[i] = new Vector.<uint>(len2+1);
d[0][0]=0;
var i:int;
var j:int;
for(i=1; i<=len1; ++i) d[i][0]=i; //int faster than uint
for(j=1; j<=len2; ++j) d[0][j]=j;
for(i = 1; i <= len1; ++i)
for(j = 1; j <= len2; ++j)
d[i][j] = Math.min( Math.min(d[i - 1][j] + 1,d[i][j - 1] + 1),
d[i - 1][j - 1] + (s1.charAt(i - 1) == s2.charAt(j - 1) ? 0 : 1) );
return(d[len1][len2]);
}
</syntaxhighlight>
==Ada==
<syntaxhighlight lang="ada">
function Levenshtein(Left, Right : String) return Natural is
D : array(0 .. Left'Last, 0 .. Right'Last) of Natural;
begin
for I in D'range(1) loop D(I, 0) := I;end loop;
for J in D'range(2) loop D(0, J) := J;end loop;
for I in Left'range loop
for J in Right'range loop
D(I, J) := Natural'Min(D(I - 1, J), D(I, J - 1)) + 1;
D(I, J) := Natural'Min(D(I, J), D(I - 1, J - 1) + Boolean'Pos(Left(I) /= Right(J)));
end loop;
end loop;
return D(D'Last(1), D'Last(2));
end Levenshtein;
</syntaxhighlight>
==AWK==
<syntaxhighlight lang="awk">
function levenshtein(str1, str2, cost_ins, cost_rep, cost_del, str1_len, str2_len, matrix, is_match, i, j, x, y, z) {
if(cost_ins == "") cost_ins = 1
if(cost_rep == "") cost_rep = 1
if(cost_del == "") cost_del = 1
str1_len = length(str1)
str2_len = length(str2)
if(str1_len == 0) return str2_len * cost_ins
if(str2_len == 0) return str1_len * cost_del
matrix[0, 0] = 0
for(i = 1; i <= str1_len; i++) {
matrix[i, 0] = i * cost_del
for(j = 1; j <= str2_len; j++) {
matrix[0, j] = j * cost_ins
x = matrix[i - 1, j] + cost_del
y = matrix[i, j - 1] + cost_ins
z = matrix[i - 1, j - 1] + (substr(str1, i, 1) == substr(str2, j, 1) ? 0 : cost_rep)
x = x < y ? x : y
matrix[i, j] = x < z ? x : z
}
}
return matrix[str1_len, str2_len]
}
</syntaxhighlight>
==Bash==
<syntaxhighlight lang="bash">
#!/bin/bash
function levenshtein {
if (( $# != 2 )); then
echo "Usage: $0 word1 word2" >&2
elif (( ${#1} < ${#2} )); then
levenshtein "$2" "$1"
else
local str1len=${#1}
local str2len=${#2}
local d
for (( i = 0; i <= (str1len+1)*(str2len+1); i++ )); do
d[i]=0
done
for (( i = 0; i <= str1len; i++ )); do
d[i+0*str1len]=$i
done
for (( j = 0; j <= str2len; j++ )); do
d[0+j*(str1len+1)]=$j
done
for (( j = 1; j <= str2len; j++ )); do
for (( i = 1; i <= str1len; i++ )); do
[ "${1:i-1:1}" = "${2:j-1:1}" ] && local cost=0 || local cost=1
del=$(( d[(i-1)+str1len*j]+1 ))
ins=$(( d[i+str1len*(j-1)]+1 ))
alt=$(( d[(i-1)+str1len*(j-1)]+cost ))
d[i+str1len*j]=$( echo -e "$del\n$ins\n$alt" | sort -n | head -1 )
done
done
echo ${d[str1len+str1len*(str2len)]}
fi
}
</syntaxhighlight>
== Common Lisp ==
<syntaxhighlight lang="lisp">
(defun levenshtein-distance (str1 str2)
"Calculates the Levenshtein distance between str1 and str2, returns an editing distance (int)."
(let ((n (length str1))
(m (length str2)))
;; Check trivial cases
(cond ((= 0 n) (return-from levenshtein-distance m))
((= 0 m) (return-from levenshtein-distance n)))
(let ((col (make-array (1+ m) :element-type 'integer))
(prev-col (make-array (1+ m) :element-type 'integer)))
;; We need to store only two columns---the current one that
;; is being built and the previous one
(dotimes (i (1+ m))
(setf (svref prev-col i) i))
;; Loop across all chars of each string
(dotimes (i n)
(setf (svref col 0) (1+ i))
(dotimes (j m)
(setf (svref col (1+ j))
(min (1+ (svref col j))
(1+ (svref prev-col (1+ j)))
(+ (svref prev-col j)
(if (char-equal (schar str1 i) (schar str2 j)) 0 1)))))
(rotatef col prev-col))
(svref prev-col m))))
</syntaxhighlight>
==C==
<syntaxhighlight lang="c">
int min(int a, int b, int c)
{
if(a <= b && a <= c)
{
return a;
}
else if(b <= a && b <= c)
{
return b;
}
else if(c <= a && c <= b)
{
return c;
}
}
int levenshtein(char *s1, char *s2) {
unsigned int x, y, s1len, s2len;
s1len = strlen(s1);
s2len = strlen(s2);
unsigned int matrix[s2len+1][s1len+1];
matrix[0][0] = 0;
for (x = 1; x <= s2len; x++)
matrix[x][0] = matrix[x-1][0] + 1;
for (y = 1; y <= s1len; y++)
matrix[0][y] = matrix[0][y-1] + 1;
for (x = 1; x <= s2len; x++)
for (y = 1; y <= s1len; y++)
matrix[x][y] = min(matrix[x-1][y] + 1, matrix[x][y-1] + 1, matrix[x-1][y-1] + (s1[y-1] == s2[x-1] ? 0 : 1));
return(matrix[s2len][s1len]);
}
</syntaxhighlight>
The above can be optimized to use O(min(m,n)) space instead of O(mn). The key observation is that we only need to access the contents of the previous column when filling the matrix column-by-column. Hence, we can re-use a single column over and over, overwriting its contents as we proceed.
<syntaxhighlight lang="C">
#define MIN3(a, b, c) ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c)))
int levenshtein(char *s1, char *s2) {
unsigned int s1len, s2len, x, y, lastdiag, olddiag;
s1len = strlen(s1);
s2len = strlen(s2);
unsigned int column[s1len + 1];
for (y = 1; y <= s1len; y++)
column[y] = y;
for (x = 1; x <= s2len; x++) {
column[0] = x;
for (y = 1, lastdiag = x - 1; y <= s1len; y++) {
olddiag = column[y];
column[y] = MIN3(column[y] + 1, column[y - 1] + 1, lastdiag + (s1[y-1] == s2[x - 1] ? 0 : 1));
lastdiag = olddiag;
}
}
return column[s1len];
}
</syntaxhighlight>
==C++==
<syntaxhighlight lang="cpp">
unsigned int edit_distance(const std::string& s1, const std::string& s2)
{
const std::size_t len1 = s1.size(), len2 = s2.size();
std::vector<std::vector<unsigned int>> d(len1 + 1, std::vector<unsigned int>(len2 + 1));
d[0][0] = 0;
for(unsigned int i = 1; i <= len1; ++i) d[i][0] = i;
for(unsigned int i = 1; i <= len2; ++i) d[0][i] = i;
for(unsigned int i = 1; i <= len1; ++i)
for(unsigned int j = 1; j <= len2; ++j)
// note that std::min({arg1, arg2, arg3}) works only in C++11,
// for C++98 use std::min(std::min(arg1, arg2), arg3)
d[i][j] = std::min({ d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + (s1[i - 1] == s2[j - 1] ? 0 : 1) });
return d[len1][len2];
}
</syntaxhighlight>
Please note, that using <syntaxhighlight lang="cpp">vector<vector<>></syntaxhighlight> isn't efficient here, since you don't need a 2 dimensional array.
Here's another implementation with usage of only <math>\sim~ min(m, n)</math> memory (also it uses fact that <math>{lev}_{a, b}(i - 1, j - 1) \leq lev_{a, b}(i, j)</math>, so it is not needed to take minimum out of 3 possibilities):
<syntaxhighlight lang="cpp">
#include <algorithm>
#include <vector>
template<typename T>
typename T::size_type LevenshteinDistance(const T &source, const T &target) {
if (source.size() > target.size()) {
return LevenshteinDistance(target, source);
}
using TSizeType = typename T::size_type;
const TSizeType min_size = source.size(), max_size = target.size();
std::vector<TSizeType> lev_dist(min_size + 1);
for (TSizeType i = 0; i <= min_size; ++i) {
lev_dist[i] = i;
}
for (TSizeType j = 1; j <= max_size; ++j) {
TSizeType previous_diagonal = lev_dist[0], previous_diagonal_save;
++lev_dist[0];
for (TSizeType i = 1; i <= min_size; ++i) {
previous_diagonal_save = lev_dist[i];
if (source[i - 1] == target[j - 1]) {
lev_dist[i] = previous_diagonal;
} else {
lev_dist[i] = std::min(std::min(lev_dist[i - 1], lev_dist[i]), previous_diagonal) + 1;
}
previous_diagonal = previous_diagonal_save;
}
}
return lev_dist[min_size];
}
</syntaxhighlight>
Here is implementation of generalized Levenshtein distance with different costs of insertion, deletion and replacement:
<syntaxhighlight lang="cpp">
#include <algorithm>
#include <vector>
template<typename T>
typename T::size_type GeneralizedLevenshteinDistance(const T &source,
const T &target,
typename T::size_type insert_cost = 1,
typename T::size_type delete_cost = 1,
typename T::size_type replace_cost = 1) {
if (source.size() > target.size()) {
return GeneralizedLevenshteinDistance(target, source, delete_cost, insert_cost, replace_cost);
}
using TSizeType = typename T::size_type;
const TSizeType min_size = source.size(), max_size = target.size();
std::vector<TSizeType> lev_dist(min_size + 1);
lev_dist[0] = 0;
for (TSizeType i = 1; i <= min_size; ++i) {
lev_dist[i] = lev_dist[i - 1] + delete_cost;
}
for (TSizeType j = 1; j <= max_size; ++j) {
TSizeType previous_diagonal = lev_dist[0], previous_diagonal_save;
lev_dist[0] += insert_cost;
for (TSizeType i = 1; i <= min_size; ++i) {
previous_diagonal_save = lev_dist[i];
if (source[i - 1] == target[j - 1]) {
lev_dist[i] = previous_diagonal;
} else {
lev_dist[i] = std::min(std::min(lev_dist[i - 1] + delete_cost, lev_dist[i] + insert_cost), previous_diagonal + replace_cost);
}
previous_diagonal = previous_diagonal_save;
}
}
return lev_dist[min_size];
}
</syntaxhighlight>
==C#==
<syntaxhighlight lang="csharp">
private int levenshtein(string a, string b)
{
if (string.IsNullOrEmpty(a))
{
if (!string.IsNullOrEmpty(b))
{
return b.Length;
}
return 0;
}
if (string.IsNullOrEmpty(b))
{
if (!string.IsNullOrEmpty(a))
{
return a.Length;
}
return 0;
}
int cost;
int[,] d = new int[a.Length + 1, b.Length + 1];
int min1;
int min2;
int min3;
for (int i = 0; i <= d.GetUpperBound(0); i += 1)
{
d[i, 0] = i;
}
for (int i = 0; i <= d.GetUpperBound(1); i += 1)
{
d[0, i] = i;
}
for (int i = 1; i <= d.GetUpperBound(0); i += 1)
{
for (int j = 1; j <= d.GetUpperBound(1); j += 1)
{
cost = (a[i-1] != b[j-1])? 1 : 0;
min1 = d[i - 1, j] + 1;
min2 = d[i, j - 1] + 1;
min3 = d[i - 1, j - 1] + cost;
d[i, j] = Math.Min(Math.Min(min1, min2), min3);
}
}
return d[d.GetUpperBound(0), d.GetUpperBound(1)];
}
</syntaxhighlight>
An implementation with reduced memory usage
<syntaxhighlight lang="csharp">
public int LevenshteinDistance(string source, string target){
if(string.IsNullOrEmpty(source)){
if(string.IsNullOrEmpty(target)) return 0;
return target.Length;
}
if(string.IsNullOrEmpty(target)) return source.Length;
if(source.Length > target.Length){
var temp = target;
target = source;
source = temp;
}
var m = target.Length;
var n = source.Length;
var distance = new int[2, m + 1];
// Initialize the distance matrix
for(var j = 1; j <= m; j++) distance[0, j] = j;
var currentRow = 0;
for(var i = 1; i <= n; ++i){
currentRow = i & 1;
distance[currentRow, 0] = i;
var previousRow = currentRow ^ 1;
for(var j = 1; j <= m; j++) {
var cost = (target[j - 1] == source[i - 1] ? 0 : 1);
distance[currentRow, j] = Math.Min(Math.Min(
distance[previousRow, j] + 1,
distance[currentRow, j - 1] + 1),
distance[previousRow, j - 1] + cost);
}
}
return distance[currentRow, m];
}
</syntaxhighlight>
Damerau-Levenshtein distance is computed in the asymptotic time O ((max + 1) * min (first.length (), second.length ()))
<syntaxhighlight lang="csharp">
/// <summary>
/// Damerau-Levenshtein distance
/// </summary>
public class DamerauLevensteinMetric
{
private const int DEFAULT_LENGTH = 255;
private int[] _currentRow;
private int[] _previousRow;
private int[] _transpositionRow;
public DamerauLevensteinMetric()
: this(DEFAULT_LENGTH)
{
}
/// <summary>
///
/// </summary>
/// <param name="maxLength"></param>
public DamerauLevensteinMetric(int maxLength)
{
_currentRow = new int[maxLength + 1];
_previousRow = new int[maxLength + 1];
_transpositionRow = new int[maxLength + 1];
}
/// <summary>
/// Damerau-Levenshtein distance is computed in asymptotic time O((max + 1) * min(first.length(), second.length()))
/// </summary>
/// <param name="first"></param>
/// <param name="second"></param>
/// <param name="max"></param>
/// <returns></returns>
public int GetDistance(string first, string second, int max)
{
int firstLength = first.Length;
int secondLength = second.Length;
if (firstLength == 0)
return secondLength;
if (secondLength == 0) return firstLength;
if (firstLength > secondLength)
{
string tmp = first;
first = second;
second = tmp;
firstLength = secondLength;
secondLength = second.Length;
}
if (max < 0) max = secondLength;
if (secondLength - firstLength > max) return max + 1;
if (firstLength > _currentRow.Length)
{
_currentRow = new int[firstLength + 1];
_previousRow = new int[firstLength + 1];
_transpositionRow = new int[firstLength + 1];
}
for (int i = 0; i <= firstLength; i++)
_previousRow[i] = i;
char lastSecondCh = (char) 0;
for (int i = 1; i <= secondLength; i++)
{
char secondCh = second[i - 1];
_currentRow[0] = i;
// Compute only diagonal stripe of width 2 * (max + 1)
int from = Math.Max(i - max - 1, 1);
int to = Math.Min(i + max + 1, firstLength);
char lastFirstCh = (char) 0;
for (int j = from; j <= to; j++)
{
char firstCh = first[j - 1];
// Compute minimal cost of state change to current state from previous states of deletion, insertion and swapping
int cost = firstCh == secondCh ? 0 : 1;
int value = Math.Min(Math.Min(_currentRow[j - 1] + 1, _previousRow[j] + 1), _previousRow[j - 1] + cost);
// If there was transposition, take in account its cost
if (firstCh == lastSecondCh && secondCh == lastFirstCh)
value = Math.Min(value, _transpositionRow[j - 2] + cost);
_currentRow[j] = value;
lastFirstCh = firstCh;
}
lastSecondCh = secondCh;
int[] tempRow = _transpositionRow;
_transpositionRow = _previousRow;
_previousRow = _currentRow;
_currentRow = tempRow;
}
return _previousRow[firstLength];
}
}
</syntaxhighlight>
==Clojure==
<syntaxhighlight lang="clojure">
(defn nextelt
"Given two characters, the previous row, and a row we are
building, determine out the next element for this row."
[char1 char2 prevrow thisrow position]
(if (= char1 char2)
(prevrow (- position 1))
(+ 1 (min
(prevrow (- position 1))
(prevrow position)
(last thisrow))))
)
(defn nextrow
"Based on the next character from string1 and the whole of string2
calculate the next row. Initially thisrow contains one number."
[char1 str2 prevrow thisrow]
(let [char2 (first str2)
position (count thisrow)]
(if (= (count thisrow) (count prevrow))
thisrow
(recur
char1
(rest str2)
prevrow
(conj thisrow (nextelt char1 char2 prevrow thisrow position))))))
(defn levenshtein
"Calculate the Levenshtein distance between two strings."
([str1 str2]
(let [row0 (vec (map first (map vector (iterate inc 1) str2)))]
(levenshtein 1 (vec (cons 0 row0)) str1 str2)))
([row-nr prevrow str1 str2]
(let [next-row (nextrow (first str1) str2 prevrow (vector row-nr))
str1-remainder (.substring str1 1)]
(if (= "" str1-remainder)
(last next-row)
(recur (inc row-nr) next-row str1-remainder str2))))
)
</syntaxhighlight>
Another implementation using transient data structure, inspired by [http://en.wikibooks.org/w/index.php?title=Algorithm_Implementation/Strings/Levenshtein_distance&stable=0#Common_Lisp Common Lisp version]:
<syntaxhighlight lang="clojure">
(defn levenshtein [str1 str2]
"a Clojure levenshtein implementation using transient data structure"
(let [n (count str1) m (count str2)]
(cond
(= 0 n) m
(= 0 m) n
:else
(let [prev-col (transient (vec (range (inc m)))) col (transient [])] ; initialization for the first column.
(dotimes [i n]
(assoc! col 0 (inc i)) ; update col[0]
(dotimes [j m]
(assoc! col (inc j) ; update col[1..m]
(min (inc (nth col j))
(inc (nth prev-col (inc j)))
(+ (get prev-col j) (if (= (nth str1 i) (nth str2 j)) 0 1)))))
(dotimes [i (count prev-col)]
(assoc! prev-col i (get col i)))) ;
(last (persistent! col)))))) ; last element of last column
</syntaxhighlight>
== D ==
<syntaxhighlight lang="D">
import std.string;
import std.algorithm; // for min, already defines levenshteinDistance in library
pure nothrow size_t damerauDistance(const string source, const string target) {
immutable auto sourceLength = source.length;
immutable auto targetLength = target.length;
auto distance = new size_t[][](sourceLength + 1, targetLength+1);
for (auto iSource = 0; iSource <= sourceLength; ++iSource) {
distance[iSource][0] = iSource;
}
for (auto iTarget = 1; iTarget <= targetLength; ++iTarget) {
distance[0][iTarget] = iTarget;
}
for (auto iSource = 1; iSource <= sourceLength; ++iSource) {
for (auto iTarget = 1; iTarget <= targetLength; ++iTarget) {
auto delete1 = distance[iSource - 1][iTarget] + 1;
auto insert1 = distance[iSource][iTarget - 1] + 1;
size_t marginalCost = source[iSource - 1] == target[iTarget - 1] ? 0 : 1;
auto substitute = distance[iSource - 1][iTarget - 1] + marginalCost;
distance[iSource][iTarget] = min(delete1, insert1, substitute);
if (iSource > 1 && iTarget > 1 &&
source[iSource - 1] == target[iTarget - 2] &&
source[iSource - 2] == target[iTarget-1]) {
distance[iSource][iTarget] =
min(distance[iSource][iTarget], distance[iSource - 2][iTarget - 2] + marginalCost);
}
}
}
return distance[sourceLength][targetLength];
}
</syntaxhighlight>
== Delphi ==
A simple implementation that can certainly be improved upon.
<syntaxhighlight lang="delphi">
function Levenshtein(Word1, Word2: String): integer;
var lev : array of array of integer;
i,j : integer;
begin
// Word1 := LowerCase(Word1);
// Word2 := LowerCase(Word2);
// If the words are identical, do nothing
if Word1 = Word2 then
begin
result := 0;
exit;
end;
SetLength(lev, length(Word1) + 1);
for i := low(lev) to high(lev) do
setLength(lev[i], length(Word2) + 1);
for i := low(lev) to high(lev) do lev[i][0] := i;
for j := low(lev[low(lev)]) to high(lev[low(lev)]) do lev[0][j] := j;
for i := low(lev)+1 to high(lev) do
for j := low(lev[i])+1 to high(lev[i]) do
lev[i][j] := min(min(lev[i-1][j] + 1,lev[i][j-1] + 1)
,lev[i-1][j-1] + ifthen(Word1[i] = Word2[j], 0, 1));
result := lev[length(word1)][length(word2)];
end;
</syntaxhighlight>
== Eiffel ==
<syntaxhighlight lang="eiffel">
distance (a, b: STRING): INTEGER
-- Compute Levenshtein distance between strings `a' and `b'.
note
synopsis: "[
Example: Calculate distance between "sitting" and "kitten":
k i t t e n
0 1 2 3 4 5 6 <-- set top row to [0 .. m]
s 1 1 2 3 4 5 6
i 2 2 1 2 3 4 5
t 3 3 2 1 2 3 4
t 4 4 3 2 1 2 3
i 5 5 4 3 2 2 3
n 6 6 5 4 3 3 2
g 7 7 6 5 4 4 3! <-- Answer
^
|
set first column to [0 .. n]
Compute top row and left-most columns first. Then go cell-by-cell
(e.g. 1 .. n over 1 .. m), row-by-row, column-by-column, computing:
d[i-1, j] + 1 -- a deletion
d[i, j-1] + 1 -- an insertion
d[i-1, j-1] + 1 -- a substitution
Taking the minimum of each and putting it in its proper place in
the d[i, j] array, unless the char's are the same (e.g. a [i - 1] = b [j - 1])
]"
language_note: "[
Eiffel is a 1-based array system and not 0-based, so do not
read the array element accesses from the 0-based mindset.
]"
local
d: ARRAY2 [INTEGER]
i, j, m, n: INTEGER
do
m := a.count + 1; n := b.count + 1
create d.make_filled (0, m, n)
from i := 0 until i = m loop d [i + 1, 1] := i; i := i + 1 end
from j := 0 until j = n loop d [1, j + 1] := j; j := j + 1 end
from j := 2 until j > n loop
from i := 2 until i > m loop
if a [i - 1] = b [j - 1] then
d[i, j] := d[i-1, j-1]
else
d[i, j] := (d[i-1, j-1] + 1).min (d[i, j-1] + 1).min (d[i-1, j] + 1)
end
i := i + 1
end
j := j + 1
end
Result := d[m, n]
end
</syntaxhighlight>
== Emacs Lisp ==
<!--
Emacs lisp implementation maintained at the [[Emacs Wiki]].[http://www.emacswiki.org/cgi-bin/emacs-en/LevenshteinDistance]''
-->
<syntaxhighlight lang="lisp">
(defun levenshtein-distance (str1 str2)
"Return the edit distance between strings STR1 and STR2."
(if (not (stringp str1))
(error "Argument was not a string: %s" str1))
(if (not (stringp str2))
(error "Argument was not a string: %s" str2))
(let* ((make-table (function (lambda (columns rows init)
(make-vector rows (make-vector columns init)))))
(tref (function (lambda (table x y)
(aref (aref table y) x))))
(tset (function (lambda (table x y object)
(let ((row (copy-sequence (aref table y))))
(aset row x object)
(aset table y row) object))))
(length-str1 (length str1))
(length-str2 (length str2))
(d (funcall make-table (1+ length-str1) (1+ length-str2) 0)))
(let ((i 0) (j 0))
(while (<= i length-str1)
(funcall tset d i 0 i)
(setq i (1+ i)))
(while (<= j length-str2)
(funcall tset d 0 j j)
(setq j (1+ j))))
(let ((i 1))
(while (<= i length-str1)
(let ((j 1))
(while (<= j length-str2)
(let* ((cost (if (equal (aref str1 (1- i)) (aref str2 (1- j)))
0
1))
(deletion (1+ (funcall tref d (1- i) j)))
(insertion (1+ (funcall tref d i (1- j))))
(substitution (+ (funcall tref d (1- i) (1- j)) cost)))
(funcall tset d i j (min insertion deletion substitution)))
(setq j (1+ j))))
(setq i (1+ i))))
(funcall tref d length-str1 length-str2)))
</syntaxhighlight>
==Erlang==
<syntaxhighlight lang="erlang">
levenshtein(A, []) -> length(A);
levenshtein([], B) -> length(B);
levenshtein([A | TA] = AA, [B | TB] = BA) ->
lists:min([levenshtein(TA, BA) + 1,
levenshtein(AA, TB) + 1,
levenshtein(TA, TB) + delta(A, B)]).
delta(_A, _A) -> 0;
delta(_A, _B) -> 1.
</syntaxhighlight>
==F#==
The inlined min function gives a big speed boost.
<syntaxhighlight lang="fsharp">
let inline min3 one two three =
if one < two && one < three then one
elif two < three then two
else three
let wagnerFischer (s: string) (t: string) =
let m = s.Length
let n = t.Length
let d = Array2D.create (m + 1) (n + 1) 0
for i = 0 to m do d.[i, 0] <- i
for j = 0 to n do d.[0, j] <- j
for j = 1 to n do
for i = 1 to m do
if s.[i-1] = t.[j-1] then
d.[i, j] <- d.[i-1, j-1]
else
d.[i, j] <-
min3
(d.[i-1, j ] + 1) // a deletion
(d.[i , j-1] + 1) // an insertion
(d.[i-1, j-1] + 1) // a substitution
d.[m,n]
</syntaxhighlight>
and here's a slightly faster lazy version.
<syntaxhighlight lang="fsharp">
let wagnerFischerLazy (s: string) (t: string) =
let m = s.Length
let n = t.Length
let d = Array2D.create (m+1) (n+1) -1
let rec dist =
function
| i, 0 -> i
| 0, j -> j
| i, j when d.[i,j] <> -1 -> d.[i,j]
| i, j ->
let dval =
if s.[i-1] = t.[j-1] then dist (i-1, j-1)
else
min3
(dist (i-1, j) + 1) // a deletion
(dist (i, j-1) + 1) // an insertion
(dist (i-1, j-1) + 1) // a substitution
d.[i, j] <- dval; dval
dist (m, n)
</syntaxhighlight>
==Go==
This version uses dynamic programming with time complexity of <math>O(mn)</math> where <math>m</math> and <math>n</math> are lengths of <math>a</math> and <math>b</math>, and the space complexity is <math>n+1</math> of integers plus some constant space(i.e. <math>O(n)</math>).
<syntaxhighlight lang="go">
import "unicode/utf8"
func Levenshtein(a, b string) int {
f := make([]int, utf8.RuneCountInString(b)+1)
for j := range f {
f[j] = j
}
for _, ca := range a {
j := 1
fj1 := f[0] // fj1 is the value of f[j - 1] in last iteration
f[0]++
for _, cb := range b {
mn := min(f[j]+1, f[j-1]+1) // delete & insert
if cb != ca {
mn = min(mn, fj1+1) // change
} else {
mn = min(mn, fj1) // matched
}
fj1, f[j] = f[j], mn // save f[j] to fj1(j is about to increase), update f[j] to mn
j++
}
}
return f[len(f)-1]
}
func min(a, b int) int {
if a <= b {
return a
} else {
return b
}
}
</syntaxhighlight>
==Groovy==
This version is based on the Java version below
<syntaxhighlight lang="Groovy">
class Levenshtein {
def static int distance(String str1, String str2) {
def str1_len = str1.length()
def str2_len = str2.length()
int[][] distance = new int[str1_len + 1][str2_len + 1]
(str1_len + 1).times { distance[it][0] = it }
(str2_len + 1).times { distance[0][it] = it }
(1..str1_len).each { i ->
(1..str2_len).each { j ->
distance[i][j] = [distance[i-1][j]+1, distance[i][j-1]+1, str1[i-1]==str2[j-1]?distance[i-1][j-1]:distance[i-1][j-1]+1].min()
}
}
distance[str1_len][str2_len]
}
}
</syntaxhighlight>
== Haskell ==
Tested with GHCi.
<syntaxhighlight lang="haskell">
levenshtein::String->String->Int
levenshtein s t =
d!!(length s)!!(length t)
where d = [[distance m n|n<-[0..length t]]|m<-[0..length s]]
distance i 0 = i
distance 0 j = j
distance i j = minimum [d!!(i-1)!!j+1, d!!i!!(j-1)+1, d!!(i-1)!!(j-1) + (if s!!(i-1)==t!!(j-1) then 0 else 1)]
</syntaxhighlight>
and here's a slightly faster version.
<syntaxhighlight lang="haskell">
levenshtein::String->String->Int
levenshtein s t =
d!!(length s)!!(length t)
where d = [[distance m n|n<-[0..length t]]|m<-[0..length s]]
distance i 0 = i
distance 0 j = j
distance i j = if s!!(i-1)==t!!(j-1) then d!!(i-1)!!(j-1) else
1 + minimum [d!!(i-1)!!j, d!!i!!(j-1), d!!(i-1)!!(j-1)]
</syntaxhighlight>
For large strings, using arrays is much faster
<syntaxhighlight lang="haskell">
import Data.Array.Unboxed
import Data.Array.ST
import Control.Monad.ST
for_ xs f = mapM_ f xs
levenshtein :: [Char] -> [Char] -> Int
levenshtein s t = d ! (ls , lt)
where s' = array (0,ls) [ (i,x) | (i,x) <- zip [0..] s ]::UArray Int Char
t' = array (0,lt) [ (i,x) | (i,x) <- zip [0..] t ]::UArray Int Char
ls = length s
lt = length t
(l,h) = ((0,0),(length s,length t))
d = runSTUArray $ do
m <- newArray (l,h) 0 :: ST s (STUArray s (Int,Int) Int)
for_ [0..ls] $ \i -> writeArray m (i,0) i
for_ [0..lt] $ \j -> writeArray m (0,j) j
for_ [1..lt] $ \j -> do
for_ [1..ls] $ \i -> do
let c = if s'!(i-1)==t'! (j-1)
then 0 else 1
x <- readArray m (i-1,j)
y <- readArray m (i,j-1)
z <- readArray m (i-1,j-1)
writeArray m (i,j) $ minimum [x+1, y+1, z+c ]
return m
</syntaxhighlight>
As recursively defined array:
<syntaxhighlight lang="haskell">
import Array
toArray l = listArray (0, length l - 1) l -- makes an Array from a List
mkArray f bnds = array bnds [ (i, f i) | i <- range bnds ] -- defines an Array over its indices
levenshtein sa sb = table
where
arrA = toArray sa
arrB = toArray sb
table = mkArray f ((0,0), (length sa , length sb))
f (ia, 0) = ia
f (0 ,ib) = ib
f (ia,ib)
| a == b = table ! (ia-1,ib-1)
| otherwise = 1 + minimum [ table ! x | x <- [(ia-1,ib-1),(ia-1,ib),(ia,ib-1)] ]
where
a = arrA ! (ia - 1)
b = arrB ! (ib - 1)
</syntaxhighlight>
And finally: fast but cryptic implementation
<syntaxhighlight lang="haskell">
levenshtein2 sa sb = last $ foldl transform [0..length sa] sb
where
transform xs@(x:xs') c = scanl compute (x+1) (zip3 sa xs xs')
where
compute z (c', x, y) = minimum [y+1, z+1, x + fromEnum (c' /= c)]
</syntaxhighlight>
==Io==
<syntaxhighlight lang="io">
Levenshtein := method(left, right,
if(right size < left size, return Levenshtein(right, left))
current := 0 to(left size) asList
right foreach(i, righti,
previous := current
current = List clone with(i + 1)
left foreach(j, leftj,
current append((current at(j) + 1) min(previous at(j + 1) + 1) min(previous at(j) + if(leftj == righti, 0, 1)))
)
)
current last
)
</syntaxhighlight>
==JavaScript==
Slow recursive version:
<syntaxhighlight lang="javascript">
function levenshteinDistance (s, t) {
if (s.length === 0) return t.length;
if (t.length === 0) return s.length;
return Math.min(
levenshteinDistance(s.substr(1), t) + 1,
levenshteinDistance(t.substr(1), s) + 1,
levenshteinDistance(s.substr(1), t.substr(1)) + (s[0] !== t[0] ? 1 : 0)
);
}
</syntaxhighlight>
Faster approach using dynamic programming
<syntaxhighlight lang="javascript">
// Compute the edit distance between the two given strings
function getEditDistance(a, b) {
if (a.length === 0) return b.length;
if (b.length === 0) return a.length;
var matrix = [];
// increment along the first column of each row
var i;
for (i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
// increment each column in the first row
var j;
for (j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
// Fill in the rest of the matrix
for (i = 1; i <= b.length; i++) {
for (j = 1; j <= a.length; j++) {
if (b.charAt(i-1) == a.charAt(j-1)) {
matrix[i][j] = matrix[i-1][j-1];
} else {
matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
Math.min(matrix[i][j-1] + 1, // insertion
matrix[i-1][j] + 1)); // deletion
}
}
}
return matrix[b.length][a.length];
};
</syntaxhighlight>
[https://gist.github.com/982927 (source)]
==Java==
<syntaxhighlight lang="java">
public class LevenshteinDistance {
private static int minimum(int a, int b, int c) {
return Math.min(Math.min(a, b), c);
}
public static int computeLevenshteinDistance(CharSequence lhs, CharSequence rhs) {
int[][] distance = new int[lhs.length() + 1][rhs.length() + 1];
for (int i = 0; i <= lhs.length(); i++)
distance[i][0] = i;
for (int j = 1; j <= rhs.length(); j++)
distance[0][j] = j;
for (int i = 1; i <= lhs.length(); i++)
for (int j = 1; j <= rhs.length(); j++)
distance[i][j] = minimum(
distance[i - 1][j] + 1,
distance[i][j - 1] + 1,
distance[i - 1][j - 1] + ((lhs.charAt(i - 1) == rhs.charAt(j - 1)) ? 0 : 1));
return distance[lhs.length()][rhs.length()];
}
}
</syntaxhighlight>
Not recursive and faster
<syntaxhighlight lang="java">
public int levenshteinDistance (CharSequence lhs, CharSequence rhs) {
int len0 = lhs.length() + 1;
int len1 = rhs.length() + 1;
// the array of distances
int[] cost = new int[len0];
int[] newcost = new int[len0];
// initial cost of skipping prefix in String s0
for (int i = 0; i < len0; i++) cost[i] = i;
// dynamically computing the array of distances
// transformation cost for each letter in s1
for (int j = 1; j < len1; j++) {
// initial cost of skipping prefix in String s1
newcost[0] = j;
// transformation cost for each letter in s0
for(int i = 1; i < len0; i++) {
// matching current letters in both strings
int match = (lhs.charAt(i - 1) == rhs.charAt(j - 1)) ? 0 : 1;
// computing cost for each transformation
int cost_replace = cost[i - 1] + match;
int cost_insert = cost[i] + 1;
int cost_delete = newcost[i - 1] + 1;
// keep minimum cost
newcost[i] = Math.min(Math.min(cost_insert, cost_delete), cost_replace);
}
// swap cost/newcost arrays
int[] swap = cost; cost = newcost; newcost = swap;
}
// the distance is the cost for transforming all letters in both strings
return cost[len0 - 1];
}
</syntaxhighlight>
==Julia==
Straightforward recursive implementation. Do not use for large strings!
<syntaxhighlight lang="julia">
function levenshtein(lhs::String, rhs::String, lhsi::Int = length(lhs), rhsi::Int = length(rhs))
if lhsi == 0
return rhsi
end
if rhsi == 0
return lhsi
end
cost = lhs[lhsi] == rhs[rhsi] ? 0 : 1
min(
levenshtein(lhs, rhs, lhsi - 1, rhsi) + 1,
levenshtein(lhs, rhs, lhsi, rhsi - 1) + 1,
levenshtein(lhs, rhs, lhsi - 1, rhsi - 1) + cost
)
end
</syntaxhighlight>
Test with
<syntaxhighlight lang="julia">
@show levenshtein("aaa", "ab")
@show levenshtein("kitten", "sitting")
</syntaxhighlight>
==Kotlin==
<syntaxhighlight lang="kotlin">
fun levenshtein(lhs : CharSequence, rhs : CharSequence) : Int {
val lhsLength = lhs.length
val rhsLength = rhs.length
var cost = IntArray(lhsLength + 1) { it }
var newCost = IntArray(lhsLength + 1) { 0 }
for (i in 1..rhsLength) {
newCost[0] = i
for (j in 1..lhsLength) {
val editCost= if(lhs[j - 1] == rhs[i - 1]) 0 else 1
val costReplace = cost[j - 1] + editCost
val costInsert = cost[j] + 1
val costDelete = newCost[j - 1] + 1
newCost[j] = minOf(costInsert, costDelete, costReplace)
}
val swap = cost
cost = newCost
newCost = swap
}
return cost[lhsLength]
}
</syntaxhighlight>
==MySQL==
This implementation seems to be broken; but I am not entirely sure how to fix it.
<syntaxhighlight lang="mysql">
DROP FUNCTION IF EXISTS `levenshtein`;
CREATE FUNCTION `levenshtein`(`s1` VARCHAR(255) CHARACTER SET utf8, `s2` VARCHAR(255) CHARACTER SET utf8)
RETURNS TINYINT UNSIGNED
NO SQL
DETERMINISTIC
BEGIN
DECLARE s1_len, s2_len, i, j, c, c_temp TINYINT UNSIGNED;
-- max strlen=255 for this function
DECLARE cv0, cv1 VARBINARY(256);
-- if any param is NULL return NULL
-- (consistent with builtin functions)
IF (s1 + s2) IS NULL THEN
RETURN NULL;
END IF;
SET s1_len = CHAR_LENGTH(s1),
s2_len = CHAR_LENGTH(s2),
cv1 = 0x00,
j = 1,
i = 1,
c = 0;
-- if any string is empty,
-- distance is the length of the other one
IF (s1 = s2) THEN
RETURN 0;
ELSEIF (s1_len = 0) THEN
RETURN s2_len;
ELSEIF (s2_len = 0) THEN
RETURN s1_len;
END IF;
WHILE (j <= s2_len) DO
SET cv1 = CONCAT(cv1, CHAR(j)),
j = j + 1;
END WHILE;
WHILE (i <= s1_len) DO
SET c = i,
cv0 = CHAR(i),
j = 1;
-- What for syntax of WHILE is that?? MYSQL do not now. Please help.
WHILE (j <= c_temp) THEN
SET c = c_temp;
END IF;
SET c_temp = ORD(SUBSTRING(cv1, j+1, 1)) + 1;
IF (c > c_temp) THEN
SET c = c_temp;
END IF;
SET cv0 = CONCAT(cv0, CHAR(c)),
j = j + 1;
END WHILE;
SET cv1 = cv0,
i = i + 1;
END WHILE;
RETURN c;
END;
</syntaxhighlight>
The implementation below, thanks to Jason Rust at [http://www.codejanitor.com/wp/ Code Janitor], seems to be more complete.
<syntaxhighlight lang="MySQL">
CREATE FUNCTION levenshtein( s1 VARCHAR(255), s2 VARCHAR(255) )
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
DECLARE s1_char CHAR;
-- max strlen=255
DECLARE cv0, cv1 VARBINARY(256);
SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0;
IF s1 = s2 THEN
RETURN 0;
ELSEIF s1_len = 0 THEN
RETURN s2_len;
ELSEIF s2_len = 0 THEN
RETURN s1_len;
ELSE
WHILE j <= s2_len DO
SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1;
END WHILE;
WHILE i <= s1_len DO
SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1;
WHILE j <= s2_len DO
SET c = c + 1;
IF s1_char = SUBSTRING(s2, j, 1) THEN
SET cost = 0; ELSE SET cost = 1;
END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost;
IF c > c_temp THEN SET c = c_temp; END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1;
IF c > c_temp THEN
SET c = c_temp;
END IF;
SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1;
END WHILE;
SET cv1 = cv0, i = i + 1;
END WHILE;
END IF;
RETURN c;
END;
</syntaxhighlight>
==Objective-C==
<syntaxhighlight lang="Objective-C">
- (NSInteger)computeLevenshteinDistanceFrom:(NSString *)source to:(NSString *)target {
NSUInteger sourceLength = [source length] + 1;
NSUInteger targetLength = [target length] + 1;
NSMutableArray *cost = [NSMutableArray new];
NSMutableArray *newCost = [NSMutableArray new];
for (NSUInteger i = 0; i < sourceLength; i++) {
cost[i] = @(i);
}
for (NSUInteger j = 1; j < targetLength; j++) {
newCost[0] = @(j - 1);
for (NSUInteger i = 1; i < sourceLength; i++) {
NSInteger match = ([source characterAtIndex:i - 1] == [target characterAtIndex:j - 1]) ? 0 : 1;
NSInteger costReplace = [cost[i - 1] integerValue] + match;
NSInteger costInsert = [cost[i] integerValue] + 1;
NSInteger costDelete = [newCost[i - 1] integerValue] + 1;
newCost[i] = @(MIN(MIN(costInsert, costDelete), costReplace));
}
NSMutableArray *swap = cost;
cost = newCost;
newCost = swap;
}
return [cost[sourceLength - 1] integerValue];
}
</syntaxhighlight>
Or with extensions "and C flavor"
<syntaxhighlight lang="Objective-C">
#define MIN3(a, b, c) ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c)))
@implementation NSString (LevensteinDistance)
- (NSUInteger)distance:(NSString *)query {
const char *selfCharArray = [self UTF8String];
const char *queryCharArray = [query UTF8String];
NSUInteger x, y;
NSUInteger selfLength = strlen(selfCharArray);
NSUInteger queryLength = strlen(queryCharArray);
NSUInteger matrix[queryLength + 1][selfLength + 1];
matrix[0][0] = 0;
for (x = 1; x <= queryLength; x++) {
matrix[x][0] = matrix[x - 1][0] + 1;
}
for (y = 1; y <= selfLength; y++) {
matrix[0][y] = matrix[0][y - 1] + 1;
}
for (x = 1; x <= queryLength; x++) {
for (y = 1; y <= selfLength; y++) {
matrix[x][y] = MIN3(matrix[x - 1][y] + 1, matrix[x][y - 1] + 1, matrix[x - 1][y - 1] + (selfCharArray[y - 1] == queryCharArray[x - 1] ? 0 : 1));
}
}
return (matrix[queryLength][selfLength]);
}
@end
</syntaxhighlight>
==OCaml==
<syntaxhighlight lang="ocaml">
(* Minimum of three integers. This function is deliberately
* not polymorphic because (1) we only need to compare integers
* and (2) the OCaml compilers do not perform type specialization
* for user-defined functions. *)
let minimum (x:int) y z =
let m' (a:int) b = if a < b then a else b in
m' (m' x y) z
(* Matrix initialization. *)
let init_matrix n m =
let init_col = Array.init m in
Array.init n (function
| 0 -> init_col (function j -> j)
| i -> init_col (function 0 -> i | _ -> 0)
)
(* Computes the Levenshtein distance between two unistring.
* If you want to run it faster, add the -unsafe option when
* compiling or use Array.unsafe_* functions (but be carefull
* with these well-named unsafe features). *)
let distance_utf8 x y =
match Array.length x, Array.length y with
| 0, n -> n
| m, 0 -> m
| m, n ->
let matrix = init_matrix (m + 1) (n + 1) in
for i = 1 to m do
let s = matrix.(i) and t = matrix.(i - 1) in
for j = 1 to n do
let cost = abs (compare x.(i - 1) y.(j - 1)) in
s.(j) <- minimum (t.(j) + 1) (s.(j - 1) + 1) (t.(j - 1) + cost)
done
done;
matrix.(m).(n)
(* This function takes two strings, convert them to unistring (int array)
* and then call distance_utf8, so we can compare utf8 strings. Please
* note that you need Glib (see LablGTK). *)
let distance x y =
distance_utf8 (Glib.Utf8.to_unistring x) (Glib.Utf8.to_unistring y)
</syntaxhighlight>
==Octave And MATLAB ==
<!-- % (C) Nov 2006, Muthiah Annamalai
%
% Eventually implemented the Levenshtein distance from
% wikipedia article on Levenshtein Distance.
%
% -->
<syntaxhighlight lang="matlab">
function [dist,L]=levenshtein_distance(str1,str2)
L1=length(str1)+1;
L2=length(str2)+1;
L=zeros(L1,L2);
g=+1;%just constant
m=+0;%match is cheaper, we seek to minimize
d=+1;%not-a-match is more costly.
%do BC's
L(:,1)=([0:L1-1]*g)';
L(1,:)=[0:L2-1]*g;
m4=0;%loop invariant
for idx=2:L1;
for idy=2:L2
if(str1(idx-1)==str2(idy-1))
score=m;
else
score=d;
end
m1=L(idx-1,idy-1) + score;
m2=L(idx-1,idy) + g;
m3=L(idx,idy-1) + g;
L(idx,idy)=min(m1,min(m2,m3));
end
end
dist=L(L1,L2);
return
end
</syntaxhighlight>
<syntaxhighlight lang="matlab">
%I think this function generates errors:
%>> levenshtein('aaa','ab')
% ans =
% 1
%correct answer here is 2, I believe: 1 deletion, 1 replacement?
function q = levenshtein(s1,s2)
d = toeplitz(find(s1),find(s2))-1;
for j = 1:numel(s2)-1
for i = 1:numel(s1)-1
d(i+1,j+1) = min(min(d(i,j+1),d(i+1,j)) + 1,d(i,j) + ne(s1(i), s2(j)));
end
end
q = d(end) + eq(i,j)*ne(s1(end),s2(end)); % check if last chars are different
</syntaxhighlight>
==Perl==
<syntaxhighlight lang="perl">
use List::Util qw(min);
sub levenshtein {
my ($str1, $str2) = @_;
my @ar1 = split //, $str1;
my @ar2 = split //, $str2;
my @dist;
$dist[$_][0] = $_ foreach (0 .. @ar1);
$dist[0][$_] = $_ foreach (0 .. @ar2);
foreach my $i (1 .. @ar1){
foreach my $j (1 .. @ar2){
my $cost = $ar1[$i - 1] eq $ar2[$j - 1] ? 0 : 1;
$dist[$i][$j] = min(
$dist[$i - 1][$j] + 1,
$dist[$i][$j - 1] + 1,
$dist[$i - 1][$j - 1] + $cost );
}
}
return $dist[@ar1][@ar2];
}
</syntaxhighlight>
==Phix==
<syntaxhighlight lang="phix">
function levenshtein(string a, b)
sequence costs = tagset(length(b)+1,0)
for i=1 to length(a) do
costs[1] = i
integer newcost = i-1, pj = i, cj
for j=1 to length(b) do
cj = costs[j+1]
pj = min({pj+1, cj+1, newcost+(a[i]!=b[j])})
{costs[j+1],newcost} = {pj,cj}
end for
end for
return costs[$-1]
end function
</syntaxhighlight>
==PHP==
PHP has provided the built-in <code>levenshtein()</code> function since PHP 4.0.1. Before PHP 8.0, it returned <code>-1</code> when either input string exceeded 255 bytes; this restriction was removed in PHP 8.0.<ref>[https://www.php.net/manual/en/function.levenshtein.php PHP Manual — levenshtein()]</ref> The built-in function is normally preferable when only the distance is needed. The following implementation is included to illustrate the Wagner–Fischer dynamic-programming recurrence.
This example computes standard unit-cost Levenshtein distance, allowing insertion, deletion and substitution, but not treating adjacent transposition as a single edit. Only the current and previous dynamic-programming rows are retained. The shorter input is placed along the row-width dimension to minimize auxiliary memory.
<syntaxhighlight lang="php">
<?php
function leven(string $s1, string $s2): int
{
$length1 = strlen($s1);
$length2 = strlen($s2);
// Standard unit-cost Levenshtein distance is symmetric.
// Keep the shorter input on the row-width dimension.
if ($length1 < $length2) {
[$s1, $s2] = [$s2, $s1];
[$length1, $length2] = [$length2, $length1];
}
// Distance from an empty prefix to each prefix of s2.
$previousRow = range(0, $length2);
for ($i = 1; $i <= $length1; ++$i) {
$currentRow = [$i];
for ($j = 1; $j <= $length2; ++$j) {
$cost = ($s1[$i - 1] === $s2[$j - 1]) ? 0 : 1;
$currentRow[$j] = min(
$previousRow[$j] + 1, // Deletion
$currentRow[$j - 1] + 1, // Insertion
$previousRow[$j - 1] + $cost // Match/substitution
);
}
$previousRow = $currentRow;
}
return $previousRow[$length2];
}
// Examples (PHP 8+):
echo leven('kitten', 'sitting'), "\n"; // 3
echo leven('ab', 'ba'), "\n"; // 2 (no transposition operation)
echo leven('', 'abc'), "\n"; // 3
echo leven(str_repeat('a', 300), str_repeat('a', 300)), "\n"; // 0
</syntaxhighlight>
===Complexity===
For byte lengths <code>m</code> and <code>n</code>, the time complexity is O(mn) and the auxiliary-space complexity is O(min(m,n)). The implementation returns the distance only, not the sequence of edit operations.
===Character representation and UTF-8===
PHP strings are byte sequences. Both <code>strlen()</code> and string indexing in the example work with bytes, so the function computes byte-level edit distance. The built-in <code>levenshtein()</code> likewise compares bytes rather than Unicode code points or grapheme clusters. For example, in UTF-8, <code>leven('é', 'e')</code> returns 2 because the first input occupies two bytes; comparing these as Unicode code points would instead give a distance of 1.
For multilingual text, choose an explicit normalization policy and comparison unit before computing edit distance. See also the [[#Unicode considerations|Unicode considerations]] section above. Unicode-aware segmentation requires additional processing; merely replacing <code>strlen()</code> with <code>mb_strlen()</code> is insufficient because individual byte-index accesses would remain.
===Further reading===
An extended discussion of implementation correctness, space optimization, Unicode representation and validation is available at:
https://www.levenshtein.net/levenshtein-implementations
== plpgsql ==
Copied the PHP version using a single dimensional array
<syntaxhighlight lang="plpgsql">
CREATE OR REPLACE FUNCTION levenshtein(s text, t text)
RETURNS integer AS $$
DECLARE i integer;
DECLARE j integer;
DECLARE m integer;
DECLARE n integer;
DECLARE d integer[];
DECLARE c integer;
BEGIN
m := char_length(s);
n := char_length(t);
i := 0;
j := 0;
FOR i IN 0..m LOOP
d[i*(n+1)] = i;
END LOOP;
FOR j IN 0..n LOOP
d[j] = j;
END LOOP;
FOR i IN 1..m LOOP
FOR j IN 1..n LOOP
IF SUBSTRING(s,i,1) = SUBSTRING(t, j,1) THEN
c := 0;
ELSE
c := 1;
END IF;
d[i*(n+1)+j] := LEAST(d[(i-1)*(n+1)+j]+1, d[i*(n+1)+j-1]+1, d[(i-1)*(n+1)+j-1]+c);
END LOOP;
END LOOP;
return d[m*(n+1)+n];
END;
$$ LANGUAGE plpgsql IMMUTABLE
</syntaxhighlight>
== Python ==
The first version is a Dynamic Programming algorithm, with the added optimization that only the last two rows of the dynamic programming matrix are needed for the computation:
<syntaxhighlight lang="python">
def levenshtein(s1, s2):
if len(s1) < len(s2):
return levenshtein(s2, s1)
# len(s1) >= len(s2)
if len(s2) == 0:
return len(s1)
previous_row = range(len(s2) + 1)
for i, c1 in enumerate(s1):
current_row = [i + 1]
for j, c2 in enumerate(s2):
insertions = previous_row[j + 1] + 1 # j+1 instead of j since previous_row and current_row are one character longer
deletions = current_row[j] + 1 # than s2
substitutions = previous_row[j] + (c1 != c2)
current_row.append(min(insertions, deletions, substitutions))
previous_row = current_row
return previous_row[-1]
</syntaxhighlight>
Second version:
<syntaxhighlight lang="python">def lev(a, b):
if not a: return len(b)
if not b: return len(a)
return min(lev(a[1:], b[1:])+(a[0] != b[0]), lev(a[1:], b)+1, lev(a, b[1:])+1)</syntaxhighlight>
''(Note that while very compact, the runtime of this implementation is really poor, making it unusable in practical usage. One way to make it significantly faster would be to add a <code>@functools.cache</code> decorator, but it does not make it optimal due to the many string copies).''
Third version (works):
<syntaxhighlight lang="python">def LD(s,t):
s = ' ' + s
t = ' ' + t
d = {}
S = len(s)
T = len(t)
for i in range(S):
d[i, 0] = i
for j in range (T):
d[0, j] = j
for j in range(1,T):
for i in range(1,S):
if s[i] == t[j]:
d[i, j] = d[i-1, j-1]
else:
d[i, j] = min(d[i-1, j], d[i, j-1], d[i-1, j-1]) + 1
return d[S-1, T-1]</syntaxhighlight>
''(Note that while compact, the runtime of this implementation is relatively poor.)''
4th version:
<syntaxhighlight lang="python">def levenshtein(seq1, seq2):
oneago = None
thisrow = range(1, len(seq2) + 1) + [0]
for x in xrange(len(seq1)):
twoago, oneago, thisrow = oneago, thisrow, [0] * len(seq2) + [x + 1]
for y in xrange(len(seq2)):
delcost = oneago[y] + 1
addcost = thisrow[y - 1] + 1
subcost = oneago[y - 1] + (seq1[x] != seq2[y])
thisrow[y] = min(delcost, addcost, subcost)
return thisrow[len(seq2) - 1]</syntaxhighlight>
''(Note this implementation is O(N*M) time and O(M) space, for N and M the lengths of the two sequences.)''
5th, a vectorized version of the 1st, using NumPy. About 40% faster, on my test case.
However, this numpy vectorized Python version incorrectly returns 5 for <code>levenshtein('aabcc', 'bccdd')</code> (which should be 4 for two 'a' insertions + 2 'd' deletions). The reason is that the deletion step <code>np.minimum(current_row[1:], current_row[0:-1] + 1)</code> does not handle the case that the minimum for <code>current_row[j]</code> could be <code>current_row[j-2] + 2</code> due to two consecutive deletions as it is in this example. See [[Talk:Algorithm_Implementation/Strings/Levenshtein_distance#Bug_in_vectorized_(5th)_version|Discussion]].
<syntaxhighlight lang="python">
def levenshtein(source, target):
if len(source) < len(target):
return levenshtein(target, source)
# So now we have len(source) >= len(target).
if len(target) == 0:
return len(source)
# We call tuple() to force strings to be used as sequences
# ('c', 'a', 't', 's') - numpy uses them as values by default.
source = np.array(tuple(source))
target = np.array(tuple(target))
# We use a dynamic programming algorithm, but with the
# added optimization that we only need the last two rows
# of the matrix.
previous_row = np.arange(target.size + 1)
for s in source:
# Insertion (target grows longer than source):
current_row = previous_row + 1
# Substitution or matching:
# Target and source items are aligned, and either
# are different (cost of 1), or are the same (cost of 0).
current_row[1:] = np.minimum(
current_row[1:],
np.add(previous_row[:-1], target != s))
# Deletion (target grows shorter than source):
current_row[1:] = np.minimum(
current_row[1:],
current_row[0:-1] + 1)
previous_row = current_row
return previous_row[-1]
</syntaxhighlight>
''(Note this implementation only works if the weight does not depend on the character edited.)''
6th version, from Wikipedia article on Levenshtein Distance; Iterative with two matrix rows.
<syntaxhighlight lang="python">
# Christopher P. Matthews
# christophermatthews1985@gmail.com
# Sacramento, CA, USA
def levenshtein(s, t):
''' From Wikipedia article; Iterative with two matrix rows. '''
if s == t: return 0
elif len(s) == 0: return len(t)
elif len(t) == 0: return len(s)
v0 = [None] * (len(t) + 1)
v1 = [None] * (len(t) + 1)
for i in range(len(v0)):
v0[i] = i
for i in range(len(s)):
v1[0] = i + 1
for j in range(len(t)):
cost = 0 if s[i] == t[j] else 1
v1[j + 1] = min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost)
for j in range(len(v0)):
v0[j] = v1[j]
return v1[len(t)]
</syntaxhighlight>
==R/S+==
<syntaxhighlight lang="rsplus">
function (str1, str2)
{
if (typeof(str1) != "character" && class(str1) != "factor")
stop(sprintf("Illegal data type: %s", typeof(str1)))
if (class(str1) == "factor")
str = as.character(str1)
if (typeof(str2) != "character" && class(str2) != "factor")
stop(sprintf("Illegal data type: %s", typeof(str2)))
if (class(str2) == "factor")
str = as.character(str2)
if ((is.array(str1) || is.array(str2)) && dim(str1) != dim(str2))
stop("non-conformable arrays")
if (length(str1) == 0 || length(str2) == 0)
return(integer(0))
l1 <- length(str1)
l2 <- length(str2)
out <- .C("levenshtein", as.character(str1), as.character(str2),
l1, l2, ans = integer(max(l1, l2)), PACKAGE = "RecordLinkage")
if (any(is.na(str1), is.na(str2)))
out$ans[is.na(str1) | is.na(str2)] = NA
if (is.array(str1))
return(array(out$ans, dim(str1)))
if (is.array(str2))
return(array(out$ans, dim(str2)))
return(out$ans)
}
</syntaxhighlight>
"(Note) this is just one of many implementations of the Levenshtein Distance, but I've not been able to get the others to work
==rexx==
<syntaxhighlight lang="rexx">
/* rexx levenshtein calculates the edit distance Karlocai 2009-01-18
between 2 strings s and t
This implementation of the Levenshtein algorithm
uses one row only (0..n), containing
- values of the previous line in columns [i-1]..n and
- values of the current line in columns 1..[i-2]
The current left value is kept in the variable lc
i: column 1..n of s, 1st index
j: row 1..m of t, 2nd index
*/
Parse Arg s,t -- gets 2 strings as parameter
n = Length(s) -- checks the parameters
m = Length(t)
If n = 0 Then
Return m
If m = 0 Then
Return n
Do i = 0 To n -- initializes the 1st row
r.i = i
End
Do j = 1 To m -- for each row
lc = j -- left column start value
Do i = 1 To n -- for each column
nv = Min(r.i + 1, ,
lc + 1, ,
r.[i-1] + (Substr(s,i,1) <> Substr(t,j,1)))
r.[i-1] = lc -- sets previous left column
lc = nv -- current left column
End
r.n = lc -- sets last current value
End
Return r.n
</syntaxhighlight>
==Ruby==
This Ruby version is simple, but extremely slow, though it works with any Array with elements that implement '=='.
<syntaxhighlight lang="ruby">
def levenshtein(first:, second:)
case
when first.empty? then second.length
when second.empty? then first.length
else [(first[0] == second[0] ? 0 : 1) + levenshtein(first: first[1..-1], second: second[1..-1]),
1 + levenshtein(first: first[1..-1], second: second),
1 + levenshtein(first: first, second: second[1..-1])].min
end
end
</syntaxhighlight>
This memoized version is significantly faster
<syntaxhighlight lang="ruby">
def levenshtein(first:, second:)
matrix = [(0..first.length).to_a]
(1..second.length).each do |j|
matrix << [j] + [0] * (first.length)
end
(1..second.length).each do |i|
(1..first.length).each do |j|
if first[j-1] == second[i-1]
matrix[i][j] = matrix[i-1][j-1]
else
matrix[i][j] = [
matrix[i-1][j],
matrix[i][j-1],
matrix[i-1][j-1],
].min + 1
end
end
end
return matrix.last.last
end
</syntaxhighlight>
And another memoized version
<syntaxhighlight lang="ruby">
def levenshtein(first:, second:)
m, n = first.length, second.length
return m if n == 0
return n if m == 0
# Create our distance matrix
d = Array.new(m+1) {Array.new(n+1)}
0.upto(m) { |i| d[i][0] = i }
0.upto(n) { |j| d[0][j] = j }
1.upto(n) do |j|
1.upto(m) do |i|
d[i][j] = first[i-1] == second[j-1] ? d[i-1][j-1] : [d[i-1][j]+1,d[i][j-1]+1,d[i-1][j-1]+1,].min
end
end
d[m][n]
end
</syntaxhighlight>
A faster implementation for the Levenshtein distance of strings (using C bindings) is available [http://github.com/dbalatero/levenshtein-ffi here]
==Rust==
A simple implementation in Rust (beta2), transposed from the C version. It is a little more general than the bare minimum, in fact it accepts any type that can be converted to &[u8].
<syntaxhighlight lang="rust" line="1">
fn levenshtein<T1: AsRef<[u8]>, T2: AsRef<[u8]>>(s1: T1, s2: T2) -> usize {
let v1 = s1.as_ref();
let v2 = s2.as_ref();
// Early exit if one of the strings is empty
let v1len = v1.len();
let v2len = v2.len();
if v1len == 0 { return v2len; }
if v2len == 0 { return v1len; }
#[inline]
fn min3<T: Ord>(v1: T, v2: T, v3: T) -> T{
std::cmp::min(v1, std::cmp::min(v2, v3))
}
#[inline]
fn delta(x: u8, y: u8) -> usize {
if x == y { 0 } else { 1 }
}
let mut column: Vec<usize> = (0..v1len+1).collect();
for x in 1..v2len+1 {
column[0] = x;
let mut lastdiag = x-1;
for y in 1..v1len+1 {
let olddiag = column[y];
column[y] = min3(
column[y] + 1,
column[y-1] + 1,
lastdiag + delta(v1[y-1], v2[x-1]),
);
lastdiag = olddiag;
}
}
column[v1len]
}
</syntaxhighlight>
You can test it live on [http://slug.it/levenshtein-distance-rust Rust Playpen].
==Scala==
===Imperative version===
A functional version would likely be far more concise.
<syntaxhighlight lang="scala">
def levenshtein(str1: String, str2: String): Int = {
val lenStr1 = str1.length
val lenStr2 = str2.length
val d: Array[Array[Int]] = Array.ofDim(lenStr1 + 1, lenStr2 + 1)
for (i <- 0 to lenStr1) d(i)(0) = i
for (j <- 0 to lenStr2) d(0)(j) = j
for (i <- 1 to lenStr1; j <- 1 to lenStr2) {
val cost = if (str1(i - 1) == str2(j - 1)) 0 else 1
d(i)(j) = min(
d(i-1)(j ) + 1, // deletion
d(i )(j-1) + 1, // insertion
d(i-1)(j-1) + cost // substitution
)
}
d(lenStr1)(lenStr2)
}
def min(nums: Int*): Int = nums.min</syntaxhighlight>
===Functional version===
<syntaxhighlight lang=scala>import scala.collection.mutable
import scala.collection.parallel.ParSeq
def levenshtein(s1: String, s2: String): Int = {
val memorizedCosts = mutable.Map[(Int, Int), Int]()
def lev: ((Int, Int)) => Int = {
case (k1, k2) =>
memorizedCosts.getOrElseUpdate((k1, k2), (k1, k2) match {
case (i, 0) => i
case (0, j) => j
case (i, j) =>
ParSeq(1 + lev((i - 1, j)),
1 + lev((i, j - 1)),
lev((i - 1, j - 1))
+ (if (s1(i - 1) != s2(j - 1)) 1 else 0)).min
})
}
lev((s1.length, s2.length))
}</syntaxhighlight>
==Scheme==
<syntaxhighlight lang=scheme>
;; using the `match' macro as defined in http://synthcode.com/scheme/match.scm
(define/memoized (edit-distance a b)
(match `(,a ,b)
(`(,a ())
(length a))
(`(() ,b)
(length b))
(`((,a0 . ,a*) (,b0 . ,b*))
(min (+ (edit-distance a* b) 1)
(+ (edit-distance a b*) 1)
(+ (edit-distance a* b*)
(if (equal? a0 b0) 0 2))))))
;; where the `define/memoized' special form can be defined in the following way:
(define (memoized proc)
(let ((cache (make-hash-table)))
(lambda args
(match (hash-get-handle cache args)
(`(,key . ,memoized-result)
(apply values memoized-result))
(_
(call-with-values (lambda () (apply proc args))
(lambda result
(hash-set! cache args result)
(apply values result))))))))
(define-syntax-rule (define/memoized (name . args) . body)
(define name (memoized (lambda args . body))))
</syntaxhighlight>
==Smalltalk==
<syntaxhighlight lang="smalltalk">
levenshteinDistanceBetween: stringOne and: stringTwo
"Iterative calculation of the Levenshtein distance between two strings."
| arrayTwo arrayOne|
" degenerate cases"
stringTwo = stringOne
ifTrue:[^0].
(stringTwo size) = 0
ifTrue:[^(stringOne size)].
(stringOne size) = 0
ifTrue:[^(stringTwo size)].
"create two work vectors of integer distances"
arrayOne := Array new:((stringTwo size) + 1).
arrayTwo := Array new:((stringTwo size) + 1).
"initialize v0 (the previous row of distances)
this row is A[0][i]: edit distance for an empty s
the distance is just the number of characters to delete from t"
(1 to: (arrayOne size)) do:[ :i | arrayOne at: i put: i-1 ].
(1 to: (stringOne size)) do: [ : i |
" calculate v1 (current row distances) from the previous row v0
first element of v1 is A[i+1][0] edit distance is delete (i+1) chars from s to match empty t"
arrayTwo at: 1 put: i.
" use formula to fill in the rest of the row"
(1 to: (stringTwo size)) do: [ :j || cost minimum minimumAux |
((stringOne at: i) = (stringTwo at: j))
ifTrue:[cost:=0]
ifFalse:[cost:=1].
minimumAux := ((arrayTwo at: j) + 1) min: ((arrayOne at: (j+1)) + 1).
minimum := minimumAux min: ((arrayOne at: j) + cost).
arrayTwo at: (j+1) put: minimum.].
(1 to: (arrayOne size)) do: [ :j | arrayOne at: j put: (arrayTwo at: j) ].
].
^arrayTwo at: ((stringTwo size)+1).
</syntaxhighlight>
==Swift==
<syntaxhighlight lang="swift">
/**
* Levenshtein edit distance calculator
*
* Inspired by https://gist.github.com/bgreenlee/52d93a1d8fa1b8c1f38b
* Improved with http://stackoverflow.com/questions/26990394/slow-swift-arrays-and-strings-performance
*/
class Levenshtein {
private class func min(numbers: Int...) -> Int {
return numbers.reduce(numbers[0], combine: {$0 < $1 ? $0 : $1})
}
class Array2D {
var cols:Int, rows:Int
var matrix: [Int]
init(cols:Int, rows:Int) {
self.cols = cols
self.rows = rows
matrix = Array(count:cols*rows, repeatedValue:0)
}
subscript(col:Int, row:Int) -> Int {
get {
return matrix[cols * row + col]
}
set {
matrix[cols*row+col] = newValue
}
}
func colCount() -> Int {
return self.cols
}
func rowCount() -> Int {
return self.rows
}
}
class func distanceBetween(aStr: String, and bStr: String) -> Int {
let a = Array(aStr.utf16)
let b = Array(bStr.utf16)
let dist = Array2D(cols: a.count + 1, rows: b.count + 1)
for i in 1...a.count {
dist[i, 0] = i
}
for j in 1...b.count {
dist[0, j] = j
}
for i in 1...a.count {
for j in 1...b.count {
if a[i-1] == b[j-1] {
dist[i, j] = dist[i-1, j-1] // noop
} else {
dist[i, j] = min(
dist[i-1, j] + 1, // deletion
dist[i, j-1] + 1, // insertion
dist[i-1, j-1] + 1 // substitution
)
}
}
}
return dist[a.count, b.count]
}
}
</syntaxhighlight>
==Turing==
<syntaxhighlight lang="turing">
%find the levenshtein distance
function LD (s, t : string) : int
% a couple variables
var cell_above := 0
var cell_left := 0
var cell_diagonal := 0
var cost := 0
%lengths
var n := length (s)
var m := length (t)
%if a string is zero
if n = 0 then
result m
elsif m = 0 then
result n
else
end if
% make an array with both words
var matrix : array 0 .. n, 0 .. m of int
% initialize array to the length of each word
for i : 0 .. n
matrix (i, 0) := i
end for
for i : 0 .. m
matrix (0, i) := i
end for
% calculate total changes
for i : 1 .. n
for j : 1 .. m
if s (i) = t (j) then
cost := 0
else
cost := 1
end if
cell_above := matrix (i - 1, j) + 1
cell_left := matrix (i, j - 1) + 1
cell_diagonal := matrix (i - 1, j - 1) + cost
var mini := min (cell_above, cell_left)
matrix (i, j) := min (mini, cell_diagonal)
end for
end for
result matrix (n, m)
end LD
put LD ("s", "t")
</syntaxhighlight>
==VBScript==
This version is identical to JavaScript and PHP implementations in this article.
<syntaxhighlight lang="vb">
Function levenshtein( a, b )
Dim i,j,cost,d,min1,min2,min3
' Avoid calculations where there there are empty words
If Len( a ) = 0 Then levenshtein = Len( b ): Exit Function
If Len( b ) = 0 Then levenshtein = Len( a ): Exit Function
' Array initialization
ReDim d( Len( a ), Len( b ) )
For i = 0 To Len( a ): d( i, 0 ) = i: Next
For j = 0 To Len( b ): d( 0, j ) = j: Next
' Actual calculation
For i = 1 To Len( a )
For j = 1 To Len( b )
If Mid(a, i, 1) = Mid(b, j, 1) Then cost = 0 Else cost = 1 End If
' Since min() function is not a part of VBScript, we'll "emulate" it below
min1 = ( d( i - 1, j ) + 1 )
min2 = ( d( i, j - 1 ) + 1 )
min3 = ( d( i - 1, j - 1 ) + cost )
If min1 <= min2 And min1 <= min3 Then
d( i, j ) = min1
ElseIf min2 <= min1 And min2 <= min3 Then
d( i, j ) = min2
Else
d( i, j ) = min3
End If
Next
Next
levenshtein = d( Len( a ), Len( b ) )
End Function
</syntaxhighlight>
==Visual Basic for Applications (no Damerau extension)==
This version is identical to JavaScript and PHP implementations in this article. I had problems when I tried to use the other VBA implementation in this article, so I had to adopt the version below.
Application.WorksheetFunction.Min() method is Excel-specific. If you implement it with other VBA-enabled applications, uncomment the conditional block and comment out the Application.WorksheetFunction.Min() line.
<syntaxhighlight lang="vb">
Function levenshtein(a As String, b As String) As Integer
Dim i As Integer
Dim j As Integer
Dim cost As Integer
Dim d(,) As Integer
Dim min1 As Integer
Dim min2 As Integer
Dim min3 As Integer
If Len( a ) = 0 Then
levenshtein = Len( b )
Exit Function
End If
If Len( b ) = 0 Then
levenshtein = Len( a )
Exit Function
End If
ReDim d(Len(a), Len(b))
For i = 0 To Len(a)
d(i, 0) = i
Next
For j = 0 To Len(b)
d(0, j) = j
Next
For i = 1 To Len(a)
For j = 1 To Len(b)
If Mid(a, i, 1) = Mid(b, j, 1) Then
cost = 0
Else
cost = 1
End If
' Since Min() function is not a part of VBA, we'll "emulate" it below
min1 = (d(i - 1, j) + 1)
min2 = (d(i, j - 1) + 1)
min3 = (d(i - 1, j - 1) + cost)
' If min1 <= min2 And min1 <= min3 Then
' d(i, j) = min1
' ElseIf min2 <= min1 And min2 <= min3 Then
' d(i, j) = min2
' Else
' d(i, j) = min3
' End If
' In Excel we can use Min() function that is included
' as a method of WorksheetFunction object
d(i, j) = Application.WorksheetFunction.Min(min1, min2, min3)
Next
Next
levenshtein = d(Len(a), Len(b))
End Function
</syntaxhighlight>
==MapBasic==
This version is identical to VB implementations in this article.
<syntaxhighlight lang="VB">
type twoDimArrayType
secondArray() as integer
end type
dim FirstArray() as twoDimArrayType
Dim i As Integer
Dim j As Integer
Dim cost As Integer
Dim d() As Integer
Dim min1 As Integer
Dim min2 As Integer
Dim min3 As Integer
declare Function calculateLevenshteinDistance(byval firstString As String, byval secondString As String) As Integer
Function calculateLevenshteinDistance(byval firstString As String, byval secondString As String) As Integer
print chr$(12)
'If one of the parameter is null, then the result will be the length of the other parameter...
if Len(firstString) = 0 Then
calculateLevenshteinDistance = Len(secondString)
exit Function
end if
if Len(secondString) = 0 Then
calculateLevenshteinDistance = Len(firstString)
exit Function
end if
'Initializing array...
redim FirstArray(len(firstString)+1)
for i=1 to ubound(FirstArray)
redim FirstArray(i).secondArray(len(secondString)+1)
next
'Deletion...
For i = 1 To ubound(FirstArray)
FirstArray(i).secondArray(1) = i-1
Next
'Insertion ...
For i = 1 To ubound(FirstArray(ubound(FirstArray)).secondArray)
FirstArray(1).secondArray(i) = i-1
Next
'Actual calculation...
for i=2 to ubound(FirstArray)
for j=2 to ubound(FirstArray(i).secondArray)
If StringCompare(Mid$(firstString, i-1, 1), Mid$(secondString, j-1, 1))=0 Then
cost = 0
Else
cost = 1
End If
min1 = FirstArray(i-1).secondArray(j) + 1
min2 = FirstArray(i).secondArray(j-1) + 1
min3 = FirstArray(i-1).secondArray(j-1) + cost
If min1 <= min2 And min1 <= min3 Then
FirstArray(i).secondArray(j) = min1
ElseIf min2 <= min1 And min2 <= min3 Then
FirstArray(i).secondArray(j) = min2
Else
FirstArray(i).secondArray(j) = min3
End If
Next
Next
'Calculating Return Value...
calculateLevenshteinDistance = FirstArray(ubound(FirstArray)).secondArray(ubound(FirstArray(ubound(FirstArray)).secondArray))
End Function
</syntaxhighlight>
== Teslock ==
This is the Levenshtein distance calculation in Teslock Machine Language.
<pre>
.declare singlecall virtual LevenshteinDistance[args(2) string s1, string s2]: out unsigned int
main
(
define unsigned int constant "cost_ins" == 1;
define unsigned int constant "cost_del" == 1;
define unsigned int constant "cost_sub" == 1;
define unsigned int variable "n1" == calculate::string_operations>length("s1");
define unsigned int variable "n2" == calculate::string_operations>length("s2");
define unsigned int_array(calculate::string_operations>array_instantiation("p")>fixed_length("n2", ++1));
define unsigned int_array(calculate::string_operations>array_instantiation("q")>fixed_length("n2", ++1));
define unsigned int_array(calculate::string_operations>array_instantiation("r")>variable_length);
p>array_vector>0 == 0;
loop_for>finalized(define unsigned int variable "j" == 1)>break_condition("j" <= "n2")>forward_condition(++j)
(
p>array_vector>j == p>array_vector>j::access>+constants::cost_ins;
)
q>array_vector>0 == 0;
loop_for>finalized(define unsigned int variable "i" == 1)>break_condition("i" <= "n1")>forward_condition(++i)
(
q>array_vector>0 == p>array_vector>0::access>+constants::cost_del;
loop for>finalized(define unsigned int variable "j" == 1)>break_condition("j" <= "n2")>forward_condition(++j)
(
define unsigned int variable "d_del" == p>array_vector>j::access>+constants::cost_del;
define unsigned int variable "d_ins" == q>array_vector>j[delegate_handle::j::access>-1]>+constants::cost_ins;
define unsigned int veriable "d_sub" == p>array_vector>j[delegate_handle::j::access>-1]>+logical_operations>xor_result["s1"::access>"s1"[delegate_handle::j::access>-1]?0>return_handle_as_result constants::"cost_sub"];
q>array_vector>j == dll_extern::math_interop_singlecall(min)::[args(3) (d_del, d_ins), d_sub;
)
local>"r" == "p"(self_typecast::ignore_unsafe_condition);
local>"p" == "q"(self_typecast);
local>"q" == "r"(self_typecast);
)
logical_result(param p::singlecall)::define>"return" == p>array_vector>"n2";
)
</pre>
== Abap ==
Please note that there is a standard ABAP function [https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abendistance_functions.htm distance] which calculates the Levenshtein distance without need for the below coding.
<syntaxhighlight lang="abap">
REPORT zlevenshtein.
*----------------------------------------------------------------------*
* CLASS lcl_levenshtein DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_levenshtein DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
distance IMPORTING i_s TYPE csequence
i_t TYPE csequence
RETURNING value(r) TYPE i.
ENDCLASS. "lcl_c DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_levenshtein IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_levenshtein IMPLEMENTATION.
METHOD distance.
DEFINE m_get.
l_m_index = ( ( l_l_t * ( l_m_i + ( &2 ) ) ) + l_m_j + ( &1 ) ) + 1 .
read table l_d into r index l_m_index.
add &3 to r.
insert r into table l_v.
END-OF-DEFINITION.
DATA: l_d TYPE STANDARD TABLE OF i,
l_v TYPE SORTED TABLE OF i WITH UNIQUE KEY table_line,
l_cost TYPE i,
l_m_i TYPE i,
l_m_j TYPE i,
l_m_index TYPE i,
l_l_s TYPE i,
l_l_t TYPE i.
l_l_s = STRLEN( i_s ).
l_l_t = STRLEN( i_t ).
DO l_l_s TIMES.
l_m_i = sy-index - 1.
DO l_l_t TIMES. "#EC CI_NESTED
l_m_j = sy-index - 1.
IF i_s+l_m_i(1) = i_t+l_m_j(1).
l_cost = 0.
ELSE.
l_cost = 1.
ENDIF.
IF l_m_j = 0.
r = l_cost.
ELSEIF l_m_i = 0.
r = l_cost.
ELSE.
CLEAR l_v.
m_get: -1 0 1, 0 -1 1, -1 -1 l_cost.
READ TABLE l_v INTO r INDEX 1.
ENDIF.
APPEND r TO l_d.
ENDDO.
ENDDO.
ENDMETHOD. "distance
ENDCLASS. "lcl_levenshtein IMPLEMENTATION
START-OF-SELECTION.
DATA: d TYPE i.
d = lcl_levenshtein=>distance( i_s = 'sitting' i_t = 'kitten' ).
WRITE: / d.
</syntaxhighlight>
== Pick Basic ==
<syntaxhighlight lang="basic">
IF STRING1 = STRING2 THEN
LD = 0
END ELSE
S.LEN = LEN(STRING1)
C.LEN = LEN(STRING2)
MAT LD.MTX = ''
DIM LD.MTX(100,100)
FOR I = 3 TO S.LEN + 2
LD.MTX(I,1) = STRING1[I-2,1]
NEXT I
FOR I = 3 TO S.LEN + 2
LD.MTX(I,2) = I - 2
NEXT I
FOR I = 3 TO C.LEN + 2
LD.MTX(1,I) = STRING2[I-2,1]
NEXT I
LD.MTX(2,2) = 0
FOR I = 3 TO C.LEN + 2
LD.MTX(2,I) = I - 2
NEXT I
FOR I = 3 TO (S.LEN+2)
S.LETTER = LD.MTX(I,1)
FOR J = 3 TO (C.LEN+2)
C.LETTER = LD.MTX(1,J)
IF C.LETTER = S.LETTER THEN COST = 0 ELSE COST = 1
P1 = LD.MTX(I-1,J) + 1
P2 = LD.MTX(I,J-1) + 1
P3 = LD.MTX(I-1,J-1) + COST
IF P1 < P2 THEN LD.NUM = P1 ELSE LD.NUM = P2
IF P3 < LD.NUM THEN LD.NUM = P3
LD.MTX(I,J) = LD.NUM
NEXT J
NEXT I
LD = LD.MTX(S.LEN+2,C.LEN+2)
END
</syntaxhighlight>
{{subject}}
<references />
== '''Zig''' ==
Implementation of the C Version<syntaxhighlight lang="zig" line="1">
// Damerau-Levenshtein includes transposition, remove for normal Levenshtein
pub fn levenshteinDistance(a: []const u8, b: []const u8) !u8 {
const length: usize = a.len + 1;
var column = try std.ArrayList(u8).initCapacity(std.heap.page_allocator, length);
try column.appendNTimes(0, length);
defer column.deinit();
var y: u8 = 1;
while (y <= a.len) : (y += 1) {
column.items[y] = y;
var x: u8 = 1;
while (x <= b.len) : (x += 1) {
column.items[0] = x;
var last_diag = x - 1;
var j: u8 = 1;
while (j <= a.len) : (j += 1) {
const old_diag = column.items[j];
const cost: u8 = if (a[j - 1] == b[x - 1]) 0 else 1;
const deletion: u8 = column.items[j] + 1;
const insertion: u8 = column.items[j - 1] + 1;
const substitution: u8 = last_diag + cost;
const transposition: u8 = if (j > 1 and x > 1 and a[j - 1] == b[x - 2] and a[j - 2] == b[x - 1]) column.items[j - 2] + 1 else std.math.maxInt(u8);
column.items[j] = std.mem.min(u8, &.{ deletion, insertion, substitution, transposition });
last_diag = old_diag;
}
}
}
return column.items[length - 1];
}
</syntaxhighlight>
93sgccq06ltepl4s2x9ejgfmvjyl0he
Template:Haskell/Wider Theory
10
104167
4675936
3292377
2026-10-13T23:55:06Z
~2026-54868-50
3628373
4675936
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/Denotational semantics|Denotational semantics]] {{stage|75%}}
{{{sep|<br>}}}[[Haskell/Equational reasoning|Equational reasoning]]
{{{sep|<br>}}}[[Haskell/Program derivation|Program derivation]]
{{{sep|<br>}}}[[Haskell/Category theory|Category theory]]
{{{sep|<br>}}}[[Haskell/The Curry–Howard isomorphism|The Curry–Howard isomorphism]]
{{{sep|<br>}}}[[Haskell/Fix and recursion|fix and recursion]]
{{Haskell/Chapter navbar|Wider Theory}}<noinclude>{{BookCat}}</noinclude>
b1fhg256n71acktudkyrfroe66vp257
Template:Haskell/Chapter navbar
10
106769
4675890
3292359
2026-10-13T18:16:10Z
Luciérnaga de conocimiento
3401314
4675890
wikitext
text/x-wiki
<div style="clear:both;"><small class="noprint">[{{fullurl:Template:Haskell/{{{1}}}|action=edit}} edit this chapter]
</small></div>
<noinclude>{{BookCat}}</noinclude>
p64giy0uskn4rvboeyif21mku5g97e4
4675896
4675890
2026-10-13T18:29:13Z
Luciérnaga de conocimiento
3401314
4675896
wikitext
text/x-wiki
<div style="clear:both;"><small class="noprint">
Parámetro recibido: {{{1}}}
[{{fullurl:Template:Haskell/{{{1}}}|action=edit}} edit this chapter]
</small></div>
<noinclude>{{BookCat}}</noinclude>
lo86ixw1t5xvuu9o5niparmtmboc9vu
4675897
4675896
2026-10-13T18:30:53Z
Luciérnaga de conocimiento
3401314
Undid revision [[Special:Diff/4675896|4675896]] by [[Special:Contributions/Luciérnaga de conocimiento|Luciérnaga de conocimiento]] ([[User talk:Luciérnaga de conocimiento|discuss]])
4675897
wikitext
text/x-wiki
<div style="clear:both;"><small class="noprint">[{{fullurl:Template:Haskell/{{{1}}}|action=edit}} edit this chapter]
</small></div>
<noinclude>{{BookCat}}</noinclude>
p64giy0uskn4rvboeyif21mku5g97e4
4675900
4675897
2026-10-13T18:47:26Z
Luciérnaga de conocimiento
3401314
4675900
wikitext
text/x-wiki
<div style="clear:both;"><small class="noprint">[{{fullurl:Template:Haskell/{{{1|Haskell Basics}}}|action=edit}} edit this chapter]
</small></div>
<noinclude>{{BookCat}}</noinclude>
02euvpuflih0ugq3hvgwvhhucc1okzl
4675901
4675900
2026-10-13T18:52:42Z
Luciérnaga de conocimiento
3401314
4675901
wikitext
text/x-wiki
<div style="clear:both;"><small class="noprint">
Parámetro recibido: {{{1|SIN PARÁMETRO}}}
[{{fullurl:Template:Haskell/{{{1|Haskell Basics}}}|action=edit}} edit this chapter]
</small></div>
<noinclude>{{BookCat}}</noinclude>
efblbrvpjjj6rvczf5w05a3bihxnors
4675902
4675901
2026-10-13T18:56:13Z
Luciérnaga de conocimiento
3401314
Undid revision [[Special:Diff/4675901|4675901]] by [[Special:Contributions/Luciérnaga de conocimiento|Luciérnaga de conocimiento]] ([[User talk:Luciérnaga de conocimiento|discuss]])
4675902
wikitext
text/x-wiki
<div style="clear:both;"><small class="noprint">[{{fullurl:Template:Haskell/{{{1|Haskell Basics}}}|action=edit}} edit this chapter]
</small></div>
<noinclude>{{BookCat}}</noinclude>
02euvpuflih0ugq3hvgwvhhucc1okzl
4675903
4675902
2026-10-13T18:56:27Z
Luciérnaga de conocimiento
3401314
4675903
wikitext
text/x-wiki
<div style="clear:both;"><small class="noprint">[{{fullurl:Template:Haskell/{{{1}}}|action=edit}} edit this chapter]
</small></div>
<noinclude>{{BookCat}}</noinclude>
p64giy0uskn4rvboeyif21mku5g97e4
Template:Haskell/General Practices
10
107342
4675947
3292316
2026-10-14T00:27:07Z
~2026-54868-50
3628373
4675947
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/Debugging|Debugging]]
{{{sep|<br>}}}[[Haskell/Testing|Testing]]
{{{sep|<br>}}}[[Haskell/Packaging|Packaging your software (Cabal)]]
{{{sep|<br>}}}[[Haskell/FFI|Using the Foreign Function Interface (FFI)]]
{{{sep|<br>}}}[[Haskell/SYB|Generic programming: Scrap your boilerplate]]
{{Haskell/Chapter navbar|General Practices}}<noinclude>{{BookCat}}</noinclude>
jxq7ykvrc35mqmn9a0dlhwnqy6grjvj
Template:Haskell/Specialised Tasks
10
107343
4675948
3697783
2026-10-14T00:27:19Z
~2026-54868-50
3628373
4675948
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/GUI|Graphical user interfaces (GUI)]] [[Image:50%.svg]]
{{{sep|<br>}}}[[Haskell/Database|Databases]] [[File:00%.svg]]
{{{sep|<br>}}}[[Haskell/XML|Working with XML]] [[File:00%.svg]]
{{{sep|<br>}}}[[Haskell/ParseExps|Parsing mathematical expressions]] [[File:100 percent.svg]]
{{{sep|<br>}}}[[Haskell/TypeCheck|Writing a basic type checker]] [[File:00%.svg]]
{{Haskell/Chapter navbar|Specialised Tasks}}<noinclude>{{BookCat}}</noinclude>
ne0z0saww2r691uiz6421ndqahjg3af
Template:Haskell/Libraries Reference
10
107345
4675946
3292350
2026-10-14T00:26:56Z
~2026-54868-50
3628373
4675946
wikitext
text/x-wiki
{{{firstsep|}}}[[Haskell/Libraries|Introduction]]
{{{breaksep|{{{subsep|<br>}}}}}}[[Haskell/Libraries/Maybe|Maybe]]{{{subsep|<br>}}}[[Haskell/Libraries/IO|IO]]{{{subsep|<br>}}}[[Haskell/Libraries/Random|Random]]
{{{sep|<br>}}}[[Haskell/Libraries/Data structures primer|Data structures primer]] {{stage|75%}}
{{{breaksep|{{{subsep|<br>}}}}}}[[Haskell/Libraries/Arrays|Arrays]]{{{subsep|<br>}}}[[Haskell/Libraries/Maps|Maps]]
{{Haskell/Chapter navbar|Libraries Reference}}<noinclude>{{BookCat}}</noinclude>
4ktlaqge9voyf7rcoek7tz2jkbd2gpp
Template:Haskell/Stub
10
108827
4675952
3363859
2026-10-14T00:38:56Z
~2026-54868-50
3628373
4675952
wikitext
text/x-wiki
{{Bmbox|type=content|text=''This {{#switch:{{{sectiononly}}}|1|true=section|page}} is a [[Help:Stub|stub]]. You can help [[Haskell]] by [{{fullurl:{{FULLPAGENAME}}|action=edit}} expanding it].''}}<includeonly>{{#ifeq:{{{example|no}}}|no|[[{{BOOKCATEGORY}}/Stubs|{{BOOKSORTKEY}}]]}}</includeonly><noinclude>{{BookCat}}</noinclude>
cq6ke00jsrsod77x920k80jn3tlkvl9
Wikibooks:Reading room/General
4
112405
4675839
4675806
2026-10-13T14:00:49Z
Codename Noreste
3441010
/* Feedback on Wikibooks redirect */ ([[:m:User:Max/MaxEdit.js|MaxEdit]])
4675839
wikitext
text/x-wiki
__NEWSECTIONLINK__ {{Discussion Rooms}} {{Shortcut|WB:CHAT|WB:RR/G|WB:GENERAL}} {{TOC left|limit=3}}
{{User:MiszaBot/config
|archive = Wikibooks:Reading room/Archives/%(year)d/%(monthname)s
|algo = old(60d)
|counter = 1
|minthreadstoarchive = 1
|minthreadsleft = 1
|key = 7a0ac23cf8049e4d9ff70cabb5649d1a
}}
Welcome to the '''General reading room'''. On this page, Wikibookians are free to talk about the Wikibooks project in general. For proposals for improving Wikibooks, see the [[../Proposals/]] reading room.
{{clear}}
[[Category:Reading room]]
== Call for administrators ==
Any experienced editor who has a good understanding of Wikibooks' policies should consider applying for administrator permissions at [[Wikibooks:Requests for permissions]]. Thank you. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] ([[User talk:Codename Noreste|discuss]] • [[Special:Contributions/Codename Noreste|contribs]]) 22:10, 5 August 2026 (UTC)
:Is there a page here that describes what admins do? I am curious because I checked [https://en.wikibooks.org/wiki/Special:ListUsers?username=&group=sysop&wpsubmit=&wpFormIdentifier=mw-listusers-form&limit=50 List of admins] and I see that there are already quite a few admins here and wonder which areas have a shortage.
:Just curious. [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 00:56, 16 September 2026 (UTC)
::[[Wikibooks:Administrators]]. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 01:09, 16 September 2026 (UTC)
== August 2026 Wikimedia Café meetups regarding [https://meta.wikimedia.org/wiki/Next_25 Next 25] ==
<div class="border-box" style="background-color: var(--background-color-warning-subtle, #f8eaba); max-width: 875px; padding: 5px; border: 1px solid black; margin: 5px; color: var(--clr-dark)">
<div class="box" style="float:left; padding-top: 10px; padding-right: 10px; padding-left: 10px; padding-bottom: 10px;">[[File:Wikimedia Café logo in plain SVG format.svg|60px|alt=The logo for the Wikimedia Café]]</div>
Hello! There will be two '''[https://meta.wikimedia.org/wiki/Wikimedia_Caf%C3%A9 Wikimedia Café]''' discussion opportunities in August. Both sessions will focus on [https://meta.wikimedia.org/wiki/Next_25 the Next 25 initiative], including [https://meta.wikimedia.org/wiki/Next_25/A_proposal_to_frame_Next_25 framing the initiative]. Participants may attend either or both Café sessions.
#'''29 August 2026 15:00 UTC''' ([https://zonestamp.toolforge.org/1788015600 timestamp converter]), at a time friendly to the Americas, Africa, and Europe
#'''30 August 2026 03:00 UTC''' ([https://zonestamp.toolforge.org/1788058800 timestamp converter]), at a time friendly to Asia and the Pacific
Please see the [https://meta.wikimedia.org/wiki/Wikimedia_Caf%C3%A9 Café] page for more information, including [https://meta.wikimedia.org/wiki/Wikimedia_Caf%C3%A9#Agenda._This_will_be_an_approximately_1_hour_Caf%C3%A9_session agenda details] and [https://meta.wikimedia.org/wiki/Wikimedia_Caf%C3%A9#How_to_attend_the_session how to register]!
To subscribe or unsubscribe for Café notices on your talk page please [https://meta.wikimedia.org/wiki/Global_message_delivery/Targets/Wikimedia_Caf%C3%A9 go here].
<br />
[[File:Buntstifte Eberhard Faber crop 64h.jpg|860px|alt=cropped image of colored pencils]]</div>
<span style="white-space:nowrap;">[[User:Pine|<span style="color:#01796f; text-shadow:#00BFFF 0 0 1.0em">༄ᨒ𖠰 Pine</span>]] [[User talk:Pine|<span style="color:DeepSkyBlue">(<b style="color:#FFDF00;text-shadow:#FFDF00 0 0 1.0em">✉</b>)</span>]]</span> 01:32, 17 August 2026 (UTC)
== Wikibooks project is not defined by goal ==
If it is for texbooks why is it called Wikibooks? It should be called Wikitextbooks! If it is for textbooks why does it contain cookbooks? For textbooks it's not supposed to have a [[Wikibooks:Featured books]]. [[User:Vivairan2|Vivairan2]] ([[User talk:Vivairan2|discuss]] • [[Special:Contributions/Vivairan2|contribs]]) 09:20, 1 September 2026 (UTC)
:It's "textbooks" broadly construed: guides, manuals, how-tos, etc. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 11:15, 1 September 2026 (UTC)
::So we should change "Wikibooks:Featured books" to "Wikibooks:Featured texts". [[User:Vivairan2|Vivairan2]] ([[User talk:Vivairan2|discuss]] • [[Special:Contributions/Vivairan2|contribs]]) 11:17, 1 September 2026 (UTC)
:::I disagree and even if I agreed, it would be priority #49,389. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 11:20, 1 September 2026 (UTC)
::::It's according to community consensus that says this website contains textbooks not books. [[User:Vivairan2|Vivairan2]] ([[User talk:Vivairan2|discuss]] • [[Special:Contributions/Vivairan2|contribs]]) 11:23, 1 September 2026 (UTC)
:::::"[[wb:WIW|Simply, Wikibooks is a collection of open-content textbooks.]]" [[User:Vivairan2|Vivairan2]] ([[User talk:Vivairan2|discuss]] • [[Special:Contributions/Vivairan2|contribs]]) 11:26, 1 September 2026 (UTC)
:Most textbooks are made by collaboration of some authors, co-authors and editors. Wikibooks help pages and guidelines remain silent when it comes to stages of writing a new texbooks. Even [[Using Wikibooks]] is not complete emough for enthusiasts. --[[User:Vivairan2|Vivairan2]] ([[User talk:Vivairan2|discuss]] • [[Special:Contributions/Vivairan2|contribs]]) 18:13, 3 September 2026 (UTC)
:@[[User:Vivairan2|Vivairan2]], In my opinion this is a good question. I wish more users would chime in. [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 16:10, 19 September 2026 (UTC)
== Wishlist 2027, invitation to share feedback ==
Hi, I’m [[m:User:SPerry-WMF|Sonja]] and I lead some of the [[mw:Contributors|teams]] at the Foundation who will be responsible for picking up wish work under the new wishlist process.
As you may know, the [[m:Community_Wishlist|Community Wishlist]] started out as an annual process through which Wikimedia contributors submit and vote on technical improvements they would like the Wikimedia Foundation to work on. The main goal of it is and has been to improve the editing experience by making changes and features the community asks for specifically.
In recent years, the process behind the wishlist has changed, and we’ve heard from many of you that it no longer meets many community members’ needs. So now, the Foundation is designing a new process with the community to improve how wishes are triaged, voted on, and prioritized in a way that is transparent, balanced across project families and language editions, and takes into account what the Foundation can deliver.
I would like to get community input specifically on these three stages of the Wishlist process:
* The [[m:Special:MyLanguage/Community_Wishlist/Community_Wishlist_2027#triage|'''triage stage''']], meaning how wishes are fleshed out, organized and filtered prior to voting
** We recommend to have a working group, including volunteers from various wikis and Wikimedia Foundation staff to work through this together
* The [[m:Special:MyLanguage/Community_Wishlist/Community_Wishlist_2027#vote|'''voting stage''']], including who may vote and how votes are structured
* The [[m:Special:MyLanguage/Community_Wishlist/Community_Wishlist_2027#postvote|'''post-vote stage''']], including how to bring equity into what work is prioritized
** One way to do this is to rank wishes within 3 categories: Large Wikipedias or covering all wikis, small and medium-sized Wikipedias, and '''sister projects''', so that top-voted wishes from smaller projects also get attention
This message is an abstract of the full proposed process. As you [[m:Special:MyLanguage/Community_Wishlist/Community_Wishlist_2027|read the proposed ideas on Meta]] (available in your language), please speak up about whether you think this will work well or if there are ways to make it stronger.
Regarding the timeline, this consultation is open for two weeks. You can post your feedback on Meta (in your preferred language) or in response below.
For this year’s cycle, [[m:Special:MyLanguage/Community_Wishlist/Community_Wishlist_2027#timeline|we plan]] to have the wish submission period in late October/early November and the triage process completed by late November. To respect the end-of-year holiday season, voting would happen in early to mid January. This first voting cycle is meant as a first step to try out a new process, and there will be more opportunities to provide feedback along the way, so that we can figure out the best process for future years together.
[[oldwikisource:M:User:SPerry-WMF|SPerry-WMF]], delivered by [[User:Trizek (WMF)|Trizek (WMF)]] ([[User talk:Trizek (WMF)|discuss]] • [[Special:Contributions/Trizek (WMF)|contribs]]) 13:52, 1 September 2026 (UTC)
:Thank you to everyone who engaged in the discussion around [[m:Talk:Community_Wishlist/Community_Wishlist_2027|the proposal from August 26]]. We've processed your feedback and [https://meta.wikimedia.org/w/index.php?title=Community_Wishlist/Community_Wishlist_2027&diff=prev&oldid=31041090 made changes] accordingly. Note that we weren’t able to implement all of it for this cycle, mostly for logistical reasons, but this is merely meant to be a first step and we will continue to improve this process with you all before we run through the next cycle. We plan to use [[m:Community_Wishlist/Community_Wishlist_2027#Updated_Community_Wishlist_Process_2027/2028|this updated version]] for the Wishlist 2027, and we look forward to hearing from you all during the submission and voting periods.
:[[:M:User:SPerry-WMF|SPerry-WMF]], delivered by [[User:Trizek (WMF)|Trizek (WMF)]] ([[User talk:Trizek (WMF)|discuss]] • [[Special:Contributions/Trizek (WMF)|contribs]]) 14:49, 17 September 2026 (UTC)
::@[[User:SPerry-WMF|User:SPerry-WMF]],@[[User:Trizek (WMF)|Trizek (WMF)]]: Thank you for posting info regarding the wishlist to the English Wikibooks. I am sure there are many new users here who can benefit.
::I used to participate in those discussions years ago and I know a lot of effort goes into making discussions useful not only for users of wikipedia, but also for the many language versions of the smaller wikimedia projects such as Wikibooks. [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 16:28, 19 September 2026 (UTC)
== How Do I Get My Book On A Shelf? ==
Help, I don't know how shelves work. I don't know how to put my book on a shelf. Can anyone help?
The book is called''' Art And AI''' [[User:3MMPEYTON|3MMPEYTON]] ([[User talk:3MMPEYTON|discuss]] • [[Special:Contributions/3MMPEYTON|contribs]]) 23:00, 8 September 2026 (UTC)
: Which shelf are you referring? [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:45, 10 September 2026 (UTC)
== Who is allowed to delete pages here? ==
On Aug 14, 2026 a user by the name of Max deleted a page I created in my user space. I don't see max in the list of admins here. Do they have the right to delete pages? Is there any documentation here I can consult?
Thanks in advance, [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 22:38, 15 September 2026 (UTC)
:We have local admins who have the technical ability to delete pages and virtually all material deleted here would be done by us (I'm one of them). A fairly small amount of users have global rights across all Wikimedia Foundation wikis and they will very rarely make deletions (e.g. if there are some kind of legal implications to material). [[User:Ottawahitech/American politics]] was deleted by [[User:Max]], who has [[Special:UserRights/Max|no special rights here]] but is one of the [[:m:Global sysops|global sysops]] I mentioned earlier. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 22:55, 15 September 2026 (UTC)
: Probably unrelated to the above, but Ottawahitech should do that with their account, unless if they are blocked. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 23:33, 15 September 2026 (UTC)
::Agreed and [[User:Ottawahitech]] is not blocked here, so no idea why he's using a temp account. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 23:43, 15 September 2026 (UTC)
:::There may be many reasons registered users are "editing" without logging in. Is it possible that they want to go about peacefully without attracting too much attention? [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 15:01, 16 September 2026 (UTC)
:::: We neither have a policy nor a guideline about this, probably. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 19:12, 20 September 2026 (UTC)
::::Notwithstanding a claim that the temp account is actually User:Ottawahitech, we have no idea that they are the same person. If the temp account is the same person, and they want to have a user space page, they can create temp account ones. The registered user account pages are intended for that registered user account and not as a dumping ground for anyone to create pages. [[User:MarcGarver|MarcGarver]] ([[User talk:MarcGarver|discuss]] • [[Special:Contributions/MarcGarver|contribs]]) 08:29, 13 October 2026 (UTC)
== Assistance to get page reviewed ==
My page is a translation page: [[Baiyi Zhuan]]
It is a single page, it is translated according to my own ability and familiarity with the language with a disclosure on external tools. I would like it to get reviewed if possible as I do not have the rights. [[User:Taitesena|Taitesena]] ([[User talk:Taitesena|discuss]] • [[Special:Contributions/Taitesena|contribs]]) 11:19, 18 September 2026 (UTC)
== Translation of books ==
Hello,
I would like to translate books from other Wikibooks into English. Are there any guidelines regarding how to do this? [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 00:34, 20 September 2026 (UTC)
: This has yet to be expanded, but you might want to take a look at [[Wikibooks:Content translation]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 19:13, 20 September 2026 (UTC)
== Feedback on Wikibooks redirect ==
I would like your feedback on my proposal to make [[Wikibooks:Username|this page]] redirect to [[Using Wikibooks/Setting Up A User Account#Choosing a Username|this page]]? I would do it myself, but it is not possible due to the fact that [[Wikibooks:Username]] can only be made by admins. This is because [[Wikibooks:Username policy]] also links to [[Using Wikibooks/Setting Up A User Account#Choosing a Username|this page]]. Regards, [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 04:37, 21 September 2026 (UTC)
:{{support}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 00:00, 22 September 2026 (UTC)
:This seems like a good idea to me. [[User:Alextejthompson|''Alextejthompson'']] (''Ping me or leave a message on my [[User talk:Alextejthompson|talk page]]'') 17:49, 21 September 2026 (UTC)
== Pages created by [[User:Sisterian]] ==
I have checked with AI checkers (GPTZero, ZeroGPT) and they claim that these pages have been made with the use of GenAI. I do not know whether this is correct or not; because yes, AI checkers can and do make mistakes. I have tried reaching out to the person via talk page, to no response. I am asking for input just to see what the future of these pages are. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 12:00, 22 September 2026 (UTC)
:Thank you for flagging this @[[User:TechVindicator|TechVindicator]]. I have looked at these pages personally, and there is fairly conclusive evidence that this user has been using genAI/LLMs for their contributions. I have warned them accordingly. Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 20:50, 22 September 2026 (UTC)
== I'm in the process of creating a separate page describing the removal of admin permissions ==
As the section title says, please see [[User:Codename Noreste/sandbox]] and feel free to make any adjustments. We might consider moving this to [[Wikibooks:Administrators/De-adminship]] someday. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 18:05, 24 September 2026 (UTC)
== Your feedback wanted: Remove ''(Language link added:) and similar'' edits from Special:RecentChanges ==
''(Apologies for posting in English. You can help by translating it)''
Hello, I’m Danny from [[:en:w:Wikimedia_Deutschland|Wikimedia Deutschland’s]] [[m:Wikidata_For_Wikimedia_Projects|Wikidata For Wikimedia Projects]] team.<br/>
We have been investigating and examining how Wikidata’s use in the [[Special:RecentChanges]] and [[Special:Watchlist]] pages can be made to be more useful, or less ‘noisy’ (fewer edits that have little value to the reader).
We are currently exploring to make a change in the volume and the type of Wikidata edits that appear in these pages, and '''we need your feedback''' to help us ensure this is a positive change for the Wikis and won’t disrupt your workflows.<br/>
Language links are also known as sitelinks or interlanguage links and describe when a Wikidata item is connected to a Wiki, adding it to the language dropdown tool for other connected Wikis.
[[File:Types of Lang Link changes.png|x350px|frame|A variety of "Language Link" edits as seen in the Recent Changes feed]]
The request for feedback is whether you support the removal of these language link edits from the Recent Changes and Watchlist feed, or would you oppose such a change and if so, why?
Please share you thoughts on the dedicated '''[[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|metawiki Talk page]]'''.
Further information about this change: [[m:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|m:Wikidata_For_Wikimedia_Projects/Hide_Language_Link_edits]]
Thank you for any participation or feedback you give, -- [[m:User:Danny_Benjafield_(WMDE)|User:Danny Benjafield (WMDE)]] 11:46, 25 September 2026 (UTC)
<!-- Message sent by User:Danny Benjafield (WMDE)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31080832 -->
== FlaggedRevs again ==
<div class="cd-moveMark">''Moved to [[Wikibooks:Reading room/Proposals#FlaggedRevs again]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 18:01, 1 October 2026 (UTC)''</div>
== Wikidata Sitelink changes in Recent Changes and Watchlist ==
''(Apologies for cross-posting in English, translating it will help spread the message)''
Editors on group 1 wikis, including Wikiquote, Wikibooks, Wikiversity, Wikivoyage, and Wikisource, will no longer see notifications on [[Special:RecentChanges|Recent Changes]] and [[Special:Watchlist|Watchlist]] when a link to ''another'' language version of a page is added, removed, or changed in its Wikidata item. This change will begin on '''October 5 at 07:00 UTC''' as a two-week trial to reduce high-volume, low-value notifications and make higher-value changes easier to identify. Editors who rely on these notifications should be aware of the change and can share feedback or concerns on the [[m:Wikidata For Wikimedia Projects/Clearer Wikidata Edit Summaries/Hide Language Link edits|project]] or [[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|talk page]].<br/>Please reach out if you have any questions, thank you! -- [[User:Danny_Benjafield_(WMDE)|Danny Benjafield (WMDE)]] ([[User_talk:Danny_Benjafield_(WMDE)|talk]]) sent via [[User:MediaWiki message delivery|MediaWiki message delivery]] ([[User talk:MediaWiki message delivery|discuss]] • [[Special:Contributions/MediaWiki message delivery|contribs]]) 12:42, 1 October 2026 (UTC)
<!-- Message sent by User:Danny Benjafield (WMDE)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31106967 -->
== Approved Revs extension ==
If we were to have this extension, we should only limit this to the Wikijunior namespace, since we will eventually stop using FlaggedRevs, unless if we want Approved Revs to work in another namespace.
Remember, this is not a vote, but an overall discussion. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 01:17, 11 October 2026 (UTC)
omxkdtkifel7dk06wfsz66a7d1fmz8f
4675844
4675839
2026-10-13T14:03:28Z
Codename Noreste
3441010
/* Feedback on Wikibooks redirect */ reply ([[mw:c:Special:MyLanguage/User:JWBTH/CD|CD]])
4675844
wikitext
text/x-wiki
__NEWSECTIONLINK__ {{Discussion Rooms}} {{Shortcut|WB:CHAT|WB:RR/G|WB:GENERAL}} {{TOC left|limit=3}}
{{User:MiszaBot/config
|archive = Wikibooks:Reading room/Archives/%(year)d/%(monthname)s
|algo = old(60d)
|counter = 1
|minthreadstoarchive = 1
|minthreadsleft = 1
|key = 7a0ac23cf8049e4d9ff70cabb5649d1a
}}
Welcome to the '''General reading room'''. On this page, Wikibookians are free to talk about the Wikibooks project in general. For proposals for improving Wikibooks, see the [[../Proposals/]] reading room.
{{clear}}
[[Category:Reading room]]
== Call for administrators ==
Any experienced editor who has a good understanding of Wikibooks' policies should consider applying for administrator permissions at [[Wikibooks:Requests for permissions]]. Thank you. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] ([[User talk:Codename Noreste|discuss]] • [[Special:Contributions/Codename Noreste|contribs]]) 22:10, 5 August 2026 (UTC)
:Is there a page here that describes what admins do? I am curious because I checked [https://en.wikibooks.org/wiki/Special:ListUsers?username=&group=sysop&wpsubmit=&wpFormIdentifier=mw-listusers-form&limit=50 List of admins] and I see that there are already quite a few admins here and wonder which areas have a shortage.
:Just curious. [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 00:56, 16 September 2026 (UTC)
::[[Wikibooks:Administrators]]. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 01:09, 16 September 2026 (UTC)
== August 2026 Wikimedia Café meetups regarding [https://meta.wikimedia.org/wiki/Next_25 Next 25] ==
<div class="border-box" style="background-color: var(--background-color-warning-subtle, #f8eaba); max-width: 875px; padding: 5px; border: 1px solid black; margin: 5px; color: var(--clr-dark)">
<div class="box" style="float:left; padding-top: 10px; padding-right: 10px; padding-left: 10px; padding-bottom: 10px;">[[File:Wikimedia Café logo in plain SVG format.svg|60px|alt=The logo for the Wikimedia Café]]</div>
Hello! There will be two '''[https://meta.wikimedia.org/wiki/Wikimedia_Caf%C3%A9 Wikimedia Café]''' discussion opportunities in August. Both sessions will focus on [https://meta.wikimedia.org/wiki/Next_25 the Next 25 initiative], including [https://meta.wikimedia.org/wiki/Next_25/A_proposal_to_frame_Next_25 framing the initiative]. Participants may attend either or both Café sessions.
#'''29 August 2026 15:00 UTC''' ([https://zonestamp.toolforge.org/1788015600 timestamp converter]), at a time friendly to the Americas, Africa, and Europe
#'''30 August 2026 03:00 UTC''' ([https://zonestamp.toolforge.org/1788058800 timestamp converter]), at a time friendly to Asia and the Pacific
Please see the [https://meta.wikimedia.org/wiki/Wikimedia_Caf%C3%A9 Café] page for more information, including [https://meta.wikimedia.org/wiki/Wikimedia_Caf%C3%A9#Agenda._This_will_be_an_approximately_1_hour_Caf%C3%A9_session agenda details] and [https://meta.wikimedia.org/wiki/Wikimedia_Caf%C3%A9#How_to_attend_the_session how to register]!
To subscribe or unsubscribe for Café notices on your talk page please [https://meta.wikimedia.org/wiki/Global_message_delivery/Targets/Wikimedia_Caf%C3%A9 go here].
<br />
[[File:Buntstifte Eberhard Faber crop 64h.jpg|860px|alt=cropped image of colored pencils]]</div>
<span style="white-space:nowrap;">[[User:Pine|<span style="color:#01796f; text-shadow:#00BFFF 0 0 1.0em">༄ᨒ𖠰 Pine</span>]] [[User talk:Pine|<span style="color:DeepSkyBlue">(<b style="color:#FFDF00;text-shadow:#FFDF00 0 0 1.0em">✉</b>)</span>]]</span> 01:32, 17 August 2026 (UTC)
== Wikibooks project is not defined by goal ==
If it is for texbooks why is it called Wikibooks? It should be called Wikitextbooks! If it is for textbooks why does it contain cookbooks? For textbooks it's not supposed to have a [[Wikibooks:Featured books]]. [[User:Vivairan2|Vivairan2]] ([[User talk:Vivairan2|discuss]] • [[Special:Contributions/Vivairan2|contribs]]) 09:20, 1 September 2026 (UTC)
:It's "textbooks" broadly construed: guides, manuals, how-tos, etc. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 11:15, 1 September 2026 (UTC)
::So we should change "Wikibooks:Featured books" to "Wikibooks:Featured texts". [[User:Vivairan2|Vivairan2]] ([[User talk:Vivairan2|discuss]] • [[Special:Contributions/Vivairan2|contribs]]) 11:17, 1 September 2026 (UTC)
:::I disagree and even if I agreed, it would be priority #49,389. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 11:20, 1 September 2026 (UTC)
::::It's according to community consensus that says this website contains textbooks not books. [[User:Vivairan2|Vivairan2]] ([[User talk:Vivairan2|discuss]] • [[Special:Contributions/Vivairan2|contribs]]) 11:23, 1 September 2026 (UTC)
:::::"[[wb:WIW|Simply, Wikibooks is a collection of open-content textbooks.]]" [[User:Vivairan2|Vivairan2]] ([[User talk:Vivairan2|discuss]] • [[Special:Contributions/Vivairan2|contribs]]) 11:26, 1 September 2026 (UTC)
:Most textbooks are made by collaboration of some authors, co-authors and editors. Wikibooks help pages and guidelines remain silent when it comes to stages of writing a new texbooks. Even [[Using Wikibooks]] is not complete emough for enthusiasts. --[[User:Vivairan2|Vivairan2]] ([[User talk:Vivairan2|discuss]] • [[Special:Contributions/Vivairan2|contribs]]) 18:13, 3 September 2026 (UTC)
:@[[User:Vivairan2|Vivairan2]], In my opinion this is a good question. I wish more users would chime in. [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 16:10, 19 September 2026 (UTC)
== Wishlist 2027, invitation to share feedback ==
Hi, I’m [[m:User:SPerry-WMF|Sonja]] and I lead some of the [[mw:Contributors|teams]] at the Foundation who will be responsible for picking up wish work under the new wishlist process.
As you may know, the [[m:Community_Wishlist|Community Wishlist]] started out as an annual process through which Wikimedia contributors submit and vote on technical improvements they would like the Wikimedia Foundation to work on. The main goal of it is and has been to improve the editing experience by making changes and features the community asks for specifically.
In recent years, the process behind the wishlist has changed, and we’ve heard from many of you that it no longer meets many community members’ needs. So now, the Foundation is designing a new process with the community to improve how wishes are triaged, voted on, and prioritized in a way that is transparent, balanced across project families and language editions, and takes into account what the Foundation can deliver.
I would like to get community input specifically on these three stages of the Wishlist process:
* The [[m:Special:MyLanguage/Community_Wishlist/Community_Wishlist_2027#triage|'''triage stage''']], meaning how wishes are fleshed out, organized and filtered prior to voting
** We recommend to have a working group, including volunteers from various wikis and Wikimedia Foundation staff to work through this together
* The [[m:Special:MyLanguage/Community_Wishlist/Community_Wishlist_2027#vote|'''voting stage''']], including who may vote and how votes are structured
* The [[m:Special:MyLanguage/Community_Wishlist/Community_Wishlist_2027#postvote|'''post-vote stage''']], including how to bring equity into what work is prioritized
** One way to do this is to rank wishes within 3 categories: Large Wikipedias or covering all wikis, small and medium-sized Wikipedias, and '''sister projects''', so that top-voted wishes from smaller projects also get attention
This message is an abstract of the full proposed process. As you [[m:Special:MyLanguage/Community_Wishlist/Community_Wishlist_2027|read the proposed ideas on Meta]] (available in your language), please speak up about whether you think this will work well or if there are ways to make it stronger.
Regarding the timeline, this consultation is open for two weeks. You can post your feedback on Meta (in your preferred language) or in response below.
For this year’s cycle, [[m:Special:MyLanguage/Community_Wishlist/Community_Wishlist_2027#timeline|we plan]] to have the wish submission period in late October/early November and the triage process completed by late November. To respect the end-of-year holiday season, voting would happen in early to mid January. This first voting cycle is meant as a first step to try out a new process, and there will be more opportunities to provide feedback along the way, so that we can figure out the best process for future years together.
[[oldwikisource:M:User:SPerry-WMF|SPerry-WMF]], delivered by [[User:Trizek (WMF)|Trizek (WMF)]] ([[User talk:Trizek (WMF)|discuss]] • [[Special:Contributions/Trizek (WMF)|contribs]]) 13:52, 1 September 2026 (UTC)
:Thank you to everyone who engaged in the discussion around [[m:Talk:Community_Wishlist/Community_Wishlist_2027|the proposal from August 26]]. We've processed your feedback and [https://meta.wikimedia.org/w/index.php?title=Community_Wishlist/Community_Wishlist_2027&diff=prev&oldid=31041090 made changes] accordingly. Note that we weren’t able to implement all of it for this cycle, mostly for logistical reasons, but this is merely meant to be a first step and we will continue to improve this process with you all before we run through the next cycle. We plan to use [[m:Community_Wishlist/Community_Wishlist_2027#Updated_Community_Wishlist_Process_2027/2028|this updated version]] for the Wishlist 2027, and we look forward to hearing from you all during the submission and voting periods.
:[[:M:User:SPerry-WMF|SPerry-WMF]], delivered by [[User:Trizek (WMF)|Trizek (WMF)]] ([[User talk:Trizek (WMF)|discuss]] • [[Special:Contributions/Trizek (WMF)|contribs]]) 14:49, 17 September 2026 (UTC)
::@[[User:SPerry-WMF|User:SPerry-WMF]],@[[User:Trizek (WMF)|Trizek (WMF)]]: Thank you for posting info regarding the wishlist to the English Wikibooks. I am sure there are many new users here who can benefit.
::I used to participate in those discussions years ago and I know a lot of effort goes into making discussions useful not only for users of wikipedia, but also for the many language versions of the smaller wikimedia projects such as Wikibooks. [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 16:28, 19 September 2026 (UTC)
== How Do I Get My Book On A Shelf? ==
Help, I don't know how shelves work. I don't know how to put my book on a shelf. Can anyone help?
The book is called''' Art And AI''' [[User:3MMPEYTON|3MMPEYTON]] ([[User talk:3MMPEYTON|discuss]] • [[Special:Contributions/3MMPEYTON|contribs]]) 23:00, 8 September 2026 (UTC)
: Which shelf are you referring? [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:45, 10 September 2026 (UTC)
== Who is allowed to delete pages here? ==
On Aug 14, 2026 a user by the name of Max deleted a page I created in my user space. I don't see max in the list of admins here. Do they have the right to delete pages? Is there any documentation here I can consult?
Thanks in advance, [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 22:38, 15 September 2026 (UTC)
:We have local admins who have the technical ability to delete pages and virtually all material deleted here would be done by us (I'm one of them). A fairly small amount of users have global rights across all Wikimedia Foundation wikis and they will very rarely make deletions (e.g. if there are some kind of legal implications to material). [[User:Ottawahitech/American politics]] was deleted by [[User:Max]], who has [[Special:UserRights/Max|no special rights here]] but is one of the [[:m:Global sysops|global sysops]] I mentioned earlier. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 22:55, 15 September 2026 (UTC)
: Probably unrelated to the above, but Ottawahitech should do that with their account, unless if they are blocked. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 23:33, 15 September 2026 (UTC)
::Agreed and [[User:Ottawahitech]] is not blocked here, so no idea why he's using a temp account. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 23:43, 15 September 2026 (UTC)
:::There may be many reasons registered users are "editing" without logging in. Is it possible that they want to go about peacefully without attracting too much attention? [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 15:01, 16 September 2026 (UTC)
:::: We neither have a policy nor a guideline about this, probably. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 19:12, 20 September 2026 (UTC)
::::Notwithstanding a claim that the temp account is actually User:Ottawahitech, we have no idea that they are the same person. If the temp account is the same person, and they want to have a user space page, they can create temp account ones. The registered user account pages are intended for that registered user account and not as a dumping ground for anyone to create pages. [[User:MarcGarver|MarcGarver]] ([[User talk:MarcGarver|discuss]] • [[Special:Contributions/MarcGarver|contribs]]) 08:29, 13 October 2026 (UTC)
== Assistance to get page reviewed ==
My page is a translation page: [[Baiyi Zhuan]]
It is a single page, it is translated according to my own ability and familiarity with the language with a disclosure on external tools. I would like it to get reviewed if possible as I do not have the rights. [[User:Taitesena|Taitesena]] ([[User talk:Taitesena|discuss]] • [[Special:Contributions/Taitesena|contribs]]) 11:19, 18 September 2026 (UTC)
== Translation of books ==
Hello,
I would like to translate books from other Wikibooks into English. Are there any guidelines regarding how to do this? [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 00:34, 20 September 2026 (UTC)
: This has yet to be expanded, but you might want to take a look at [[Wikibooks:Content translation]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 19:13, 20 September 2026 (UTC)
== Feedback on Wikibooks redirect ==
I would like your feedback on my proposal to make [[Wikibooks:Username|this page]] redirect to [[Using Wikibooks/Setting Up A User Account#Choosing a Username|this page]]? I would do it myself, but it is not possible due to the fact that [[Wikibooks:Username]] can only be made by admins. This is because [[Wikibooks:Username policy]] also links to [[Using Wikibooks/Setting Up A User Account#Choosing a Username|this page]]. Regards, [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 04:37, 21 September 2026 (UTC)
:{{support}} ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 00:00, 22 September 2026 (UTC)
:This seems like a good idea to me. [[User:Alextejthompson|''Alextejthompson'']] (''Ping me or leave a message on my [[User talk:Alextejthompson|talk page]]'') 17:49, 21 September 2026 (UTC)
: {{done}}, I restored the redirect per consensus here. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:03, 13 October 2026 (UTC)
== Pages created by [[User:Sisterian]] ==
I have checked with AI checkers (GPTZero, ZeroGPT) and they claim that these pages have been made with the use of GenAI. I do not know whether this is correct or not; because yes, AI checkers can and do make mistakes. I have tried reaching out to the person via talk page, to no response. I am asking for input just to see what the future of these pages are. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 12:00, 22 September 2026 (UTC)
:Thank you for flagging this @[[User:TechVindicator|TechVindicator]]. I have looked at these pages personally, and there is fairly conclusive evidence that this user has been using genAI/LLMs for their contributions. I have warned them accordingly. Cheers —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 20:50, 22 September 2026 (UTC)
== I'm in the process of creating a separate page describing the removal of admin permissions ==
As the section title says, please see [[User:Codename Noreste/sandbox]] and feel free to make any adjustments. We might consider moving this to [[Wikibooks:Administrators/De-adminship]] someday. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 18:05, 24 September 2026 (UTC)
== Your feedback wanted: Remove ''(Language link added:) and similar'' edits from Special:RecentChanges ==
''(Apologies for posting in English. You can help by translating it)''
Hello, I’m Danny from [[:en:w:Wikimedia_Deutschland|Wikimedia Deutschland’s]] [[m:Wikidata_For_Wikimedia_Projects|Wikidata For Wikimedia Projects]] team.<br/>
We have been investigating and examining how Wikidata’s use in the [[Special:RecentChanges]] and [[Special:Watchlist]] pages can be made to be more useful, or less ‘noisy’ (fewer edits that have little value to the reader).
We are currently exploring to make a change in the volume and the type of Wikidata edits that appear in these pages, and '''we need your feedback''' to help us ensure this is a positive change for the Wikis and won’t disrupt your workflows.<br/>
Language links are also known as sitelinks or interlanguage links and describe when a Wikidata item is connected to a Wiki, adding it to the language dropdown tool for other connected Wikis.
[[File:Types of Lang Link changes.png|x350px|frame|A variety of "Language Link" edits as seen in the Recent Changes feed]]
The request for feedback is whether you support the removal of these language link edits from the Recent Changes and Watchlist feed, or would you oppose such a change and if so, why?
Please share you thoughts on the dedicated '''[[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|metawiki Talk page]]'''.
Further information about this change: [[m:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|m:Wikidata_For_Wikimedia_Projects/Hide_Language_Link_edits]]
Thank you for any participation or feedback you give, -- [[m:User:Danny_Benjafield_(WMDE)|User:Danny Benjafield (WMDE)]] 11:46, 25 September 2026 (UTC)
<!-- Message sent by User:Danny Benjafield (WMDE)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31080832 -->
== FlaggedRevs again ==
<div class="cd-moveMark">''Moved to [[Wikibooks:Reading room/Proposals#FlaggedRevs again]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 18:01, 1 October 2026 (UTC)''</div>
== Wikidata Sitelink changes in Recent Changes and Watchlist ==
''(Apologies for cross-posting in English, translating it will help spread the message)''
Editors on group 1 wikis, including Wikiquote, Wikibooks, Wikiversity, Wikivoyage, and Wikisource, will no longer see notifications on [[Special:RecentChanges|Recent Changes]] and [[Special:Watchlist|Watchlist]] when a link to ''another'' language version of a page is added, removed, or changed in its Wikidata item. This change will begin on '''October 5 at 07:00 UTC''' as a two-week trial to reduce high-volume, low-value notifications and make higher-value changes easier to identify. Editors who rely on these notifications should be aware of the change and can share feedback or concerns on the [[m:Wikidata For Wikimedia Projects/Clearer Wikidata Edit Summaries/Hide Language Link edits|project]] or [[m:Talk:Wikidata_For_Wikimedia_Projects/Clearer_Wikidata_Edit_Summaries/Hide_Language_Link_edits|talk page]].<br/>Please reach out if you have any questions, thank you! -- [[User:Danny_Benjafield_(WMDE)|Danny Benjafield (WMDE)]] ([[User_talk:Danny_Benjafield_(WMDE)|talk]]) sent via [[User:MediaWiki message delivery|MediaWiki message delivery]] ([[User talk:MediaWiki message delivery|discuss]] • [[Special:Contributions/MediaWiki message delivery|contribs]]) 12:42, 1 October 2026 (UTC)
<!-- Message sent by User:Danny Benjafield (WMDE)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Danny_Benjafield_(WMDE)/MassMessage_test_list&oldid=31106967 -->
== Approved Revs extension ==
If we were to have this extension, we should only limit this to the Wikijunior namespace, since we will eventually stop using FlaggedRevs, unless if we want Approved Revs to work in another namespace.
Remember, this is not a vote, but an overall discussion. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 01:17, 11 October 2026 (UTC)
4nsmjnkk9gc4dtkzws0vwp4h98h5n3v
Radiation Oncology/Randomized
0
125673
4675984
4322733
2026-10-14T06:04:42Z
Jcb
90773
4675984
wikitext
text/x-wiki
{{Radiation Oncology:TOC}}
==Meta-analysis and Systemic Review==
A
Acute Lymphoblastic Leukemia (ALL)
Acute Myeloid Leukemia (AML)
Adolescents, Cancer in
Adrenocortical Carcinoma
AIDS-Related Cancers
Kaposi Sarcoma (Soft Tissue Sarcoma)
AIDS-Related Lymphoma (Lymphoma)
Primary CNS Lymphoma (Lymphoma)
Anal Cancer
Appendix Cancer - see Gastrointestinal Neuroendocrine Tumors
Astrocytomas, Childhood (Brain Cancer)
Atypical Teratoid/Rhabdoid Tumor, Childhood, Central Nervous System (Brain Cancer)
B
Basal Cell Carcinoma of the Skin - see Skin Cancer
Bile Duct Cancer
Bladder Cancer
Bone Cancer (includes Ewing Sarcoma and Osteosarcoma and Malignant Fibrous Histiocytoma)
Brain Tumors
Breast Cancer
Bronchial Tumors (Lung Cancer)
Burkitt Lymphoma - see Non-Hodgkin Lymphoma
C
Carcinoma of Unknown Primary
Central Nervous System
Atypical Teratoid/Rhabdoid Tumor, Childhood (Brain Cancer)
Medulloblastoma and Other CNS Embryonal Tumors, Childhood (Brain Cancer)
Germ Cell Tumor, Childhood (Brain Cancer)
Primary CNS Lymphoma
Cervical Cancer
Childhood Cancers
Childhood Cardiac Tumors Treatment
Cancers of Childhood, Rare
Cholangiocarcinoma - see Bile Duct Cancer
Chordoma, Childhood (Bone Cancer)
Chronic Lymphocytic Leukemia (CLL)
Chronic Myelogenous Leukemia (CML)
Chronic Myeloproliferative Neoplasms
Colorectal Cancer
Craniopharyngioma, Childhood (Brain Cancer)
Cutaneous T-Cell Lymphoma - see Lymphoma (Mycosis Fungoides and Sézary Syndrome)
D
Ductal Carcinoma In Situ (DCIS) - see Breast Cancer
E
Embryonal Tumors, Medulloblastoma and Other Central Nervous System, Childhood (Brain Cancer)
Endometrial Cancer (Uterine Cancer)
Ependymoma, Childhood (Brain Cancer)
Esophageal Cancer
Esthesioneuroblastoma (Head and Neck Cancer)
Ewing Sarcoma (Bone Cancer)
Extracranial Germ Cell Tumor, Childhood
Extragonadal Germ Cell Tumor
Eye Cancer
Intraocular Melanoma
Retinoblastoma
F
Fallopian Tube Cancer
G
Gallbladder Cancer
Gastric (Stomach) Cancer
Gastrointestinal Neuroendocrine Tumors
Gastrointestinal Stromal Tumors (GIST) (Soft Tissue Sarcoma)
Germ Cell Tumors
Childhood Central Nervous System Germ Cell Tumors (Brain Cancer)
Childhood Extracranial Germ Cell Tumors
Extragonadal Germ Cell Tumors
Ovarian Germ Cell Tumors
Testicular Cancer
Gestational Trophoblastic Disease
H
Hairy Cell Leukemia
Head and Neck Cancer
Heart Tumors, Childhood
Hepatocellular (Liver) Cancer
Histiocytosis, Langerhans Cell
Hodgkin Lymphoma
Hypopharyngeal Cancer (Head and Neck Cancer)
I
Intraocular Melanoma
Islet Cell Tumors, Pancreatic Neuroendocrine Tumors
K
Kaposi Sarcoma (Soft Tissue Sarcoma)
Kidney (Renal Cell) Cancer
L
Langerhans Cell Histiocytosis
Laryngeal Cancer (Head and Neck Cancer)
Leukemia
Lip and Oral Cavity Cancer (Head and Neck Cancer)
Liver Cancer
Lung Cancer (Non-Small Cell, Small Cell, Pleuropulmonary Blastoma, Pulmonary Inflammatory Myofibroblastic Tumor, and Tracheobronchial Tumor)
Lymphoma
M
Male Breast Cancer
Melanoma
Melanoma, Intraocular (Eye)
Merkel Cell Carcinoma (Skin Cancer)
Mesothelioma, Malignant
Metastatic Cancer
Metastatic Squamous Neck Cancer with Occult Primary (Head and Neck Cancer)
Midline Tract Carcinoma With NUT Gene Changes
Mouth Cancer (Head and Neck Cancer)
Multiple Endocrine Neoplasia Syndromes
Multiple Myeloma/Plasma Cell Neoplasms
Mycosis Fungoides (Lymphoma)
Myelodysplastic Syndromes, Myelodysplastic/Myeloproliferative Neoplasms
Myelogenous Leukemia, Chronic (CML)
Myeloid Leukemia, Acute (AML)
Myeloproliferative Neoplasms, Chronic
N
Nasal Cavity and Paranasal Sinus Cancer (Head and Neck Cancer)
Nasopharyngeal Cancer (Head and Neck Cancer)
Neuroblastoma
Neuroendocrine Tumors (Gastrointestinal)
Non-Hodgkin Lymphoma
Non-Small Cell Lung Cancer
O
Oral Cancer, Lip and Oral Cavity Cancer and Oropharyngeal Cancer (Head and Neck Cancer)
Osteosarcoma and Undifferentiated Pleomorphic Sarcoma of Bone Treatment
Ovarian Cancer
P
Pancreatic Cancer
Pancreatic Neuroendocrine Tumors (Islet Cell Tumors)
Papillomatosis (Childhood Laryngeal)
Paraganglioma
Paranasal Sinus and Nasal Cavity Cancer (Head and Neck Cancer)
Parathyroid Cancer
Penile Cancer
Pharyngeal Cancer (Head and Neck Cancer)
Pheochromocytoma
Pituitary Tumor
Plasma Cell Neoplasm/Multiple Myeloma
Pleuropulmonary Blastoma (Lung Cancer)
Pregnancy and Breast Cancer
Primary Central Nervous System (CNS) Lymphoma
Primary Peritoneal Cancer
Prostate Cancer
Pulmonary Inflammatory Myofibroblastic Tumor (Lung Cancer)
R
Rare Cancers of Childhood
Rectal Cancer
Recurrent Cancer
Renal Cell (Kidney) Cancer
Retinoblastoma
Rhabdomyosarcoma, Childhood (Soft Tissue Sarcoma)
S
Salivary Gland Cancer (Head and Neck Cancer)
Sarcoma
Childhood Rhabdomyosarcoma (Soft Tissue Sarcoma)
Childhood Vascular Tumors (Soft Tissue Sarcoma)
Ewing Sarcoma (Bone Cancer)
Kaposi Sarcoma (Soft Tissue Sarcoma)
Osteosarcoma (Bone Cancer)
Soft Tissue Sarcoma
Uterine Sarcoma
Sézary Syndrome (Lymphoma)
Skin Cancer
Small Cell Lung Cancer
Small Intestine Cancer
Soft Tissue Sarcoma
Squamous Cell Carcinoma of the Skin - see Skin Cancer
Squamous Neck Cancer with Occult Primary, Metastatic (Head and Neck Cancer)
Stomach (Gastric) Cancer
T
T-Cell Lymphoma, Cutaneous - see Lymphoma (Mycosis Fungoides and Sèzary Syndrome)
Testicular Cancer
Throat Cancer (Head and Neck Cancer)
Nasopharyngeal Cancer
Oropharyngeal Cancer
Hypopharyngeal Cancer
Thymoma and Thymic Carcinoma
Thyroid Cancer
Tracheobronchial Tumors (Lung Cancer)
Transitional Cell Cancer of the Renal Pelvis and Ureter (Kidney (Renal Cell) Cancer)
U
Unknown Primary, Carcinoma of
Ureter and Renal Pelvis, Transitional Cell Cancer (Kidney (Renal Cell) Cancer
Urethral Cancer
Uterine Cancer, Endometrial
Uterine Sarcoma
V
Vaginal Cancer
Vascular Tumors (Soft Tissue Sarcoma)
Vulvar Cancer
W
Wilms Tumor and Other Childhood Kidney Tumors
Y
Young Adults, Cancer in
== Randomized Evidence ==
(In the process of being crosslinked)
*[[Radiation Oncology/Anal canal/Randomized|Anal canal]]
*[[Radiation Oncology/Benign/Randomized|Benign Diseases]]
*[[Radiation Oncology/Bladder/Randomized|Bladder]]
*[[Radiation Oncology/Palliation/Brain Metastases/Randomized|Brain Metastases]]
*[[Radiation Oncology/Breast/Randomized|Breast]]
*[[Radiation Oncology/Cervix/Randomized|Cervix]]
*[[Radiation Oncology/Bile duct/Randomized|Cholangiocarcinoma]]
*[[Radiation Oncology/Colon/Randomized|Colon]]
*[[Radiation Oncology/Endometrium/Randomized|Endometrial]]
*[[Radiation Oncology/Epilepsy|Epilepsy]]
*[[Radiation Oncology/Esophagus/Randomized|Esophagus]]
*[[Radiation Oncology/Stomach/Randomized|Gastric]]
*[[Radiation Oncology/CNS/Glioma/Randomized|Gliomas]]
*[[Radiation Oncology/Head & Neck/Randomized|Head & Neck]]
*[[Radiation Oncology/Hodgkin/Randomized|Hodgkin's Disease]]
*[[Radiation Oncology/Heel Spurs/Randomized|Heel Spurs]]
*[[Radiation Oncology/Kaposi's sarcoma/Randomized|Kaposi's Sarcoma]]
*[[Radiation Oncology/Lung/NSCLC/Randomized|Lung, NSCLC]]
*[[Radiation Oncology/Lung/SCLC/Randomized|Lung, SCLC]]
*[[Radiation Oncology/NHL/Randomized|Lymphoma, Non-Hodgkin's]]
*[[Radiation Oncology/Medulloblastoma/Randomized|Medulloblastoma]]
*[[Radiation Oncology/Lung/Mesothelioma/Randomized|Mesothelioma]]
*[[Radiation Oncology/Melanoma/Randomized|Melanoma, Cutaneous]]
*[[Radiation Oncology/Eye/Ocular melanoma/Randomized|Melanoma, Ocular]]
*[[Radiation Oncology/Pancreas/Randomized|Pancreas]]
*[[Radiation Oncology/Prostate/Randomized|Prostate]]
*[[Radiation Oncology/Rectum/Randomized|Rectum]]
*[[Radiation Oncology/Sarcoma/Randomized|Sarcoma]]
*[[Radiation Oncology/Skin/Randomized|Skin Non-melanoma]]
*[[Radiation Oncology/Palliation/Spinal Cord Compression/Randomized|Spinal Cord Compression]]
*[[Radiation Oncology/SVC Syndrome/Randomized|Superior Vena Cava Syndrome]]
*[[Radiation Oncology/Testis/NSGCT/Randomized|Testis, NSGCT]]
*[[Radiation Oncology/Thymoma/Randomized|Thymoma]]
*[[Radiation Oncology/Benign/Vascular Brachytherapy/Randomized|Vascular Brachytherapy]]
*[[Radiation Oncology/Nephroblastoma/Randomized|Wilms' Tumor (Nephroblastoma)]]
*[[Radiation Oncology/Hyperthermia/Randomized|Hyperthermia]]
*[[Radiation Oncology/Supportive care/Randomized|Supportive Care]]
*[[Radiation Oncology/Randomized/Technology|RT Technology]]
*[[Radiation Oncology/Randomized/Protons|Proton Therapy]]
== Literature Review ==
*'''Kentucky; 2009''' {{PMID|19111269}} -- "Randomized prospective trials of innovative radiotherapy technology are necessary." (Halperin EC, J Am Coll Radiol. 2009 Jan;6(1):33-7.)
**"It is possible to identify innovations that should be required to meet the standard of proof of a benefit in a randomized prospective clinical trial before being introduced into widespread clinical practice."
*'''NCI Canada; 2008''' (1975–2004) {{PMID|18955452}} -- "Evolution of the Randomized Controlled Trial in Oncology Over Three Decades." (Booth CM, J Clin Oncol. 2008 Oct 27. [Epub ahead of print])
**321 reports evaluating RCT in systemic therapy for breast, CRC, and NSCLC reviewed.
**Outcome: Number and size of RCT increased substantially. For profit sponsorship increased substantially (4% to 57%, SS). Effect size remained stable, but authors have become more likely to strongly endorse experimental arm (SS). Endorsement of experimental arm strongly associated with industry sponsorship
*'''Wisconsin; 2008''' {{PMID|18237799}} -- "Randomized controlled trials in health technology assessment: Overkill or overdue?" (Bentzen SM, Radiother Oncol. 2008 Jan 29 [Epub ahead of print])
*'''Oxford; 2007''' {{PMID|17303884}} -- "When are randomised trials unnecessary? Picking signal from noise." (Glasziou P, BMJ. 2007 Feb 17;334(7589):349-51.)
*'''RTOG; 2005''' (1968–2002) {{PMID|15728168}} -- "Evaluation of new treatments in radiation oncology: are they better than standard treatments?" (Soares HP, JAMA. 2005 Feb 23;293(8):970-8.)
**Review of all completed Phase III RTOG trials. 57 trials, 12734 patients
**Outcome: survival OR for intervention arm over standard arm 1.01 (NS). Only 10% significantly better, 88% inconclusive
**Toxicity: treatment-related mortality intervention arm worse OR 1.76 over standard arm (SS)
**Conclusion: Results of individual trials cannot be predicted in advance
*'''COG; 2005''' (1955–1997) {{PMID|16299015}} -- "Are experimental treatments for cancer in children superior to established treatments? Observational study of randomised controlled trials by the Children's Oncology Group." (Kumar A, BMJ. 2005 Dec 3;331(7528):1295. Epub 2005 Nov 18.)
**Review of completed Phase III trials. 126 trials, 36567 patients
**Outcome: survival OR 0.96 (NS)
**Conclusion: New treatments in childhood cancer are as likely to be inferior as they are to be superior to standard treatments
{{BOOKCAT}}
6l2q1mwvaa26k2s3kxq5fmeqmz2k4cw
Radiation Oncology/Rectum/Randomized
0
140505
4675998
4100190
2026-10-14T09:32:45Z
Jcb
90773
4675998
wikitext
text/x-wiki
{{Radiation_Oncology:TOC}}
<big>'''Rectal Cancer Randomized Evidence'''</big>
<br>In process of being cross-linked...
==Surgical Technique==
*'''National Taiwan University''' (1997-1999) -- medial-to-lateral vs lateral-to-medial laparoscopic dissection
**Randomized. 67 patients, rectosigmoid cancer, single surgeon performing laparoscopic dissection. Arm 1) medial-to-lateral dissection vs Arm 2) lateral-to-medial dissection
**'''2003''' {{PMID|12616435}} -- "Comparison of medial-to-lateral versus traditional lateral-to-medial laparoscopic dissection sequences for resection of rectosigmoid cancers: randomized controlled clinical trial." (Liang JT, World J Surg. 2003 Feb;27(2):190-6.)
***Outcome: No difference in LN harvest, intraop complications, conversion rate, postop complications, or disability. Improved OR time, C-RP and ESR in medial group
***Conclusion: Medial-to-lateral dissection may be most appropriate for laparoscopic rectection of rectosigmoid cancers
==Neoadjuvant Therapy==
===TME Surgery +/- Neoadjuvant RT===
*'''Dutch'''
**Randomized. 1805 patients treated with 1) Preop RT 25/5 or 2) TME alone. If surgery-only patients had SM+ (<=1mm), mandatory post-op RT
**'''5-years; 2007''' {{PMID|17968156}} -- "The TME Trial After a Median Follow-up of 6 Years: Increased Local Control But No Survival Benefit in Irradiated Patients With Resectable Rectal Carcinoma." (Peeters KC, Ann Surg. 2007 Nov;246(5):693-701.). Median F/U 6.1 years
***Outcome: 5-year LR TME 11% vs. RT + TME 6% (SS); OS 63% vs. 64% (NS)
***Subgroup benefit: N+, tumors 5-10 cm from anal verge, negative radial margins
***Conclusion: Preop short-term RT improves local control; no effect on survival
===Preop Chemo-RT: Dose Intensification===
*'''ACCORD 12/0405-Prodige 2''' (2005-2008) -- Cap 45 vs Capox 50
**Randomized. 598 patients, resectable T3-T4 rectal adenoca, T2 tumors in anterior/lower rectum also included. Arm 1) RT 45/25 with concurrence capecitabine 800 mg/m2 BID (Cap 45) vs Arm 2) RT 50/25 with concurrence capecitabine 800 mg/m2 BID and oxaliplatin 50 mg/m2 QW (Capox 50). RT excluded external/common illiac, in Capox 50 group boost after 44 Gy. Primary endpoing ypCR to get quick answer, as follow up to FFCD 9203
**'''2010''' {{PMID|20194850}} -- "Comparison of two neoadjuvant chemoradiotherapy regimens for locally advanced rectal cancer: results of the phase III trial ACCORD 12/0405-Prodige 2." (Gerard JP, J Clin Oncol. 2010 Apr 1;28(10):1638-44. Epub 2010 Mar 1.)
***Outcome: ypCR Cap45 14% vs Capox 50 19% (NS). SM+ (0-2mm) 19% vs 10% (SS)
***Toxicity: Preop G3+ Cap 45 1% vs Capox 50 25% (SS). No difference in surgery (75%) or postop deaths (0.3%).
***Conclusion: Benefit of oxaliplatin not demonstrated. Suggest Cap 50 as the next regimen to test
==Intraoperative RT==
===TME Surgery with Lateral LND +/- Pelvic LN Sparing with IORT===
*'''Kyorin University; 2008''' (2000-2007) {{PMID|18172677}} -- "Intraoperative radiotherapy for oncological and function-preserving surgery in patients with advanced lower rectal cancer." (Masaki T, Langenbecks Arch Surg. 2008 Jan 3 [Epub ahead of print])
**Randomized. 41 patients with advanced lower rectal CA. Arm 1) TME + bilateral lateral LND + limited PANP vs. Arm 2) TME + bilateral lateral LND + complete PANP + IORT to preserved pelvic nerve plexuses
**Outcome: No difference in LR, DFS, OS. Improved time with indwelling catheter and voiding function
**Conclusion: Complete pelvic autonomic nerve preservation with IORT may be useful
==Preop vs Postop Therapy==
*'''MRC CR07 and NCIC C016''' (1998-2005) -- preop RT 25/5 vs. selective postop chemo-RT 45/25
**Randomized. 1350 patients, operable carcinoma of rectum, <15cm from anal verge, TME encouraged but not mandated (done in 92%). Arm 1) RT 25/5 vs. Arm 2) surgery + selective postop chemo-RT if SM+ (RT 45/25 + concurrent 5-FU and leucovorin). RT sacral promontory superiorly, 3–5 cm below the inferior tumor extent, 2–3 cm anterior to the sacral promontory, 1 cm posterior to the anterior sacrum, and 1 cm lateral to the most lateral aspect of the bony true pelvis. Primary outcome LR. In postop arm, SM+ was in 12% as trigger for postop chemo-RT vs 10% in preop group. Adjuvant chemo in 40% of preop arm and 45% of postop arm
**'''2009''' {{PMID|19269519}} -- "Preoperative radiotherapy versus selective postoperative chemoradiotherapy in patients with rectal cancer (MRC CR07 and NCIC-CTG C016): a multicentre, randomised trial." (Sebag-Montefiore D, Lancet. 2009 Mar 7;373(9666):811-20.) Median F/U 4 years
***Outcome: LR preop RT 4% vs. postop RT 11% (SS), DFS 77% vs. 71% (SS), no difference in OS. By SM status: SM+ 14% vs. 21% (NS), SM- 4% vs. 9% (SS). Upper 1/3 tumors lower LRR than lower 1/3, preop RT 1% vs. 5%, postop chemo-RT 6% vs. 10%
***Conclusion: Short-course RT more effective than selective postop chemo-RT
**Editorial ({{PMID|19269501}}): Preop RT appears to benefit both good-prognosis and bad-prognosis tumors, so need a good way to select, and patient preference likely to play a role. Nevertheless, short preop RT is an excellent option
*'''German Rectal Cancer Study''' CAO/ARO/AIO (1995-2002) -- preop chemo-RT vs. postop chemo-RT
**Randomized. 823 patients, clinical stage T3-4 or N+, inferior margin within 16cm from anal verge. Arm 1) ''post-op regimen:'' surgery (TME) -> chemo/RT (55.8 Gy) -> 4 cycles bolus 5-FU, or 2) ''pre-op regimen:'' chemo/RT (50.4 Gy) -> surgery (TME) -> 4 cycles bolus 5-FU. In both arms, chemo was 5-FU C.I. 1000 mg/m2/d on days 1-5, weeks 1+5.
**'''2004''' {{PMID|15496622}} [http://content.nejm.org/cgi/content/full/351/17/1731 Full text] "Preoperative versus postoperative chemoradiotherapy for rectal cancer." (Sauer R, N Engl J Med. 2004 Oct 21;351(17):1731-40.) Median F/U 3.8 years
***Outcome: 5-year OS preop 76% vs postop 74% (NS); 5-year DFS 68% vs. 65% (NS); LR 6% vs. 13% (SS); DM 36% vs. 38% (NS). Preop downstaging: pCR 8%, 25% (vs 40%) were Stage III/LN+. TNM Stage I disease found in 18% of post-op group (vs. 25% in pre-op).
***Toxicity: Fewer acute (27% vs 40%) and late toxicities (14% vs 24%) in preoperative-treatment group. Increased rate of sphincter-preserving surgery (39% vs 19%) in preoperative-treatment group.
***Conclusion: Preop chemo-RT improved local control and improved toxicity, but did not impact overall survival
**Critique (and clinical reality): only 54% of adjuvant patients vs. 92% of neoadjuvant patients received full RT dose
*'''NSABP R-03''' (1993-1999) -- Preop vs postop chemo-RT
**Randomized. ''Trial closed prematurely due to poor accrual''. 267/900 expected patients. Clinical T3-T4 or N+ rectal cancer. Arm 1) Preop chemo-RT 50.4/28 + 5-FU 500 mg/m2 and leucovorin 500 mg/m2 vs Arm 2) Postop chemo-RT (same as preop). Surgery APR, LAR, or local excision; TME not mandated. Both groups adjuvant 3 cycles of 5-FU/leucovorin
**'''2009''' {{PMID|19770376}} [http://jco.ascopubs.org/cgi/reprint/27/31/5124 Full text] — "Preoperative multimodality therapy improves disease-free survival in patients with carcinoma of the rectum: NSABP R-03." (Roh M et al. J Clin Oncol. 2009 Nov 1;27(31):5124-30. Epub 2009 Sep 21.)
***Outcome: 5-year DFS was improved for pre-op over post-op (64.7% v 53.4%, SS). Nonsignificant trend in 5-year OS (74.5% v 65.6%, p=0.065). No difference in locoregional recurrence, 11% in each group. pCR in 15%. Significant reduction in N+ (67% vs. 52%, SS)
***Toxicity: Grade 4 diarrhea preop 24% vs. postop 13%; Grade 5 toxicity 5% vs 3%
***Conclusion: Pre-op chemoradiotherapy, compared with post-op chemoradiotherapy, significantly improved DFS and showed a trend toward improved OS
==Induction chemo vs adjuvant chemo, with neoadjuvant chemo-RT-surgery==
*'''Grupo Cancer De Recto 3, Spain''' (2006-2007) -- Induction chemo vs adjuvant chemo, with chemo-RT -> surgery
**Randomized, Phase II. 108 patients, locally advanced rectal cancer, <12 cm from verge, LAR disease based on high-res MRI. Treated with chemo-RT followed by surgery. Randomized to Arm 1) Induction capecitabine 2000 mg/m2 and oxaliplatin 130 mg/m2 (CAPOX) x4 cycles vs Arm 2) Adjuvant CAPOX x4 cycles. Primary endpoint pCR
**'''2010''' {{PMID|20065174}} -- "Phase II, randomized study of concomitant chemoradiotherapy followed by surgery and adjuvant capecitabine plus oxaliplatin (CAPOX) compared with induction CAPOX followed by concomitant chemoradiotherapy and surgery in magnetic resonance imaging-defined, locally advanced rectal cancer: Grupo cancer de recto 3 study." (Fernandez-Martos C, J Clin Oncol. 2010 Feb 10;28(5):859-65. Epub 2010 Jan 11.)
***Outcome: pCR induction 13% vs adjuvant 14% (NS), no difference in downstaging, tumor regression, R0 resection.
***Toxicity: Higher during adjuvant arm. No difference during chemo-RT.
***Conclusion: No difference in outcomes, but less toxicity with induction chemo compared with adjuvant chemo
==Adjuvant RT vs Chemo-RT==
*'''NCCTG 79-47-51''' (1980-1986) -- postop RT vs postop chemo-RT
**Randomized. 204 patients, rectal CA T3-4 or N+, within 12 cm of anal verge. Arm 1) post-op RT vs. Arm 2) post-op chemo-RT. RT given 45/25 + 5.4/3 Gy boost to tumor bed and adjacent LN. Chemo bolus 5-FU bolus + semustine x1 month, then bolus 5-FU 500 mg/m2 concurrent with RT, then 2 months consolidative 5-FU/semustine. Major deviations 9%
**'''7-years; 1991''' {{PMID|1997835}} — "Effective surgical adjuvant therapy for high-risk rectal carcinoma." (Krook JE et al. N Engl J Med. 1991 Mar 14;324(11):709-15.). Median F/U 7 years
***Outcome: 5-year recurrence RT 63% vs. chemo-RT 41% (decreased by 34%, SS). LR 25% vs. 13% (decreased by 47%, SS), DM 46% vs. 29% (SS). 5-year OS ~40% vs. ~55% (decreased by 29%, SS). Reduction in death rate highly significant for LAR (52%), not significant for APR (10%)
***Toxicity: SBO 5%, median time-to-complication 10 months; overall severe late toxicity 7% (comparable between 45 and 50.4 Gy)
***Conclusion: Adjuvant chemo-RT superior to RT alone; confirms prior GITSG 7175 results
***Comment: CRT generally well tolerated, unlike GITSG GI-7175. Adjuvant chemo 1 month first, consolidation 2 months vs 1.5 years in GITSG. On the basis of this study and GITSG 7175, NIH consensus conference recommended chemo-RT as standard of care for T3-T4 or N+ patients
*'''GITSG GI-7175''' (1975-1980) -- surgery alone vs postop chemo vs postop RT vs postop chemo-RT
**Randomized, 4 arms. ''Terminated early due to significant benefit of chemo-RT arm''. 227/520 patients. Dukes B and C (T3-4 or N+), distal edge within 12 cm from anal verge. Only R0 resection allowed. Treated with 1) Surgery alone, 2) post-op Chemo (bolus IV 5-FU/M-CCNU), 3) post-op RT 40 or 48 Gy standard fraction, 4) post-op Chemo-RT 40 or 44 Gy standard fraction + 5-FU 500 mg/m2 followed by adjuvant 5-FU/M-CCNU as in chemo alone arm. RT given AP/PA, superior border L4/L5, inferior border included perineum; major deviations in 39%. Consolidative chemo given x1.5 years or until disease progression
**'''7-years, 1985''' {{PMID|2859523}}, 1985 — "Prolongation of the disease-free interval in surgically treated rectal carcinoma. Gastrointestinal Tumor Study Group." [No authors]. N Engl J Med. 1985 Jun 6;312(23):1465-72. Median F/U 6.7 years.
***Outcome: Recurrence surgery 55% vs. chemo 46% vs. RT 48% vs. chemo-RT 33% (SS). Benefit of chemo-RT (p=0.009) due to both RT (, better LRC p=0.06) and chemo (better DM p=0.06) components. Initial LRR overall 21%; by arm 24% vs. 27% vs. 20% vs. 11%; initial DM overall 25%. LR in perineum 21%, vagina/uterus 17%, anastomosis 12%, sacrum/coccyx 12%, bladder/prostate 12%. Actuarial OS 36% vs. 46% vs. 46% vs. 56% (p=0.07)
***Toxicity: Severe nonhematological chemo 15% vs. RT 16% vs. chemo-RT 35%
***Conclusion: Postoperative chemo-RT significantly better for disease-free survival, with trend to overall survival benefit
**'''8-years, 1986''' {{PMID|3773947}}, 1986 (No abstract) — "Survival after postoperative combination treatment of rectal cancer." Douglass HO et al. N Engl J Med. 1986 Nov 13;315(20):1294-5. Median F/U 7.8 years
***Outcome: No new recurrences. Now overall survival benefit for chemo-RT over surgery alone (SS)
***Conclusion: Postoperative chemo-RT improves overall survival over surgery alone in T3-4 or N+ patients
**'''GITSG overview, 1988''' {{PMID|3064191}}, 1988 — "Adjuvant postoperative radiotherapy and chemotherapy in rectal carcinoma: a review of the Gastrointestinal Tumor Study Group experience." Thomas PR et al. Radiother Oncol. 1988 Dec;13(4):245-52.
***Severe acute toxic side-effects, but late effects rare in arm 4. Three late deaths (2 enteritis in chemo-RT group, one acute leukemia in chemo group).
***Conclusions: Compared to surgery alone, postop Chemo-RT improved OS (45% v 27% @ 10yrs), prolonged Time-To-Recurrence, decreased Recurrence Rate (33% v 55%), and decreased LF Rate (10% v 25%).
**Critique: severely underpowered to show benefit, unequal randomization and not analyzed by intent to treat, semustine x1.5 years increases risk for leukemia
lco0k6j9t5j46zh5nxznmao8yrscsym
MediaWiki:Deletereason-dropdown
8
141232
4675854
4528507
2026-10-13T14:31:43Z
Codename Noreste
3441010
Using commas and removing periods. ([[:m:User:Max/MaxEdit.js|MaxEdit]])
4675854
wikitext
text/x-wiki
*Speedy deletion candidates
**[[WB:SPEEDY|Requested by only significant contributors or authors blanked page]]
**[[WB:SPEEDY|Requested by user in user space]]
**[[WB:NMC|Spam, vandalism, or nonsense]]
**[[WB:NMC|Test page]], please use the [[WB:SB|sandbox]] for experimenting with Wikibooks
**[[WB:NMC|Abandoned material with intent and no development]] after 7 days
**[[WB:NMC|Talk page with no corresponding content page]]
**[[WB:SPEEDY|Empty category]]
**[[WB:SPEEDY|Orphaned, broken or unnecessary redirect]]
**[[WB:SPEEDY|Other speedy deletion reasons]]
**Please request [[WB:RFU|undeletion]] instead of [[WB:SPEEDY|reposting deleted material]]
*Inclusion criteria
**[[WB:NOR|Original works of fiction and literature]] are outside project scope
**[[WB:NOR|Original research]] belongs at [[v:WV:WIW|Wikiversity]]
**Non-linguistic books on Wikibooks must be in the English language
**[[WB:DICT|Dictionaries and thesauruses]] belong at [[wikt:WT:WIN|Wiktionary]]
**[[WB:NOTWP|Encyclopedic]] articles belong at [[w:WP:WIW|Wikipedia]]
**[[WB:SOURCE|Source texts]] belong at [[s:WS:WIW|Wikisource]]
**[[WB:NEWS|News articles]] belong at [[n:WN:WWI|Wikinews]]
**[[WB:NOT|Travel guides]] belong at [[voy:WV:WIW|Wikivoyage]]
**Use a blog, forum, or personal website to share your [[WB:SOAP|personal opinions and thoughts]] instead
**[[WB:HOST|Wikibooks is not your personal web host or web space provider]]
*Policy related
** Consensus by community per [[Wikibooks:Requests for deletion/{{BOOKNAME}}|requests for deletion]]
** Use of [[WB:COPYVIO|copyrighted work without permission]], please read [[Foundation:Terms of Use|Terms of Use]]
** Biased interpretation of the facts, books must maintain a [[WB:NPOV|neutral point of view]]
** [[WB:ATTACK|Attack page]]
2i2rhr10yflk60cb84or9s4cgra4pai
Wikibooks:Reading room/Proposals
4
155682
4675845
4675796
2026-10-13T14:07:22Z
Codename Noreste
3441010
/* Disable (some) page creation by temporary accounts */ delete comment by [[User:~2026-55204-42|~2026-55204-42]] ([[mw:c:Special:MyLanguage/User:JWBTH/CD|CD]])
4675845
wikitext
text/x-wiki
__NEWSECTIONLINK__ {{Discussion Rooms}} {{Shortcut|WB:RFC|WB:PROPOSALS}} {{TOC left<!--|limit=2-->}}
Welcome to the '''Proposals reading room'''. On this page, Wikibookians are free to talk about suggestions for improving Wikibooks.
{{User:MiszaBot/config
|archive = Wikibooks:Reading room/Proposals/%(year)d/%(monthname)s
|algo = old(120d)
|counter = 1
|key = 1f2adc5eee951900b65c7b981b786191
|minthreadstoarchive = 1
|minthreadsleft = 1
}}
{{clear}}
<!--Take threads to archive below this line-->
<!--Add new threads to bottom of page-->
== New gadget to browse subpages ==
Hi all! I developed a gadget to easily browse subpages through a collapsible menu, that I think might be useful in Wikibooks. Here's a little demo video:
[[File:Subpages_gadget_demo.webm|frameless]]
To test it yourself, add the following to [[Special:MyPage/common.js|your common.js]]:
<syntaxhighlight lang="javascript">
mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-Subpages' );
</syntaxhighlight>
If you find it useful, I can enable it as a gadget to make it generally available from the preferences. Thoughts? Cheers! [[User:Sophivorus|Sophivorus]] ([[User talk:Sophivorus|discuss]] • [[Special:Contributions/Sophivorus|contribs]]) 16:02, 2 July 2026 (UTC)
:Wikibooks relies heavily on subpages, so this is a nice addition. Merci. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 16:43, 2 July 2026 (UTC)
:This could be extremely useful for books here!! I'll note, though, that it doesn't work quite right with the vector legacy skin (what I use). —[[User:Kittycataclysm|Kittycataclysm]] ([[User talk:Kittycataclysm|discuss]] • [[Special:Contributions/Kittycataclysm|contribs]]) 01:20, 3 July 2026 (UTC)
: @[[User:Sophivorus|Sophivorus]] I will be the one in charge installing this as a gadget since there is no objection, but what dependecies does this gadget need to use? You might also want to read Kittycataclysm's suggestion above. ''Muchos saludos''. [[User:Codename Noreste|<span style="color:#0024FF">Codename Noreste</span>]] ([[User talk:Codename Noreste|discuss]] • [[Special:Contributions/Codename Noreste|contribs]]) 23:08, 9 July 2026 (UTC)
::@[[User:Codename Noreste|Codename Noreste]] Hi! I just fixed the issue with Vector legacy and also for other skins. Regarding dependencies, this gadget requires <code>mediawiki.api</code> and <code>@wikimedia/codex</code>. If you want to take care of the installation, please do not copy-paste the source code, but rather load the global version using <code>mw.loader.load( '//www.mediawiki.org/w/load.php?modules=ext.gadget.Global-Subpages' );</code>, like other [[mw:Global gadgets|global gadgets]]. Thanks! [[User:Sophivorus|Sophivorus]] ([[User talk:Sophivorus|discuss]] • [[Special:Contributions/Sophivorus|contribs]]) 14:22, 22 July 2026 (UTC)
::: I put the code on the gadgets definition page @[[User:Sophivorus|Sophivorus]], but feel free to fix what I placed. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] ([[User talk:Codename Noreste|discuss]] • [[Special:Contributions/Codename Noreste|contribs]]) 21:45, 22 July 2026 (UTC)
== Breadcrumbs in the title ==
Hi! I think breadcrumbs would be more intuitive, compact and cleaner if they were integrated into the title rather than below it, like so:
<gallery>
Wikisource breadcrumbs proposal (before).png|Current breadcrumbs
Wikisource breadcrumbs proposal (after).png|Proposed breadcrumbs
</gallery>
What do you think? [[User:Sophivorus|Sophivorus]] ([[User talk:Sophivorus|discuss]] • [[Special:Contributions/Sophivorus|contribs]]) 16:02, 17 August 2026 (UTC)
:I appreciate the effort, but I don't see a big difference or that one would be more usable than another. ―[[User:Koavf|Justin (<span style="color:grey">ko'''a'''<span style="color:black">v</span>f</span>)]]<span style="color:red">❤[[User talk:Koavf|T]]☮[[Special:Contributions/Koavf|C]]☺[[Special:Emailuser/Koavf|M]]☯</span> 19:14, 17 August 2026 (UTC)
:I like proposal and I think it would be an improvement. Having the breadcrumbs twice, as in the current system, creates a redundant ui element. I also think the formatting around the forward slashes in the "new" version better conveys that they have specific technical meaning and are not part of the name of the page. --[[User:JCrue|JCrue]] ([[User talk:JCrue|discuss]] • [[Special:Contributions/JCrue|contribs]]) 14:52, 7 October 2026 (UTC)
== Approve [[Wikibooks:CheckUser]] as a local policy? ==
Some of the text was based off of the global CheckUser policy, but in this case, should we approve [[Wikibooks:CheckUser]] as a local policy? There is a special clause allowing stewards to perform checks even during non-emergency situations (as set in [[Wikibooks:Global rights policy]]). I have yet to include a part where users may request CU checks. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 21:55, 13 September 2026 (UTC)
:I'm somewhat just unsure on what the benefit of making this policy would be. Sure, there's strength in policy, of course. But this seems to be doing fine overall as an information page, no? It doesn't differ very much from the global CU policy, so I'm not sure that a page without any Wikibooks-specific information really benefits from policy status. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 00:22, 14 September 2026 (UTC)
:I would {{support}} this. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 00:26, 20 September 2026 (UTC)
== FlaggedRevs again ==
<div class="cd-moveMark">''Moved from [[Wikibooks:Reading room/General#FlaggedRevs again]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 18:01, 1 October 2026 (UTC)''</div>
Hi all. I already know there were various topics over the years about this subject, but I was considering for the project on whether we should remove this extension from this project, and go back to using MediaWiki's page patrol system.
Currently, there is a backlog of more than 3000 unreviewed edits (some going back as far as a few years ago); that’s why I started this discussion here.
{{collapse top}}
* <code>autoreview</code> and <code>editor</code> would be <code>autopatrolled</code> and <code>patroller</code>, respectively.
* <code>wgUseNPPatrol</code> and <code>wgUseFilePatrol</code> would be re-enabled for English Wikibooks.
* <code>autopatrol</code> and <code>patrol</code> would be re-assigned back to sysops and their respective user groups.
* <code>patroller</code> would also have <code>rollback</code> and <code>suppressredirect</code> and its rate limit untouched.
{{collapse bottom}}
Best, [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 12:56, 30 September 2026 (UTC)
:{{s}} the removal of FlaggedRevs. Inasmuch as the extension works at all, it works best when it is used selectively on projects like Wikipedia, for individual high-traffic pages with lots of watchers which are subject to vandalism or controversy. Wikibooks is not a good use case for this extension. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 15:51, 1 October 2026 (UTC)
:{{s}} I don't see any way that backlog ever gets cleared, frankly, and if it isn't going to be cleared, we might as well go to something easier, which is the normal page patrol system, which works well off of [[Special:NewPages]] already. [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 00:31, 3 October 2026 (UTC)
:{{neutral}} - Wikibooks is not a good use case for this extension, and with 3000 unreviewed edits with no progress at all, it does make sense to remove it. On the other hand, there could be a WikiProject to review each of these edits. For this reason, I am voting neutral [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 13:41, 3 October 2026 (UTC)
:: There was the outdated [[Wikibooks:New page patrol]] before this project used FlaggedRevs. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 19:22, 3 October 2026 (UTC)
:{{support}} the removal of FlaggedRevs from Wikibooks. It's a redundant extension that's not useful in this wiki. --[[User:Agusbou2015|Agusbou2015]] ([[User talk:Agusbou2015|discuss]] • [[Special:Contributions/Agusbou2015|contribs]]) 21:53, 3 October 2026 (UTC)
:{{Support}}. Several years ago I spent hundreds of hours trying to do the first review of every page. I managed to get all the root pages done but only got as far as "E" for the other pages. While I was doing this I stopped reviewing changes - and in that time over a 1,000 out of date pages were in the list. I concluded it was an impossible task unless lots of people joined in the work but that didn't happen and I doubt it ever will. I do think it has value for Wikijunior in showing the last reviewed page rather than the possibly offensively vandalised latest revision, but other than that it's a waste of time. At some point the extension will get fully deprecated and we'll be forced to stop using it anyway. [[User:MarcGarver|MarcGarver]] ([[User talk:MarcGarver|discuss]] • [[Special:Contributions/MarcGarver|contribs]]) 09:53, 6 October 2026 (UTC)
:Will <code>patroller</code> be granted automatically? [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 13:24, 6 October 2026 (UTC)
:: Unfortunately, no. Since we will stop using FlaggedRevs, the patroller user group will not be granted automatically and thus will have to be manually given out by administrators. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 13:46, 6 October 2026 (UTC)
:::@[[User:Codename Noreste|Codename Noreste]]: And are we planning on giving back the <code>patroller</code> right to existing reviewers? Or will they have to manually reapply? [[User:JJPMaster|JJP]]<sub>[[User talk:JJPMaster|Mas]]<sub>[[Special:Contributions/JJPMaster|ter]]</sub></sub> ([[wikt:she|she]]/[[wikt:they|they]]) 02:30, 8 October 2026 (UTC)
:::: I have a plan: any former reviewer who has been active recently in the past two years will have patroller rights. This will be done to reduce a huge amount of inactive former reviewers. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 12:26, 8 October 2026 (UTC)
::::Keep the name the same; just remove the reviewer right. After all, patrolling is a form of reviewing. [[User:Leaderboard|Leaderboard]] ([[User talk:Leaderboard|discuss]] • [[Special:Contributions/Leaderboard|contribs]]) 18:52, 8 October 2026 (UTC)
::::: Do we have to use the term {{tq|reviewing}} instead of {{tq|patrolling}}? [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 18:57, 8 October 2026 (UTC)
:::{{ping|Codename Noreste}} Is there a reason that we should not simply give the reviewer group the <code>patrol</code> right, and keep the auto-granting going? [[Wikibooks:Reviewers#Automatic criteria]] does not appear to be FlaggedRevs-specific, so auto-promotion should still be able to continue even without FlaggedRevs, and reviewers could simply become patrollers (in the technical sense). [[User:EggRoll97|EggRoll97]] ([[User talk:EggRoll97|discuss]] • [[Special:Contributions/EggRoll97|contribs]]) 07:55, 10 October 2026 (UTC)
:::: I believe that would require some additional code on InitialiseSettings.php, and as for <code>reviewer</code>, I'm not sure we should still use that user group term over <code>patroller</code> as per the point {{tq|Special groups on small wikis}} on [[m:Limits to configuration changes]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 13:58, 10 October 2026 (UTC)
: If you take a look at the extended content, I also included what I also proposed too. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 18:19, 6 October 2026 (UTC)
:{{comment}}. The [[mw:Extension:FlaggedRevs|FlaggedRevs extension]] is not recommended for production use, per Mediawiki. On this basis alone we should discontinue use of it. However, we haven't determined if page patrolling is the best replacement. There are [[mw:Content approval extensions|alternative extensions]] and the mediawiki page for FlaggedRevs specifically recommends [[mw:Extension:Approved Revs|'''Approved Revs extension''']]. We should determine which of page patrolling or these extensions is the most appropriate antivandalism tool first. (after all, according to [[Help:Tracking_changes#Reviewing_pages]], the purpose of FlaggedRevs is to be "our primary counter-vandalism tool"). --[[User:JCrue|JCrue]] ([[User talk:JCrue|discuss]] • [[Special:Contributions/JCrue|contribs]]) 14:48, 7 October 2026 (UTC)
:: Approved Revs would require significant testing and approval per [[mw:Writing an extension for deployment]]. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 16:35, 7 October 2026 (UTC)
== Disable (some) page creation by temporary accounts ==
Creating a new book, or adding a chapter to an existing book, is a significant action, and users performing this action should be available to discuss it. Additionally, in practice, most page creations by temp accounts are out of scope, if not outright vandalism. (See https://en.wikibooks.org/w/index.php?title=Special:Log&type=create for some examples.)
As such, I'd like to propose that the wiki require a registered account to create pages in any non-talk namespace. Temporary accounts will still be able to edit existing pages, or to create talk pages to start discussions. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 18:48, 1 October 2026 (UTC)
: From a technical point of view, this would require moving <code>createpage</code> from unregistered users (<code><nowiki>*</nowiki></code>) to registered users (<code>user</code>), but that would mean every non-registered user may not be able to create pages in every namespace, but talk pages.
: Another solution would be to add [[mw:Extension:ArticleCreationWorkflow]] to this project, but we don't have a system to create drafts (or similar).
: And a final solution would be to create an edit filter disallowing unregistered users from creating pages in mainspace. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 19:43, 1 October 2026 (UTC)
:: Just to note, please read the first point of [[m:Limits to configuration changes#Changes that are likely to be declined]] (Disable non-autoconfirmed page creation). [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 19:50, 1 October 2026 (UTC)
:::What I'm proposing is that we require a registered account for page creation, not autoconfirmed. enwiki (as well as a few other wikis) already use this configuration - it's not new. [[User:Omphalographer|Omphalographer]] ([[User talk:Omphalographer|discuss]] • [[Special:Contributions/Omphalographer|contribs]]) 19:58, 1 October 2026 (UTC)
:::: Okay, but I provided some alternatives above. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 20:06, 1 October 2026 (UTC)
: In that case, I have no objections here. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 19:03, 6 October 2026 (UTC)
:I would propose the use of autoconfirmed, to better patrol new pages that are being created. There are countless advertisement pages being created on Wikibooks, usually in the user's userpage. The use of a registered account proposed by Omphalographer therefore may have some limitations. I agree with the proposal to make new pages strictly autoconfirmed. If a user wishes to create a page, there could be a feature for reviewers/patrollers to check such pages that are being created. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 13:36, 9 October 2026 (UTC)
:: You might want to read my point about limits to configuration changes. [[User:Codename Noreste|<span style="color: blue">Codename Noreste</span>]] /// [[User talk:Codename Noreste|⭐️✨]] 14:53, 9 October 2026 (UTC)
:Why turn off potential good contributors by telling them they must register AND log-in in order to contribute? The problem at Wikibooks right now is the dearth of contributions, not vandalism, I think (?).
:* Anons are already precluded from editing pages that have been "protected" by admins.
:* Anon user contributions are automatically marked for Review before they become public
:* There are less than 500 anon accounts that have contributed more than one edit to Wikibooks?
:Is it really necessary to stop us from contributing to Wikibooks? [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 00:19, 10 October 2026 (UTC)
:: {{ping|~2026-40500-29}} The initial question was not whether registered accounts can contribute, it is whether temporary accounts can create pages. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 00:48, 10 October 2026 (UTC)
:::Isn't the creation of new pages a subset of potential contributions to Wikibooks? Are you saying that some members in good standing of this community are only allowed to correct obvious spelling and grammar mistakes by others? [[Special:Contributions/~2026-40500-29|~2026-40500-29]] ([[User talk:~2026-40500-29|talk]]) 19:23, 11 October 2026 (UTC)
::::That message was to {{comment}} that this discussion was about creating pages, not about whether anonymous users can contribute. [[User:TechVindicator|TechVindicator]] ([[User talk:TechVindicator|discuss]] • [[Special:Contributions/TechVindicator|contribs]]) 07:22, 13 October 2026 (UTC)
:Limiting page creation to registered users might reduce new spam/promotional/out of scope pages. I disagree with 2026-405000-29 that requiring account registration is unnecessarily burdensome for new editors.
:I don't know where the number >500 anon accounts have contributed more than one edit comes from and it seems unlikely to me: that would mean there have only been 23 anon editors per year since wikibooks was founded. Looking at Special:RecentChanges there seems to be four or five anon editors a day.
:Overall I think it is a reasonable restriction. I can't speak to the technical aspects of this change (re configuration changes, vs. autoconfirmed patrolling, etc) but if it is easy to implement I support it. [[User:JCrue|JCrue]] ([[User talk:JCrue|discuss]] • [[Special:Contributions/JCrue|contribs]]) 10:13, 12 October 2026 (UTC)
jx98ipssap0xpkceubxpwztaswdnze9
Radiation Oncology/Randomized/Technology
0
163348
4675986
4100731
2026-10-14T06:06:53Z
Jcb
90773
4675986
wikitext
text/x-wiki
{{:Radiation_Oncology:TOC}}
<big>'''Randomized Trials of Radiation Therapy Technology'''</big>
==Radiation Therapy Machines==
*'''Hopital Timone, Marseille''' (2006) -- Gamma Knife 4C vs PerfeXion
**Randomized. 200 patients. Arm 1) GammaKnife 4C vs Arm 2) GammaKnife PerfeXion
**'''2009''' {{PMID|19190462}} -- "Radiosurgery with the world's first fully robotized Leksell Gamma Knife PerfeXion in clinical use: a 200-patient prospective, randomized, controlled comparison with the Gamma Knife 4C." (Regis J, Neurosurgery. 2009 Feb;64(2):346-55; discussion 355-6.)
***Outcome: No technical failures. Median # of collimator sizes 4C 1 vs PerfeXion 2. Median treatment time 60 min vs 40 min (SS), but median beam-on time 33.4 vs 34.0 minutes (NS). Single run 42% vs. 99%. Collision risk requiring gamma angle 24% vs 0%.
***Toxicity: Less dose with PerfeXion to vertex (8x), thyroid (10x), sternum (13x), and gonads (15X)
***Conclusion: Technological advances with PerfeXion
==Immobilization==
===Head & Neck===
*'''Princess Margaret''' (2006-2008) -- standard immobilization mask vs skin-sparing immobilization mask
**Randomized. 762 CBCT scans in 20 patients. Arm 1) standard mask (SM) vs Arm 2) skin-sparing mask (SSM) modified with low neck cutouts
**'''2010''' {{PMID|20056344}} -- "Cone-beam CT assessment of interfraction and intrafraction setup error of two head-and-neck cancer thermoplastic masks." (Velec M, Int J Radiat Oncol Biol Phys. 2010 Mar 1;76(3):949-55. Epub 2010 Jan 7.)
***Outcome: Initial interfraction sigma SM 1.6 mm or 1.1 degrees vs SSM 2.0 mm and 0.8 degrees. No difference after CBCT correction. Initial intrafraction sigma <1 mm and <1 degree for both masks.
***Conclusion: Interfraction and intrafraction setup error not significantly different between masks. Mask cutouts should be considered to reduce skin toxicity
*'''Karolinska Hospital''' (Sweden)(1998-2001) -- head mask vs head-and-neck mask setup
**Randomized. 241/260 patients. H&N cancers excluding NPC. Arm 1) Head mask vs. Arm 2) Head-and-shoulder mask. Both Posicast thermoplastic masks. Assessed reproducibility (port films and table positions), patient tolerability (fit, pain, movement within, claustrophobia), and skin damage
**'''2005''' {{PMID|15629618}} -- "Randomized trial on two types of thermoplastic masks for patient immobilization during radiation therapy for head-and-neck cancer." (Sharp L, Int J Radiat Oncol Biol Phys. 2005 Jan 1;61(1):250-6.)
***Outcome: No difference in reproducibility of setup
***Toxicity: Claustrophobia head mask 45% vs. head-and-shoulder maks 58% (SS), otherwise no difference in tolerability. Skin toxicity Grade 3 head mask 21% vs. head-and-shoulder mask 39% (SS)
***Conclusion: Smaller head makes reduced claustrophobial and skin reactions, without compromising reproducibility of the setup
===Prostate===
*'''Princess Margaret''' -- VacLok vs BodyFix
**Randomized. 32 patients. Arm 1) VacLok immobilization vs. Arm 2) BodyFix abdominal compression. Interfraction motion >3 mm corrected pre-treatment
**'''2008''' {{PMID|18279985}} -- "A randomized comparison of interfraction and intrafraction prostate motion with and without abdominal compression." (Rosewall T, Radiother Oncol. 2008 Feb 13 [Epub ahead of print])
***Outcome: No difference in interfraction or intrafraction motion with or without adnominal compression
***Conclusion: Addition of abdominal compression didn't influence interfraction or intrafraction prostate motion
*'''Nijmegen, The Netherlands''' -- 3D-CRT +/- endorectal balloon
**Randomized. 48 patients, treated with 3D-CRT to 67.5 Gy. Arm 1) No endorectal balloon (ERB-) vs. Arm 2) with endorectal balloon (ERB+). Rectosigmoidoscopy at 3 months, 6 months, 1 year, 2 years. 146 endoscopies and 2,336 mucosal areas analyzed
**'''2007''' {{PMID|17161552}} -- "Reduced late rectal mucosal changes after prostate three-dimensional conformal radiotherapy with endorectal balloon as observed in repeated endoscopy." (van Lin EN, Int J Radiat Oncol Biol Phys. 2007 Mar 1;67(3):799-811. Epub 2006 Dec 8.) Median F/U 2.5 years
***Outcome: ERB group significantly lower rectal wall volume exposed to high doses. Late rectal toxicity G1: ERB- 58% vs. ERB+ 21%; G2 4% vs. 0%; G3 4% vs. 0%. Overall G1+ rectal toxicity 67% vs. 21% (SS)
***Endoscopy: Telangiectasia ERB- vs ERB+ @ 6 months 16% vs. 24%; 1 year 45% vs. 28%; 2 years 39% vs. 24% (SS). High grade telangiectasia @ 1 years 20% vs. 10%; 2 years 19% vs. 9% (SS). Significantly less high grade telangiectasia at lateral and posterior part of Rwall
***Conclusion: ERB reduced rectal wall volume exposed to >40 Gy, resulting in reduction of late mucosal changes and reduced late rectal toxicity
==Radiation Delivery: 3D Conformal RT==
===Prostate===
*'''Rotterdam, Netherlands''' (1994-1996) -- conformal RT vs conventional RT
**Randomized. 266 patients, prostate cancer Stage T1-4N0. RT 66/33. PTV expansion 15 mm. Arm 1) conventional RT (rectangular, open fields) vs. Arm 2) conformal RT (conformally shaped fields with MLC). PTV = GTV + 1.5 cm
**'''1999''' {{PMID|10098427}} -- "Acute morbidity reduction using 3DCRT for prostate carcinoma: a randomized study." (Koper PC, Int J Radiat Oncol Biol Phys. 1999 Mar 1;43(4):727-34.)
***Outcome: Acute GI Grade 2 conventional 32% vs. conformal 19% (SS); Acute GU Grade 2 in 17% vs. 18% (NS). Further GI analysis: rectal symptoms 18% vs. 14% (NS) but anal symptoms 16% vs. 8% (SS)
***Conclusion: Significant reduction in GI toxicity, driven by anal symptoms. No difference between rectum/sigmoid and bladder toxicity
**'''2004''' {{PMID|15465140}} -- "Gastro-intestinal and genito-urinary morbidity after 3D conformal radiotherapy of prostate cancer: observations of a randomized trial." (Koper PC, Radiother Oncol. 2004 Oct;73(1):1-9.) F/U 2 years
***Toxicity: Grade 2 conventional 10% vs 3D-CRT 7% (NS), Grade 1 47% vs. 40% (NS). Most bothersome symptoms: urgency, soiling, and fecal loss
***Predictors: Anal/rectal V90% for rectal toxicity. Acute anal/rectal toxicity for late rectal toxicity. Pretreatment urgency for later bladder toxicity
***Conclusion: Conformal RT at 66 Gy doesn't significantly decrease incidence of rectal, anal, and bladder toxicity compared with conventional RT
*'''Royal Marsden''' (1988-1995) -- conformal RT vs conventional RT
**Randomized. 225 men with prostate CA, T1-T4N0. NACHT in 68%. RT 64/31. Arm 1) conformal RT vs. Arm 2) conventional RT
**'''1999''' {{PMID|9929018}} -- "Comparison of radiation side-effects of conformal and conventional radiotherapy in prostate cancer: a randomised trial." (Dearnaley DP, Lancet. 1999 Jan 23;353(9149):267-72.) Median F/U 3.6 years
***Outcome: Radiation-induced proctitis G1+ conformal RT 37% vs. conventional RT 56% (SS), G2+ 5% vs. 15% (SS). No difference in bladder toxicity. No difference in bPFS (78% vs 83%, NS)
***Conclusion: Conformal RT significantly reduced risk of late proctitis
==Radiation Delivery: IMRT==
===Head & Neck===
*'''Prince of Wales Hospital; 2007''' (Hong Kong)(2001-2003) {{PMID|17971582}} -- "Prospective randomized study of intensity-modulated radiotherapy on salivary gland function in early-stage nasopharyngeal carcinoma patients." (Kam MK, J Clin Oncol. 2007 Nov 1;25(31):4873-9.)
**Randomized. 60 patients with T1-2bN0-1 nasopharynx. Arm 1) IMRT 66 Gy (CTV=GTV + 1cm; at-risk anatomic sites; LN Levels IB-II, LN upper Level V, LN retropharyngeal; PTV=CTV+3mm), lower neck LN+ 66 Gy anterior field, LN- 54-60 Gy + intracavitary BT boostvs. Arm 2) 66 Gy 2D + intracavitary BT boost
**Outcome: observer-rated severe xerostomia IMRT 39% vs. 2D-RT 82% (SS), stimulated parotid flow (SS), unstimulated parotid flow (SS), but no difference in patient-reported feeling of xerostomia
**Conclusion: IMRT superior in preserving objective parotid function, but no difference in patient-reported benefit
**Editorial ({{PMID|17971579}}): Observer-rated scoring underestimates patient reports and has low agreement among various observers. Suspect sparing of parotid alone not sufficient. Parotid gland produces saliva without mucins (lubricants, bind water, and provide selective permeability barrier). Mucin-secreting glands (e.g. minor salivary glands, submandibular glands) produce <10% saliva but >50% mucins. May need to spare these glands as well for subjective feeling of benefit
*'''Queen Mary Hospital; 2006''' (Hong Kong)(2000-2004) {{PMID|17145528}} -- "Xerostomia and quality of life after intensity-modulated radiotherapy vs. conventional radiotherapy for early-stage nasopharyngeal carcinoma: initial report on a randomized controlled clinical trial." (Pow EH, Int J Radiat Oncol Biol Phys. 2006 Nov 15;66(4):981-91.)
**Randomized. 51 patients, Stage II (T2N0-1, AJCC 1997). Arm 1) conventional RT 68 Gy, neck 66 Gy vs. Arm 2) IMRT, GTV dose 68-72 Gy, PTV 66-68 Gy. Stimulated whole (SWS) and parotid (SPS) saliva flow evaluated, QoL SF-36, EORTC Core, EORTC QLQ-H&N35 questionnaires. Minimum F/U 1 years
**1-year outcome: 25% whole flow (SWS) IMRT 50% vs. 2D 5% (SS), 25% parotid flow (SPS) 83% vs. 9% (SS). At 2 months, both group had xerostomia, but IMRT group improved significantly better over time. Also improvements in QoL
**Conclusion: IMRT significantly better than conventional RT for salivary function and QoL
===Breast===
*'''Canada''' (2003-2005) -- 2D vs. IMRT
**Randomized. 331 patients, early-stage BCA (no >=4 LN+) treated with breast-only RT. Arm 1) 2D tangent + wedge vs. Arm 2) IMRT. RT dose 50/25 + optional 16 Gy electron boost.
**'''2008''' {{PMID|18285602}} -- "A Multicenter Randomized Trial of Breast Intensity-Modulated Radiation Therapy to Reduce Acute Radiation Dermatitis." (Pignol JP, J Clin Oncol. 2008 Feb 19 [Epub ahead of print])
***IMRT associated with decreased moist desquamation ), in inframammary fold (26% vs 43%). The breast volume (V95) is associated with acute skin toxicity.
***Outcome: Dose distribution: IMRT better. Moist desquamation anywhere in breast: IMRT 31% vs 2D 48% (SS), 26% vs. 43% (SS), no difference in pain 23% vs. 25% (NS) or QoL
***Conclusion: Breast IMRT reduced occurrence of moist desquamation
*'''Royal Marsden''' -- 2D vs. IMRT
**Randomized. 240/306 patients. Early stage. Treated with Arm 1) IMRT vs. Arm 2) 2D using standard wedges. Dose 50/25 + boost 11.1/5.
**'''2007''' {{PMID|17224195}} -- "Randomised trial of standard 2D radiotherapy (RT) versus intensity modulated radiotherapy (IMRT) in patients prescribed breast radiotherapy." (Donovan E, Radiother Oncol. 2007 Mar;82(3):254-64.) Minimum F/U 5 years
***Change in breast: IMRT 40% vs. 2D 58% (SS); significantly fewer developed palpable induration. No difference in pain, hardness, or QoL
***Conclusion: Minimisation of inhomogeneity reduces late adverse effects
==Middle ear ventilation tube==
*'''Hong Kong; 2002''' {{PMID|12512893}} -- "Randomized evaluation of the audiologic outcome of ventilation tube insertion for middle ear effusion in patients with nasopharyngeal carcinoma." (Ho WK, J Otolaryngol. 2002 Oct;31(5):287-93.)
**Randomized. ? patients. NPC and middle ear effusion. Arm 1) pre-RT ventilation tube insertion vs. Arm 2) observation. Audiologic assessment throughout. F/U 4 years
**Outcome: No difference in hearing changes up to 4 years
**Conclusion: Ventilation tube insertion before RT did not offer hearing benefit
kkblanmccfk0bxqxev4xj5pu8szhv2k
Radiation Oncology/Radiobiology/DNA Damage
0
164209
4675978
4110047
2026-10-14T06:00:30Z
Jcb
90773
4675978
wikitext
text/x-wiki
{{:Radiation_Oncology:TOC}}
<big>'''Radiation-Induced DNA Damage'''</big>
==DNA As Radiation Target==
[[Image:DNA_chemical_structure.svg|right|thumb]]
*Multiple lines of evidence point to DNA damage being critical component in cell death
**Micro-irradiation studies show that to kill a cell requires much higher dose if cytoplasm only is irradiated vs. if nucleus is irradiated
**Isotopes with short-range emission (e.g [[Radiation_Oncology/Physics/Isotopes|I-125]]) produce efficient killing when incorporated directly into DNA
**Incidence of single strand DNA breaks doesn't result in cell kill, while incidence of double strand breaks and chromosome abnormalities is associated closely with cell kill
**Thymidine analogues (IUdR, BrUdR) modify radiosensitivity when incorporated into chromatin
*However, there is some evidence that radiation damage to cell membranes may also be important, possibly triggering apoptosis
*Finally, there is also evidence for 'bystander effect', where for every micro-targeted cell damaged by RT, neighboring 80-100 would also die and/or show evidence of damage
==DNA Structure==
*[[w:Nucleobase|Base]]: ring of nitrogen, oxygen, and carbon. Adenine, guanine, thymine, cytosine. Bound to opposite DNA strand via hydrogen bonds
*[[w:Nucleoside|Nucleoside]]: Base + deoxyribose sugar
*[[w:Nucleotides|Nucleotide]]: Base + deoxyribose sugar + phosphate group(s)
*Backbone: alternating sugar (deoxyribose) and phosphate groups
*Single strand: sequence of nucleotides
*Double strand: two complementary strands bound together via hydrogen bonds
*[[w:Chromosome|Chromosome]]: The entire length of an individual dsDNA; multiple chromosomes are present in a cell. Consists of a centromere and two arms, although under normal circumstances there are not visible as such
*[[w:Chromatin|Chromatin]]: complex of dsDNA and proteins, semi-tightly packed, present in nucleus during interphase. Each chromosome is present as chromatin for packing and ease of access for DNA transcription and repair
*[[w:Chromatid|Chromatid]]: one of two identical copies of DNA making up a chromosome after synthesis during cell division. Tightly packed. Term used as long as chromatids are in contact through centromere. Thereafter they are called daughter-chromosomes
[[Image:Chromatin_Structures.png|center|thumb|600px]]
{{clr}}
==DNA Damage Overview==
*Radiation may damage any of the components of DNA:
**Base damage
**Single strand break (SSB)
**Double strand break (DSB)
**DNA strand cross-links
**DNA-protein cross-links
*Ultraviolet radiation (UV-A) typically causes base damage, such as 8-oxo-G and [[w:Pyrimidine_dimers|pyrimidine dimers]] (e.g. cyclobutane pyrimidine dimer, and 6-4 photoproduct), although can also lead to SSBs. In fact, pyrimidine dimers are usually not found after irradiation with x-rays
*For therapeutic radiation, damage to DNA is caused by energy deposition along the track of the charged particle (electron for x-rays, proton, alpha particle for neutrons)
**Energy is not deposited uniformly along the track, and deposition pattern can be grouped as follows:
**"Spur": diameter of ~4 nm (2x DNA diameter), 100 eV energy deposited, ~3 ion pairs
***X-rays deposit 95% of their energy via spurs
**"Blob": diameter of ~7 nm, 100-500 eV energy deposited, ~12 ion pairs
***Neutrons and alpha particles deposit much of their energy via blobs
***Due to higher number of ion pairs generated, DNA damage can be much more severe than in spurs
*Damage from spur and blob energy depositions can lead to multiple close sites of DNA damage, termed ''locally multiply damaged site''
*Frequency of DNA damage from photon radiation
**A dose that induces on average one lethal event per cell is the '''D<sub>0</sub>''' dose; statistically ~37% of cells in a population exposed to D<sub>0</sub> dose will survive, while other cells will accumulate one or multiple lethal events
**For most mammalian cells, photon D<sub>0</sub> is 1-2 Gy
**Number of DNA lesions per cell, immediately after D<sub>0</sub> dose:
{| class="wikitable"
! colspan="23" | Events per D<sub>0</sub> (1-2 Gy) dose
|-
| width="160" | Ionizations || width="100" align="center" | ~100,000/cell
|-
| Base damage || align="center" | >1000/cell
|-
| Single strand breaks || align="center" | ~1000/cell
|-
| Double strand breaks || align="center" | ~40/cell
|-
| Cell deaths || align="center" | ~0.63/cell <br>(SF = 0.37)
|}
*Amount of DNA damage is influenced by the ability of cells to scavenge free radicals produced during ionizations prior to them causing damage, the number of ionizations that are close enough to DNA to damage it, and the effectiveness of [[Radiation_Oncology/Radiobiology/DNA_Repair|DNA repair]]. As a result, frequency of radiation damage of free DNA is much higher than cellular DNA
*Base damage and single strand breaks
**Typically efficiently repaired
**Do not correlate with cell killing (for example, hydrogen peroxide produces frequent SSBs but doesn't not lead to significant cell kill)
**However, if incorrectly repaired, may lead to alteration in DNA base sequence and thus to mutations
**Frequency of mutations usually increases in dose-dependent manner, but at higher doses, lethal events begin to predominate and frequency of surviving mutations decreases
*Double strand breaks
**Implicated in being primarily responsible for cell killing
**Simple DSB: defined as the occurrence of two single-strand breaks (SSBs) within approximately 6-10 base pairs caused by a single radiation track ({{PMID|9652804}})
**Complex DSB: In addition characterized by a presence of other DNA damage sites (oxidative base lesions, abasic (AP) sites, single strand breaks) in close proximity to the break termini
**Radiation can produce a range of structural complexity DSBs; higher LET radiation produces more complex DSBs due to bleb energy deposition. Low LET radiation is also able to produce complex DSBs
**Strand ends typically have an overhang, that is one strand is several bases longer than the other strand, resulting from an asymmetric break
*Complex double strand breaks
**Occur in ~30% of low LET induced DSBs
**Survival curve shoulder for low LET radiation is thought to reflect the cell's DSB repair capacity
**No survival curve shoulder for high LET radiation may result from the high structural complexity and low repairability of complex DSBs
**It is postulated that complex DSBs may similarly be responsible for majority of cell kill resulting from low LET radiation, after simple DSBs are repaired
**A high degree of associated base damage in complex DSBs may be a factor in poor repair via the non-homologous end-joining pathway (NHEJ)
*Once double strand break has been produced, the broken fragments may have several different fates:
**Rejoin in the original configuration - this leaves no lasting impact at the next mitosis
**Fail to rejoin and remain free - this results in a deletion mutation at the next mitosis
**Rejoin different broken chromosome or fragment - this results in a chromosome/chromatid aberration at the next mitosis, depending on when along the cell cycle the DSB occurred
*Historically, chromosome aberrations are scored at the first metaphase after exposure to radiation. Therefore, depending on when in cell cycle the damage happens, there are two types of aberrations
**Chromosome aberrations - both sister chromatid strands are damaged. Damage happens before chromosome is duplicated; S phase replicates the break in the new sister chromatid
**Chromatid aberrations - single chromatid strand is damaged. Damage happens after chromosome is duplicated; the complementary sister chromatid is undamaged
*There are multiple types of aberrations, some lethal and others not. Please see more at [[w:Chromosome_abnormalities]]
**Dicentric (chromosome, lethal): two different chromosomes suffer DSB. The long pieces (containing centromeres) inappropriately join, the two short fragments (acentric) remain free. The long piece containing two centromeres is duplicated. [http://chromosometesting.com/html/samples6.html Image]
**Ring (chromosome, lethal): one chromosome suffers two separate DSBs, one in each arm. The sticky ends may rejoin to form a ring, while the two short fragments (acentric) remain free. The ring containing a single centromere is duplicated. [http://chromosometesting.com/html/samples4.html Image]
**Anaphase bridge (chromatid, lethal): Only evident at anaphase, happens after chromosome is duplicated. Both chromatids suffer DSB, and sticky ends join inappropriately. At anaphase, normal separation of chromosomes to opposite poles is not possible
**Symmetric translocation (chromosome, non-lethal): Two different chromosomes suffer DSB. The broken fragments are exchanged, and the sticky ends rejoin. This may result in an [[w:Oncogene_fusion_protein|oncogene fusion protein]] (e.g. [[w:Bcr-abl_fusion_protein|bcr-abl]])
**Deletion (chromosome/chromatid, non-lethal): one chromosome suffers two separate DSBs, on the same arm. The middle fragments falls out, and the outer fragment is inappropriately reattached. The middle fragment is lost at the next mitosis
*Each chromosome is restricted to a specific nuclear domain; as a result, the interactions between breaks are not completely random. Active chromosomes tend to be those with largest surface area (e.g. chromosome 8)
*These radiation-induced DNA events form the basis of the [[Radiation_Oncology/Radiobiology/Linear-Quadratic|Linear-Quadratic Model]]
==Double Strand Break Literature==
*'''NIH'''
**Evaluation of structural organization of radiation-induced DNA double-strand break, produced by 125I-labeled oligonucleotide targeting a particular DNA sequence
**'''2005''' {{PMID|15962759}} -- "Characterization of a complex 125I-induced DNA double-strand break: implications for repair." (Datta K, Int J Radiat Biol. 2005 Jan;81(1):13-21.)
***Conclusion: Complex DSBs have high degree of base damage clustering proximal to DSB end
**'''2006''' {{PMID|17067210}} -- "Molecular analysis of base damage clustering associated with a site-specific radiation-induced DNA double-strand break." (Datta K, Radiat Res. 2006 Nov;166(5):767-81.)
***Conclusion: Base damage clustering within 8 bases of the I-125 target base. Base lesions were 8-hydroxyguanine, 8-hydroxyadenine, and 5-hydroxycytosine. Also evidence for base damage >24 bp upstream, possibly via charge migration mechanism
*'''MRC; 2001''' {{PMID|11604075}} -- "Computational approach for determining the spectrum of DNA damage induced by ionizing radiation." (Nikjoo H, Radiat Res. 2001 Nov;156(5 Pt 2):577-83.)
**Mone Carlo track simulation. Conclusions:
**(1) Yield of strand breaks per unit absorbed dose is nearly constant over a wide range of LET
**(2) Majority of DNA damage is of simple type, though majority of SSBs are accompanied by at least one base damage
**(3) For low energy electrons, ~20-30% of DSBs are complex DSBs. This increases with LET, reaching ~70% for alpha particles
**(4) Extent of damage in local hit region of the DNA is limited to few base pairs
*'''Columbia; 1992''' {{PMID|1351522}} -- "Constraints on energy deposition and target size of multiply damaged sites associated with DNA double-strand breaks." (Brenner DJ, Int J Radiat Biol. 1992 Jun;61(6):737-48.)
**Locally multiply damaged sites (LMDS) are energy depositions of 2-5 ionizations localized in 1-4 nm diameter
*'''UCSD; 1990''' {{PMID|1971840}} -- "The yield of DNA double-strand breaks produced intracellularly by ionizing radiation: a review." (Ward JF, Int J Radiat Biol. 1990 Jun;57(6):1141-50.)
**DNA dsb linearly related to dose; DNA damage per dose constant among cell types
**Variations in radiosensitivity assigned to difference in repair speed and/or accuracy
==Detection of DNA Damage==
===Base damage===
*High pressure liquid chromatography (HPLC)
*Tritium release from labeled thymine
*Phosphate release
*Fluorescent labeling
===Strand breaks===
*For most of the assays, DSBs are evaluated in neutral pH (7-10) solutions and SSBs are evaluated in alkaline pH (~12) solution<br>
*Damage detected by these assays is typically repaired within 24 hours
*'''Sucrose gradient segmentation''' - centrifuge
**Sucrose solution with gradient varying from 5%-30%
**Cell DNA radiolabeled (e.g. <sup>14</sup>C)
**Cell lysis induced, DNA released (depending on solution as single strand or double strand) to sucrose solution
**Sucrose solution with DNA then centrifuged
**Larger DNA fragments travel differently through the sucrose solution than small fragments
**Fractions of the fluid are then collected and assayed for <sup>14</sup>C to evaluate amount of DNA present at each gradient level
**Strand break frequency is estimated from distribution of fragment size
*'''Nucleoid sedimentation''' - centrifuge
**Sucrose gradient solution is used
**Cells are lysed at neutral pH in the presence of high salt concentration and non-ionic detergent
**Interphase nucleus opens up, and chromatin strands are revealed. The individual broken strands are called nucleoids, and consist of supercoiled DNA still wrapped around residual protein structures
**Single strand DNA breaks allow the chromatin fragments to relax the supercoil and enlarge
**Differently sized chromatin fragments travel differently through the sucrose solution
**Sometimes, a fluorescent dye is added, and resulting halos can be measured by microscopy (= the ''halo method'')
*'''Neutral filter elution''' - elution
**Filter with pore size ~2 mm (DNA fiber has diameter ~25nm, 100x smaller)
**Cell DNA is radiolabeled (e.g. <sup>14</sup>C)
**Cell lysis induced, DNA released (depending on solution as single strand or double strand) on top of filter
**Elution buffer solution is used to wash DNA fragments through the filter
**Rate of DNA elution is related to size of DNA fragments
**Double strand breaks are assayed at pH 7.4-9.6, single strand breaks are assayed at more alkaline pH 12.3
*'''Pulsed-field gel electrophoresis (PFGE)''' - electrophoresis
**Agarose gel
**Cell DNA is radiolabeled (e.g. <sup>14</sup>C) or DNA-specific fluorescent dye is used after the electrophoresis
**Cell lysis induced, DNA released (depending on solution as single strand or double strand) to agarose gel
**Fragments of DNA carry a net negative charge
**Electric field is applied to the agarose gel, and DNA fragments travel at speed inversely related to their size
**Constant field electrophoresis can work, but separation of fragments is improved by pulsing the field at different directions to axis of migration
*'''Single-cell gel electrophoresis ([[w:Comet_assay|Comet assay]])''' - electrophoresis
**Cells are embedded in agarose gel and then lysed to release DNA in-situ
**Electric field is applied, and DNA fragments migrate away from the DNA mass in the nucleus outward
**The shape of the resulting migration structure resembles a comet, hence the name
**Double strand breaks are assayed at neutral pH, while single strand breaks are assayed at alkaline pH
**High sensitivity to SSB, though not as much for DSB
*'''Gamma-H2AX assay''' - immunohistochemistry/flow cytometry
**IHC is very labor intensive and not easily implemented in a routine practice, but allows detection of ~10X lower level of DNA damage
**This assay is a highly sensitive method for detecting presence (and/or repair) of individual DSBs
===Chromosome aberrations===
*Stable chromosome aberrations can be present for months - years after exposure
*'''Visual observation''' - at the first metaphase after exposure to ionizing radiation
*'''Chromosome aberration assay''' - immunohistochemistry via FISH painting
==Chromosome Aberrations in Human Lymphocytes==
*Used widely as biomarkers of radiation exposure
*Incidence of dicentrics and rings (see above) in peripheral blood lymphocytes is scored after total body irradiation exposure
**Dose-response fits linear quadratic relationship
**Doses as low as 0.25 Gy can be detected, which can be used for evaluation of "black film badges" or potential accidents
*Damage kinetics
**Terminal deletions - single hit - linear response
**Dicentrics, translocations, rings, interstrand deletions - two hits - quadratic response
*Radiation exposure can be tracked over time
**Mature lymphocytes have life span of ~1500 days (~4 years) and are slowly eliminated from the peripheral blood. Therefore, yield of asymmetric aberrations (dicentrics, rings) in mature lymphocytes declines over time
**Stem cell/precursors lymphocytes also experience DNA damage, which has different time course depending on type
**Unstable aberrations: Asymmetric aberrations (e.g. dicentrics, rings) kill the cell, and are not passed on to progeny. Their yield decreases over time
**Stable aberrations: Symmetric translocations may persist indefinitely, as they are propagated through the progeny. Their yield remains stable over time
**Frequency of translocations after >50 years in Hiroshima survivors correlates well with total body dose received at that time
3d9r1dcp0u7arkf4fbt0lc2udaf11sd
Radiation Oncology/Radiobiology/DNA Repair
0
164210
4675979
4100697
2026-10-14T06:01:14Z
Jcb
90773
4675979
wikitext
text/x-wiki
{{:Radiation_Oncology:TOC}}
<big>'''Repair of Radiation-Induced DNA Damage'''</big>
==Single Strand Damage Repair==
*Single strand breaks are common occurrence; 1 Gy of radiation induces ~1000 SSB per cell
*Given this, cells have efficient machinery to repair SSB
*However, single strand breaks are also important to double strand break formation
#Ionizing radiation often occurs in clusters, and some SSB will be created in proximity to areas with base damage. In these, the temporary strand nick performed during BER can combine with the near SSB to form a DSB
#If SSB happens in a replication fork during S-phase, the fork collapses and there is a single-end double-strand break. These cannot be repaired by NHEJ (since there are not two ds breaks), and must be attempted to be repaired by HR. This may be a problem in tumors with HR deficiencies (such as BRCA1 and BRCA2 mutations), and PARP inhibition seems particularly effective in these settings
===Base Excision Repair (BER)===
*Major pathway responsible for repair of hydrolytic and oxidative base damage (e.g. Uracil, 8OH-guanine, abasic sites)
*Damage is recognized by Poly (ADP-ribose) polymerase (PARP)
*Depending on the number of bases damaged, BER proceeds through either Short Patch or Long Patch pathway
**Short Patch BER
***''DNA glycosylase'' excises the base leading to AP Site (apurinic site). There are different glycosylases which recognize specific bases
***''AP endonuclease'' (APE-1) removes the sugar residue
***''DNA polymerase β'' replaces the correct nucleotide
***''DNA ligase III'' and ''XRCC1'' complex ligate the free DNA strands together
**Long Patch BER
***''DNA glycosylase'' excises the base leading to AP Site (apurinic site). There are different glycosylases which recognize specific bases
***''AP endonuclease'' (APE-1/AP Lyase) removes the sugar residues
***''PCNA'' (Proliferating cell nuclear antigen) serves as an adapter for proteins involved in the subsequent steps
***''DNA polymerase δ/ε'' and ''PCNA'' complex duplicate the correct nucleotide sequence, duplicating it even under the undamaged strand
***''Flap endonuclease 1 (FEN1)'' and ''PCNA'' complex snips off normal overhang of the prior undamaged strand
***''DNA ligase I'' and ''PCNA'' complex ligate the free DNA strands together
*Defects generally do not increase radiation sensitivity, but lead to increased mutation rate. Defect in XRCC1 does increase radiosensitivity (1.7X), but this may be due to its role in SSB repair
*Inhibition of PARP and XRCC1 is efficient in HR-deficient tumors
*Hereditary Syndromes:
**No human diseases resulting from BER mutation have thus far been identified
===Nucleotide Excision Repair (NER)===
*Major pathway responsible for repair of bulky DNA adducts (e.g. pyrimidine dimers); as such, it is not critically important for radiation oncology
*Overview of the steps involved (see more at [[w:Nucleotide_excision_repair|wikipedia]]
**Incision in DNA surrounding the damage; this is typically a bracket 24 - 32 bp long
**Removal of the entire region containing the adducts
**Repair synthesis of DNA
**DNA ligation
*Proteins involved include XPA,XPB, XPC,XPD,XPE,XPF, and XPG (linked to Xeroderma pigmentosum patients) and CSA (ERCC8) and CSB (ERCC6) (linked to Cockayne syndrome)
*Defects generally do not increase radiation sensitivity, but lead to increased sensitivity to UV damage and to anticancer agents that induce bulky addicts (e.g. alkylating agents)
*Hereditary Syndromes:
**[[Radiation_Oncology/Cancer_Syndromes/Xeroderma_pigmentosum|Xeroderma Pigmentosum]]
**[[Radiation_Oncology/Cancer_Syndromes/Cockayne_Syndrome|Cockayne Syndrome]]
===Mismatch Repair===
*Pathway responsible for removes base-base mismatches and small insertion/ deletion mismatches
*Overview of the steps involved
**Initiation: MSH2, MSH3, and MSH6 surround DNA; MLH1 and PSM2
**Excision and resynthesis: Polymerase δ/ε and PCNA complex
**DNA ligation with DNA ligase I
*Defects generally do not increase radiation sensitivity, but lead to increased mutation rate
*Mutations in MLH, MSH, or PSM families result in microsatellite instability (small base insertions or deletions) and cancer (e.g. sporadic [[Radiation_Oncology/Endometrium|endometrial cancer]])
*Hereditary Syndromes:
**[[Radiation_Oncology/Cancer_Syndromes|Hereditary Non-Polyposis Colon Cancer (HNPCC)]].
===DNA Damage Bypass===
*Occurs when a moving replication fork encounters damage in the template strand
*Important component of cellular response to DNA damage, and contributes similar survival as NER and HR
*Rad 18 binds to DNA, Rad 6 ubiquitylates PCNA
*PCNA may determine if a recombinatorial bypass (error-free) or translesion bypass (error-prone) will take place. Not well understood
*SRS2 is a helicase, which blocks further homologous recombination
*Recombination bypass proteins include Rad5, Ubc13, Mms2
*Translesion bypass proteins include DNA polymerase ζ and η
*Please see [http://asajj.roswellpark.org/huberman/DNA_Repair/bypass.html Rosewell Park lecture] for more information
===DNA Alkylation===
'''''MGMT'''''
*MGMT (O<sup>6</sup>-methylguanine-DNA methyltransferase) gene is located on chromosome 10q26
*It encodes DNA-repair proteins that removes alkyl groups from O<sup>6</sup> position on guaning
*Repair of DNA by MGMT consumes the protein, which must be replaced by the cell
*O<sup>6</sup>-methylguanine lesions are induced by chemotherapy [[Radiation_Oncology/Chemotherapy#Alkylating_Agents|alkylating agents]], and if left unrepaired, trigger cytotoxicity and apoptosis
*Epigenetic silencing of MGMT gene by promoter methylation results in loss of MGMT expression and reduced DNA repair. Please see the [[Radiation_Oncology/CNS/High_grade_glioma/Overview#Biologic_markers_for_prognosis|Glioblastoma]] chapter for more information
==Double Strand Damage Repair==
*There are two main pathways for repair of DSBs
**Nonhomologous end-joining ([[w:NHEJ|NHEJ]]): primarily active during G0, G1, early S when sister chromatid not present, though also active in G2/M. Joins two double strand breaks. Error-prone
**Homologous recombination repair ([[w:Homologous_recombination|HRR]]): during G2/M when sister chromatid is present. Copies information from the undamaged chromosome. Error-free
*The role of single-strand annealing as a repair pathway for DSB has not been well clarified, but seems to involve homologous recombination as well
===Nonhomologous End-Joining (NHEJ)===
*Joins two DSB ends together, without requiring a template
*Low fidelity, with frequent deletions or insertions at the break site. While this may increase mutations, it allows the cell to survive. Also used for immunoglobulin V(D)J recombination
*Starts with Ku70/Ku80 heterodimer binding to free DNA ends, and acting as a scaffold
*It then recruits DNA-PKcs (PRKDC), which acts as a bridge between the two free DNA ends. It also phosphorylates a number of target proteins involved in DNA repair and cell cycle control
*DNA-PKcs complexes with Artemis, which is an endonuclease to process the DNA ends
*Several other enzymes, including nucleases and polymerases, then fill in or remove single-strand overhangs. This process can result in insertions or deletions
*Final step is ligation of the two ends together by ligase IV, assisted by XRCC4 and XLF
*Hypersensitivity to ionizing radiation
*Hereditary syndromes:
**DNA-PKcs, Artemis, XLF: [http://www.humpath.com/spip.php?page=article&id_article=8944 Radiosensitive Severe Combined Immunodeficiency (RS-SCID)] ({{PMID|19075392}})
**LIG4 (Ligase IV gene): [http://www.humpath.com/LIG4-syndrome LIG4 syndrome], similar to SCID
===Homologous Recombination (HR)===
*Uses homologous DNA (replicated DNA) as a template to repair damage
*May take up to 6 hours or more to complete
*Starts with creating single strand overhang regions around each side of the break by resecting part of the 5' -> 3' strand, with MRN playing a major role
*MRN complex (MRE11-RAD50-NBS1) holds the broken ends of DNA, such that MRE11 attaches to the broken DNA ends, while RAD50 bridges the break, and NBS1 activates ATM to start the repair
*BRCA1 is recruited by H2AX to regulate the activity of the MRN complex
*Replication protein A (RPA) coats each single strand overhang as scaffold
*RAD51 complex attaches around the ssDNA to create a nucleoprotine filament and searches for the homologue strand. There are multiple versions of RAD51 that participate in this process (e.g. RAD51B, RAD51C, RAD51D, XRCC2, XRCC3)
*BRCA2 facilitates loading of RAD51 onto the RPA-covered single strand overhang
*FANC-D2 regulates function of BRCA2, and is also involved in S-phase checkpoint
*RAD52 and RAD54 are supporting proteins to RAD51 in this process
*Helicases BLM, TopIIIA, WRN, and others unwind the homologous DNA double strand; RAD54 may also play some role in this process
*The identity of polymerases and ligases involved in copying the damaged strand based on the homologous template is not known, although Ligase I is probably involved
*MMS4 and MUS81 resolve the [[w:Holliday_junction|Holiday junction]] crossovers
*Hereditary Syndromes:
**MRE11:[[Radiation_Oncology/Cancer_Syndromes/Ataxia-Telangiectasia-Like_Disorder|Ataxia-Telangiectasia-Like Disorder (ATLD)]]
**NBS1: [[Radiation_Oncology/Cancer_Syndromes/Nijmegen_Breakage_Syndrome|Nijmegen Breakage Syndrome (NBS)]]
**RAD50: [[Radiation_Oncology/Cancer_Syndromes/Nijmegen_Breakage_Syndrome-Like_Disorder|Nijmegen Breakage Syndrome-Like Disorder (NBSLD)]]
**BLM: [[Radiation Oncology/Cancer Syndromes/Bloom Syndrome|Bloom Syndrome]]
**WRN: [http://www.humpath.com/spip.php?page=article&id_article=1772 Werner syndrome]
**FANC-D2: [[Radiation_Oncology/Cancer_Syndromes/Fanconi_Anemia|Fanconi Anemia (FA)]]
**ATM: [[Radiation_Oncology/Cancer_Syndromes/Ataxia-Telangiectasia|Ataxia-Telangiectasia]]
**ATR: [http://www.humpath.com/spip.php?page=article&id_article=4010 ATR-Seckel syndrome]
===Single Strand Annealing (SSA)===
*A transitional process between NHEJ and HR
*One strand on each side of the break is digested away, until a region of homology is found between the remaining two strands
*The two single strands are annealed at that point
*The complementary strands that were digested are reconstituted
*Results in loss of genetic information
*Please see [http://www.bio.brandeis.edu/haberlab/jehsite/ssa.html this page] for more detail and pictures
==NHEJ vs HR==
*NHEJ happens along in all phases of the cell cycle
*HR is specific only to dividing cells, since it occurs in S and G2 phase
*In G1 phase, double strand DNA damage is repaired with NHEJ, while in S-G2 phases, both processes are active and compete against each other
*Therefore, in slowly dividing or non-dividing tissues (e.g. spinal cord or stromal tissues), primary repair process is NHEJ
*There is some evidence that MRN is active in both processes, and that it may regulate the choice between NHEJ and HR in dividing cells
*If one of the components is defective, it leads to various genomic instability disorders and increased malignancy
==Cross-Link Repair==
*Genes and pathways used for DNA-DNA and DNA-protein cross-links are under investigation
*The pathway depends on homologous recombination
==DNA Repair Literature==
*'''Saarland (Germany); 2008''' {{PMID|18805648}} -- "DNA Double-Strand Break Rejoining in Complex Normal Tissues." (Rube Ce, Int J Radiat Oncol Biol Phys. 2008 Sep 19. [Epub ahead of print])
**TBI in mice model. Formation and rejoining of DSBs analyzed via gammaH2AX in both early responding (small intestine) and late responding (lung, brain, heart, kidney) tissues
**Outcome: Linear dose correlation of gammaH2AX to dose. Various normal tissues exhibited identical kinetics of gammaH2AX foc loss, despite different clinical radiation response
**Conclusion: Identical kinetics of DSB rejoining in various organs suggest that tissue specifice difference in radiation response are independent of DSB rejoining
*'''Oxford; 2008''' {{PMID|18571480}} -- "Interplay of two major repair pathways in the processing of complex double-strand DNA breaks." (Dobbs TA, DNA Repair (Amst). 2008 Aug 2;7(8):1372-83. Epub 2008 Jun 20.)
**Evaluation of base excision repair and DSB ligation
**Conclusion: Reduced efficiency of repair of complex DSBs
*'''London Research Institute; 2008''' {{PMID|18596698}} -- "Mre11-Rad50-Nbs1-dependent processing of DNA breaks generates oligonucleotides that stimulate ATM activity." (Jazayeri A, EMBO J. 2008 Jul 3. [Epub ahead of print])
*'''Wayne State; 2007''' {{PMID|17967316}} -- "Transition in Survival From Low-Dose Hyper-Radiosensitivity to Increased Radioresistance Is Independent of Activation of ATM SER1981 Activity." (Krueger SA, Int J Radiat Oncol Biol Phys. 2007 Nov 15;69(4):1262-71.)
**Role of ATM and downstream G2 cell-cycle checkpoint in low-dose hyper-radiosensitivity
*'''Harvard; 2007''' {{PMID|17525332}} -- "ATM and ATR substrate analysis reveals extensive protein networks responsive to DNA damage." (Matsuoka S, Science. 2007 May 25;316(5828):1160-6.)
**Proteomic analysis of ATM/ATR phosphorylated proteins
**>900 regulated sites found on >700 proteins, many involved in DNA damage response
==ERCC1==
*Impacts DNA damage from lesions caused by UV light, exogenous chemicals that induce bulky DNA adducts (eg cisplatin)
*1/16 genes in nucleotide excision repair complex
*Forms heterodimer with XPF, which excises 5' DNA strand relative to site of damage. This is final step of the excision process
*{{PMID|16957145}} -- "DNA repair by ERCC1 in non-small-cell lung cancer and cisplatin-based adjuvant chemotherapy." (Olaussen, N Engl J Med. 2006 Sep 7;355(10):983-91.)
**Prognostic for benefit of chemo in resected NSCLC
==Summary of Damage - Repair==
*Thymine glycol - BER
*8-OH-guanine - BER
*Urea/uracil - BER
*Bulky adducts, pyrimidine dimers - NER
*Nucleotide error - Mismatch repair
*DNA double strand break - NHEJ or HR
==Review==
*'''2007''' {{PMID|17512070}} -- "DNA damage-induced signalling in ataxia-telangiectasia and related syndromes." (Lavin MF, Radiother Oncol. 2007 Jun;83(3):231-7. Epub 2007 May 23.)
*'''2007''' {{PMID|18066093}} -- "DNA double-strand break repair and development." (Phillips ER, Oncogene. 2007 Dec 10;26(56):7799-808.)
*'''2002''' {{PMID|12016139}} -- "Sensing and repairing DNA double-strand breaks." (Jackson SP, Carcinogenesis. 2002 May;23(5):687-96.)
*'''1998''' {{PMID|9806612}} -- "Monitoring and signaling of radiation-induced damage in mammalian cells." (Szumiel I, Radiat Res. 1998 Nov;150(5 Suppl):S92-101.)
aztgpwvagmfm6bihi6iq0a719odc3vl
Adventist Youth Honors Answer Book/Recreation/Map and Compass
0
168652
4675911
4531877
2026-10-13T21:15:18Z
~2026-55082-89
3628364
/* a. How is distance defined. */
4675911
wikitext
text/x-wiki
{{honor_header|Level 2|From GC 1956 This version SPD 2010|Recreation|South Pacific Division}}
This honour is similar to the General Conference's [[../Orienteering (General Conference)|Orienteering]] Honour. This page will mainly show the answers to the different questions or where a different answer is needed.
The Honour is equivalent to the New Zealand NZQA 431 Navigation in Good visibility.
==Section 1 – The Map==
Please note. This honour has had alterations as the South Pacific Division has reviewed the honour and made changes in 2010
===1.1 Know the following===
====a. What is a topographical map?====
Basically a view from on top. Symbols and colours to represent true features on the land.
====b. What is found on a topographical map?====
Key, contour lines, scale, grid system, trigs, G-MA information, map series and name
====c. Give three uses of a topographical map.====
Navigation, route planning. Identifying physical land features. In emergency situations when visibility is reduced.
* Description of land surface showing the shape of the land.
* Shows positions of roads, fences, and other man made objects.
* Indicates a pictorial view from above
===1.2 What is an orthophoto map?===
An orthophoto map uses aerial photos as the background with symbols and other information overlaid. Find a picture of one using Google.
===1.3 Be able to recognize twenty signs and symbols found on a topographical map, giving some in each of the following categories===
====a. man made====
====b. water feature====
====c. vegetation feature====
Most good tramping (hiking) maps will have a key showing lots of different symbols representing various features.
'''Man made:'''
Roads: Highways, sealed roads, gravel roads, 4wd tracks (Dryweather roads), walking tracks. Bridges, cuttings, embankment.
Railway: single track, multi track, stations, cuttings, bridges.
Miscellaneous: buildings, churches, schools, structures, cemetery,light house, ship wreek, electricity lines and poles, fences, mines open & underground.
'''Relief features:''' contour lines, permanent ice, rock outcrops, boulders, banks, trig station, alpine scree, glacier.
'''Water feature:''' marsh, river, lake, sea, small stream, ditch, spring, mangrove, getty, break water, gravel, sand, mud, dam, waterfall, sink hole.
'''Vegetation features:''' native forest, exotic coniferous (and non coniferous) forest, orchard, vineyard, shelter belt.
===1.4 Know and explain the following as they relate to elevation===
====a. Elevation.====
====b. Contour interval.====
Coloured orange. Points of same altitude
In the NZ old inch to a mile series 1:63360 the difference in height between contours was 100 feet. In the new (2005) metric series 260. the interval is 20 metres.
====c. Ground formations (Valey, Ridge, Spur, Bluff or Cliff, Saddle, Sholder, Escarpment, Knoll, Brow) defined by their contour lines====
[[Image:shapes of contours.jpg|thumb|300px|left|shapes of contours]]
[[Image:Milford track.jpg|thumb|300px|right|Milford track]]
This picture of part of the Milford Track gives some idea of the contour lines on the Hollyford Map. These are glacier-formed valleys, U-shaped with steep sides. The Milford, Routeburn and Hollyford tracks are in the same area in Fiordland.
{{clear}}
===1.5. Know and explain the following as they relate to distance===
This is a horizontal distance as the crow flies. It is not always a very accurate estimation of the amount of land between two points (land distance). Land distance depends on terrain. Land distance = horizontal distance + (contour interval x number of contour lines).
====a. How is distance defined.====
the total length of the path or the amount of space between two points, objects, or times
====b. The map scale====
Relationship of the horizontal distance between two points on the map and the horizontal distance on the ground in real life. This is shown as a ratio
====c. How to measure linear distance====
Look at the map scale to calculate the real distance
====d. How to estimate land distance.====
The land distance can be estimated by the following:
L = H + (CI x n)
Where: L = land distance between points A & B<br/>
H = horizontal distance between points A & B<br/>
CI = contour interval of the map<br/>
n = number of contour lines crossed between points A & B
===1.6. Know and explain the following as they relate to a map grid system.===
====a. What is the grid system?====
To accurately locate reference points on a map using a set of 6 numbers.
====b. What is a six figure grid reference?====
Grid numbers are a two digit number at the end of each grid line. However a grid reference must contain 6 numbers. 3 from the horizontal and 3 from the vertical. The third digit is the approximate distance in tenths between the two nearest grid lines. Always give the longitude first then latitude.
====c. Rules for reading grid references.====
A typical grid reference would look like 355884. Most topo maps would explain how to do this on the borders.
===1.7. Know and explain the following in relation to map reading===
====a. Grid North====
The direction of the North Grid lines run vertically on the map so the top of the map would be grid north.
====b. True North====
Usually grid north and true north are the same on topographical maps, ''but'' in some instances this is not the case, especially as the maps get closer to the arctic regions. Check the map do NOT guess or assume or you will be geographically embarrassed (i.e. lost). Check the magnetic delineation on the map.
====c. Magnetic North====
The direction to which the red pointer needle on the compass nearly always points. The difference between true North and magnetic North is called the magnetic declination or G-MA (Grid Magnetic Angle)
====d. Declination====
The compass needle aligns itself with the Earth's magnetic flux (lines)of force passing through the place you are standing. The difference between true north and magnetic north is the G-MA angle. This changes with the Earth's magnetic field variations. The G-MA must be considered when using a compass to orientate a map. The map will give a value and time calculation so you can work the value of the angle.
====e. Grid Magnetic Angle (G-MA or GMA)====
==Section Two – The Compass==
===2.1. What are the eight major points of the compass and their bearings?===
{|border=0 cellpadding=5 cellspacing=1
|-
|1||N || 0°/360°
|-
|2||NE || 45°
|-
|3||E|| 90°
|-
|4||SE|| 135°
|-
|5||S|| 180°
|-
|6||SW|| 225°
|-
|7||W|| 270°
|-
|8||NW|| 315°
|}
===2.2. Identify the type of compass most popular with bushwalkers.===
I have come to understand that there is a difference between Northern Hemisphere compasses and Southern Hemisphere compasses. I am free to be corrected on this point. It may pay to check if you are country hopping.
Most people I know use a Silva brand or similar. Plastic transparent base. Scales, glow in the dark dots. Some are good for Orienteering as they have triangles and circles cut out of base for marking controls on your map.
===2.3. Know the parts of an orienteering compass.===
The Silva compass is a very good one to use on map work. It has a plastic see through base. To get a good picture with a label of what each part is called cheek out Google images.
[[Image:CompassUseTargetMarked.jpg|thumb|Setting compass to a bearing]]
1. Scales. Inches and mm
2. Transparent base plate
3. North on dial
4. Magnetic needle north end
5. Liquid filed housing with graduated dial and orienting line
6. Direction of travel arrow
7. Magnifying lens
8. Index pointer (for setting bearings and reading
9. Orienting arrow
10. Dial graduations 360 deg
===2.4. Know and explain the following as they relate to Grid Bearings and Magnetic Bearings===
====a. What are Bearings?====
Directions expressed in degrees from North. A circle has 360 degrees. So North is 0 degrees.
There are true bearings with the North Pole as the reference point. There are also magnetic bearings taken from a theoretical Magnetic North. But in reality you are influenced by a local magnetic flux. The magnetic forces around our planet are not always even. So when giving a bearing always state if it is true or magnetic.
On a map there usually are grid lines and bearings can also have them as the bearing reference. (usually gridlines are true North or very close to it. It is wise to check)
====b. How to calculate Grid Bearings from the map ====
i. Place long edge of compass along the bearing desired.
ii. Hold compass base on the map and turn compass housing until orienting arrow is parallel to grid lines.
iii. Correct for G-MA
iv. Hold compass at waist and turn until needle aligns with orienting arrow. Travel in the direction of travel arrow.
====c. How to convert a Grid Bearing to a Magnetic Bearing====
Point the travel arrow towards where you want to go. Rotate compass housing until the orienting arrow is directly below the magnetic needle. This will give the magnetic bearing.
====d. How to convert a Magnetic Bearing to a Grid Bearing====
====e. How to take and march on a Magnetic Bearing====
Set the compass to the required magnetic bearing. Follow the travel arrow. It is good practice to look in the direction of travel and find a notable feature in the distance then the compass can go back in your pocket. If visibility poor or nil use a rope and a runner to go ahead and caste about till the runner on the desired bearing. Then move to the stationary runner following the tight rope. If no rope use same method but go by sight, not letting the runner out of your sight you position him in line with the travel arrow.
====f. What is Slipping and how to correct for it?====
When traveling on a compass bearing large obstacles or the lie of the land can put you off course usually with out you knowing. The result is that after the obstacle you are really traveling on a parallel course to that you started on. This is called slipping.
To correct this you need to have the starting point in view. So without adjusting the compass turn around to point in the general direction of the starting point. Then move sideways so that the needle (south end) points to the orientation arrow. You are now in the original line and can continue on course. If the starting point is not visible you would have to find your true position by doing a resection and then moving to where you should be so you can continue on the original course.
====g. How to take a back bearing ====
Used to check back where you have come from. The bearing should be 180 deg different or the compass can be turned around so that the white end of needle aligns with the orienting arrow. (Check for slipping)
===2.5. Know and explain the following in relation to Resection. ===
====a. What is resection?====
Used to locate your position on a map by locating major recognisable land features and working out where you are.
====b. The two-bearing method of Resection. ====
Take two back bearings from known features. Remember to transfer backward for G-MA. The point where the two or more bearings cross is your location. Of course is accuracy is not an issue you could look at the features around you and find them on the map and work out where you are in relation to the sighted features.
====c. The three-bearing method of Resection. ====
The same as above but using three features. The more apart they are the better.
===2.6. Know and explain how to Orient your map by===
====a. inspection and ====
Have a good look about you.. Mountain peaks, passes, rivers valleys. Put map on ground turn ot about to get it to match what is about you.
====b. by compass.====
Work out your particular GM-A
Set the compass housing to the G-MA so that the compass replicates the north arrow diagram: that is, the direction of travel arrow points generally along the grid north arrow and the orienting arrow points generally along the magnetic arrow.
Leaving the compass set, place it anywhere on the map with the long edge along one of the grid lines and with the direction of travel arrow pointing to Grid North. Disregard the compass needle.
Without moving the compass, rotate the map until the North end of the compass needle aligns over the orienting arrow.
==Section Three – Direction without the aid of a Compass==
===3.1 Demonstrate how to find directions without a compass using the Southern Cross (ie. Crux) method===
I have also included a couple other methods as well for daytime and night as extra bonus material.
====1. Watch.====
Southern Hemisphere method only.Point the 12 to the sun. Halfway between the hour hand and the 12 is North. You still have to use your intelligence for this as early morning time and evening time care must be taken as to which half you use. E.g. 8am sun is rising in the East; point 12 to the sun North is halfway between the 8 and the 12 at the 10. BUT late evening the sun is heading to set in the west say time is 8pm you point the 12 at the sun. North is halfway between the 8 and the 12 at the other side of watch at the 4. This should be used only as a guide as in some countries the real time has been adjusted and sometimes there is daylight saving time etc.
I use this method as it saves getting out the compass or even carrying one. One draw back is that you do need to know where the sun is. Usually when you are lost it is getting dark and there is no sun.
====2. Southern Cross. ====
[[Image:crux.jpg|thumb|Crux]]
With the lack of a significant pole star in the southern sky (Sigma Octantis is closest to the pole, but is too faint to be useful for the purpose), two of the stars of Crux (Alpha and Gamma, Acrux and Gacrux respectively) are commonly used to mark south. Following the line defined by the two stars for approximately 4.5 times the distance between them leads to a point close to the Southern Celestial Pole.
Alternatively, if a line is constructed perpendicularly between Alpha Centauri and Beta Centauri, the point where the above line and this line intersect marks the Southern Celestial Pole. The two stars are often referred to as the "Pointer Stars" or "White Pointers", allowing people to easily find the top of Crux.
The junction of these two lines is the SCP Southern Celestial Pole. If you were at the South Pole this would be directly above you. This is the point where the night sky revolves around. Point to this spot then lower your arm to the horizon. Where you are pointing is South.
This is the only method I use at night. The crux is easy to find usually, as long as you are not in a valley which blocks out the essential constellation.
====3. Orion====
[[image:Orion-guide dark.svg|thumb|220px|left| Orion constellation]]
Orion is not visible all year in the southern hemisphere
To find south we need to look to Orion. Best when it is high in the sky. Find the head stars belt and sword. The line of the sword points closely to the Southern celestial pole (SCP) The line of the sword depending where you are will not point to south and as the night progresses further off the North South line. So to use Orion as a navigational tool you will have to know where the SCP actually is so to do this use the method determined in finding South by use of the Southern Cross. Once you have determined where the SCP is in relation to you point at it then drop your arm to the horizon you are pointing to South.
I never use this method.
====4. Shadow Stick.====
This method can be a waste of time. We all know the sun rises in the East and sets in the West. The stick shadow shows you this. Also when the sun is at its zenith the highest it gets in the Southern Hemisphere look at the sun and it is towards the North the opposite in the Northern Hemisphere. So we learn that at midday is the best time to find North (or South).
But if you must... place a stick in the ground on an open area. Mark the shadows at times through out the day. From this you can find North or South (depending what side of the equator you are on) from the shortest shadow and also East and West by drawing a line from the ends of the longest shadows assuming you had an early morning and late evening marking with equal time from mid-day. But for this you have to be lucky to have sunshine for most of the day, which usually is not the case if you are lost. Anyhow it is something to know if you do not have a watch to know when real time mid-day is and you have a full day to hang about.
An alternative method to this as suggested to me by a major contributor to these pages.
Get a stick. Point the stick end to the sun while pushing stick into the ground so it free stands. Observe the shadow in the first 15 minutes. The base line of the shadow will be the East West line. A perpendicular line off the base line towards the sun side will be North. Over a longer period you will be more accurate.
==Section Four – Practical ==
===4.1. Demonstrate how to===
====a. Read six figure Grid Refences. Refer to Requirement 1.6c.====
====b. Calculate a Grid Bearing from the map. Refer to Requirement 2.4b.====
====c. Convert Grid Bearing to a Magnetic Bearing. Refer to Requirement 2.4c.====
====d. Take a Magnetic Bearing. Refer to Requirement 2.4c====
====e. Locate a position using Resection. Refer to Requirement 2.5====
===4.2. Navigate to a target feature using a Magnetic Bearing. Refer Requirement 2.4c===
===4.3. Prove your ability in the use of a map and compass by following a cross-country course with at least ten given readings or control points.===
===Keep a log detailing===
====*Grid reference====
====*Grid and Magnetic Bearings====
====*Records of actual course taken====
The exercise is not the ability to travel exactly on a bearing between the two points, this is usually impossible in rough wilderness areas. Following an established trail or not so established between the two points would be permissible.
It is not the intention of the honour that the terrain is almost impassable. Remember to have the safety of the participants in mind. There is no set distance for this 10 stage course. It is suggested that controls be more than 200m apart but the next control not visible from previous control.
Have lots of fun and save lots of memories.
==References==
[[{{BOOKCATEGORY|Adventist Youth Honors Answer Book}}/Completed Honors|{{SUBPAGENAME}}]]
j8vxxdm6xhkta3tymle04piuv09lhsf
Structural Biochemistry/Proteins/Protein Folding
0
174044
4675967
4667854
2026-10-14T05:27:09Z
Jcb
90773
4675967
wikitext
text/x-wiki
'''Protein folding''' is a process in which a polypeptide folds into a specific, stable, functional, three-dimensional structure. It is the process by which a protein structure assumes its functional shape or conformation
[[Structural Biochemistry/Proteins|Proteins]] are formed from long chains of [[Structural Biochemistry/Proteins/Amino Acids|amino acids]]; they exist in an array of different structures which often dictate their functions. Proteins follow energetically favorable pathways to form stable, orderly, structures; this is known as the proteins’ native structure. Most proteins can only perform their various functions when they are folded. The proteins’ folding pathway, or mechanism, is the typical sequence of structural changes the protein undergoes in order to reach its native structure. Protein folding takes place in a highly crowded, complex, molecular environment within the cell, and often requires the assistance of molecular chaperones, in order to avoid aggregation or misfolding. Proteins are comprised of amino acids with various types of side chains, which may be hydrophobic, hydrophilic, or electrically charged. The characteristics of these side chains affect what shape the protein will form because they will interact differently intramolecularly and with the surrounding environment, favoring certain conformations and structures over others. Scientists believe that the instructions for folding a protein are encoded in the sequence. Researchers and scientists can easily determine the sequence of a protein, but have not cracked the code that governs folding (Structures of Life 8).
== Protein Folding Theory and Experiment ==
Early scientists who studied [http://en.wikipedia.org/wiki/Proteomics proteomics] and its structure speculated that proteins had templates that resulted in their native conformations. This theory resulted in a search for how proteins fold to attain their complex structure. It is now well known that under physiological conditions, proteins normally spontaneously fold into their native conformations. As a result, a protein's primary structure is valuable since it determines the three-dimensional structure of a protein. Normally, most biological structures do not have the need for external templates to help with their formation and are thus called [http://en.wikipedia.org/wiki/Self_assembly self-assembling].
=== Protein Renaturation ===
Protein renaturation known since the 1930s. However, it was not until 1957 when [http://en.wikipedia.org/wiki/Christian_Anfinsen Christian Anfinsen] performed an experiment on bovine pancreatic [http://en.wikipedia.org/wiki/Ribonuclease_A RNase A] that protein renaturation was quantified. RNase A is a single chain protein consisting of 124 residues. In 8M urea solution of 2-mercaptoethanol, the RNase A is completely unfolded and has its four disulfide bonds cleaved through reduction. Through [http://en.wikipedia.org/wiki/Dialysis_(biochemistry) dialysis] of urea and introducing the solution to O2 at pH 8, the enzymatically active protein is physically incapable of being recognized from RNase A. As a result, this experiment demonstrated that the protein spontaneously renatured.
One criteria for the renaturation of RNase A is for its four disulfide bonds to reform. The likelihood of one of the eight Cys residues from RNase A reforming a disulfide bond with its native residue compared to the other seven Cys residues is 1/7. Furthermore, the next one of remaining six Cys residues randomly forming the next disulfide bond is 1/5 and etc. As a result, the probability of RNase A reforming four native disulfide links at random is (1/7 * 1/5 * 1/3 * 1/1 = 1/105). The result of this probability demonstrates that forming the disulfide bonds from RNase A is not a random activity.
When RNase A is reoxidized utilizing 8M urea, allowing the disulfide bonds to reform when the polypeptide chain is a random coil, then RNase A will only be around 1 percent enzymatically active after urea is removed. However, by using 2-mercaptoethanol, the protein can be made fully active once again when disulfide bond interchange reactions occur and the protein is back to its native state. The native state of the RNase A is thermodynamically stable under physiological conditions, especially since a more stable protein that is more stable than that of the native state requires a larger [http://en.wikipedia.org/wiki/Activation_barrier activation barrier], and is kinetically inaccessible.
By using the enzyme [http://en.wikipedia.org/wiki/Protein_disulfide_isomerase protein disulfide isomerase (PDI)], the time it takes for randomized RNase A is minimized to about 2 minutes. This enzyme helps facilitate the disulfide interchange reactions. In order for PDI to be active, its two active site Cys residues needs to be in the -SH form. Furthermore, PDI helps with random cleavage and the reformation of the disulfide bonds of the protein as it attain thermodynamically favorable conformations.
=== Posttranslationally Modified Proteins Might Not Renature ===
Proteins in a "scrambled" state go through PDI to renature, and their native state does not utilize PDI because native proteins are in their stable conformations. However, proteins that are posttranslationally modified need the disulfide bonds to stabilize their rather unstable native form. One example of this is [http://en.wikipedia.org/wiki/Insulin insulin], a polypeptide hormone. This 51 residue polypeptide has two disulfide bonds that is inactivated by PDI. The following link is an [http://www.littletree.com.au/images/dna4.jpg image showing insulin with its two disulfide bonds]. Through observation of this phenomenon, scientists were able to find that insulin is made from [http://en.wikipedia.org/wiki/Proinsulin proinsulin], an 84-residue single chain. This [http://www.bio.davidson.edu/courses/molbio/molstudents/spring2005/dresser/my%20favorite%20protein.html link] provides more information on the structure of proinsulin and its progression on becoming insulin. The disulfide bonds of proinsulin need to be intact before conversion of becoming insulin through [http://en.wikipedia.org/wiki/Proteolysis proteolytic excision] of its C chain which is an internal 33-residue segment. However, according to two findings, the C chain is not what dictates the folding of the A and B chains, but instead holds them together to allow formation of the disulfide bonds. For one, with the right renaturing conditions in place, scrambled insulin can become its native form with a 30% yield. This yield can be increased if the A and B chains are cross-linked. Secondly, through analysis of sequences of proinsulin from many species, mutations are permitted at the C chain eight times more than if it were for A and B chains.
== Determinants of Protein Folding ==
There are various interactions that help stabilize structures of native proteins. Specifically, it is important to examine how the interactions that form protein structures are organized. In addition, there are only a small amount of possible polypeptide sequences that allow for a stable conformation. Therefore, it is evident that specific sequences are used through evolution in biological systems.
== Helices and Sheets Predominate in Proteins because They Efficiently Fill Space ==
On average, about sixty percent of proteins contain a high amount of [http://en.wikipedia.org/wiki/Alpha_helices alpha helices], and [http://en.wikipedia.org/wiki/Beta_pleated_sheet beta pleated sheets]. Through hydrophobic interactions, the protein is able to achieve compact nonpolar cores, but they lack the ability to specify which polypeptides to restrict in particular conformations. As seen in polypeptide segments in the coil form, the amount of hydrogen boding is not lesser than that of alpha helices and beta pleated sheets. This observation demonstrates that the different kinds of conformations of polypeptides are not limited by hydrogen bonding requirements. [http://en.wikipedia.org/wiki/Ken_A._Dill Ken Dill] has suggested that helices and sheets occur as a result of the [http://en.wikipedia.org/wiki/Steric_effects steric hindrance] in condensed polymers. Through experimentation and simulation of conformations with simple flexible chains, it can be determined that the proportion of beta pleated sheets and alpha helices increase as the level of complication of chains is increased. Therefore, it can be concluded that helices and sheets are important in the complex structure of a protein, as they are compact in protein folding. The coupling of different forces such as [http://en.wikipedia.org/wiki/Hydrogen_bonding hydrogen bonding], ion pairing, and [http://en.wikipedia.org/wiki/Van_der_Waals_force van der Waals interactions] further aids in the formation of alpha helices and beta sheets.
== Protein Folding is Directed by Internal Residues ==
By investigating protein modification, the role of different classes of amino acid residues in protein folding can be determined. For example, in a particular study the free primary amino groups of RNase A were [http://en.wikipedia.org/wiki/Derivatization derivatized] with poly-DL-alanine which consist of 8 residue chains. The poly-Ala chains are large in size and are water-soluble, thus allowing the RNase's 11 free amino groups to be joined without interference of the native structure of the protein or its ability to refold. As a result, it can be concluded that the protein's internal residues facilitates its native conformation because the RNase A free amino groups are localized on the exterior. Furthermore, studies have shown that mutations that occur on the surface of residues are common, and less likely to change the protein conformation compared to changes of internal residues that occur. This finding suggests that protein folding is mainly due to the [http://en.wikipedia.org/wiki/Hydrophobic_effect hydrophobic forces].
== Protein Structures Are Hierarchically Organized ==
George Rose demonstrated that protein domains consisted of subdomains, and furthermore have sub-subdomains, and etc. As a result, it is evident that large proteins have domains that are continuous, compact, and physically separable. When a polypeptide segment within a native protein is visualized as a string with many tangles, a plane can be seen when the string is cut into two segments. This process can be repeated when n/2 residues of an n-residue domain is highlighted with a blue and red color. As this process is repeated it can be seen that at all stages, the red and blue areas of the protein do not interpenetrate with one another. The following [http://www.nd.edu/~aseriann/CHAP9B.html/sld005.htm link] shows an X-ray structure of HiPIP (high potential iron protein) and its first n/2 residues on the n-residue protein colored red and blue. Furthermore, the subsequent structures shown in the second and third row show this process of n/2 residue splitting reiterated as shown where the left side of the protein has its first and last halves with red and blue while the rest of the chain colored in gray. Through this example, it is clearly seen that protein structures are organized in a hierarchical way, meaning that the polypeptide chains are seen as sub-domains that are themselves compact structures and interact with adjacent structures. These interactions forms a larger well organized structure largely due to [http://en.wikipedia.org/wiki/H_bond hydrogen bonding interactions] and has an important role in understanding how [http://en.wikipedia.org/wiki/Peptide polypeptides] fold to form their native structure.
== Protein Structures are Adaptable ==
Since the [http://en.wikipedia.org/wiki/Side_chain side chains] inside [http://en.wikipedia.org/wiki/Globular_protein globular proteins] fit together with much complementary its packing density can be almost like that of organic crystals. As a result, in order to confirm whether or not this phenomenon of high packing density was an important factor in contributing to protein structure, Eaton Lattman along with George Rose attempted to verify if there was an interaction between side chains that was preferred in a globular protein. They analyzed a total of 67 well studied structures of globular proteins, and concluded that there were no preferred interactions. This experiment demonstrated that packing is not what directs the native fold, but instead the native fold is necessary for packing of a globular protein. This notion can be further supported as members of a protein family result in the same fold despite their lack of sequence similarity and distant relationships.
In addition, structural experimental data have shown that there are a variety of ways that a protein's internal residues can become compact together in an efficient manner. In an extensive study done by [http://en.wikipedia.org/wiki/Brian_Matthews_(biochemist) Brian Matthews] based on T4 lysozyme, which is produced by [http://en.wikipedia.org/wiki/Enterobacteria_phage_T4 bacteriophage T4], it was found that changes in the residues of the T4 lysozyme only affected local shifts and did not result in any global structure change. The following [http://ambermd.org/tutorials/advanced/tutorial9/ link] gives an X-ray view of T4 lysozyme and a brief biochemical description of the structure. Matthews took over 300 different mutants of the 164 residue T4 lysozyme, and compared them with one another. Also, it was observed that the T4 lysozyme could withstand insertions of about 4 residues while still not having any major structural changes to the overall protein structure nor enzyme activity. Furthermore, by using assay techniques it was demonstrated that only 173 of the mutants in T4 of the 2015 single residue substitutions done had significant amounts of enzymatic activity diminished. Through these experiments, it is evident that protein structures are extremely withstanding.
== The Levinthal Paradox ==
Levinthal's paradox is a thought experiment, also constituting a self-reference in the theory of protein folding. In 1969, Cyrus Levinthal noted that, because of the very large number of degrees of freedom in an unfolded polypeptide chain, the molecule has an astronomical number of possible conformations. An estimate of 3<sup>300</sup> or 10<sup>143</sup> was made in one of his papers.
The Levinthal paradox observes that if a protein were folded by sequentially sampling of all possible conformations, it would take an large amount of time to do so, even if the conformations were sampled at a rapid rate . Based upon the observation that proteins fold much faster than this, Levinthal then proposed that a random conformational search does not occur, and the protein must, therefore, fold through a series of meta-stable intermediate states.
In 1969 Cyrus Levinthal calculated that if a protein were to randomly sample every possible conformation as it folded from the unfolded state to the native state it would take an astronomical amount of time, even if the protein reached 100 billion conformations in one second. Observing that proteins fold in a relatively short amount of time, Levinthal proposed that proteins fold in a fixed and directed process. We now know that while protein folding is not a random process there does not seem to be a single fixed protein folding pathway.This observation came to be known as the Levinthal paradox. This paradox clearly reveals that proteins do not fold by trying every possible conformation. Instead, they must follow at least a partly defined folding pathway made up of intermediates between the fully denatured proteins and its native structure.
== Cumulative Selection ==
The way out of the Levinthal Paradox is to recognize cumulative selection. According to Richard Dawkins, he asked how long it would take a monkey poking randomly at a typewriter to reproduce "Methinks it is like a weasel", Hamlet's remark to Polonius. A large number of keystrokes, of the order of 10<sup>40</sup> would be required. Yet if we suppose that each correct character was preserved, allowing the monkey to retype only the wrong ones, only a few thousand keystrokes, on average, would be needed. The crucial difference between these scenarios is that the first utilizes a completely random search whereas in the second case, partly correct intermediates are retained. This also reveals that the essence of protein folding is the tendency to retain partly correct intermediates, although the protein-folding problem is much more difficult than the one presented to Shakespeare example above.
== Nucleation-Condensation model ==
In order to correctly understand the protein-folding problem, we must consider certain characteristics of protein. Since proteins are only marginally stable, the free-energy difference between the folded and the unfolded states of a typical 1000-residue protein is 42 kJ mol<sup>−1</sup> and thus each residue contributes on average only 0.42 kJ mol<sup>−1</sup> of energy to maintain the folded state. This amount is less than the amount of thermal energy, which is 2.5 kJ mol<sup>−1</sup> at room temperature. This meagre stabilization energy means that correct intermediates, especially those formed early in folding, can be lost. The interactions that lead to cooperative folding, nonetheless, can stabilize intermediates as structure builds up. Thus, local regions that have significant structural preference, though not necessarily stable on their own, will tend to adopt their favored structures and, as they form, can interact with one other, resulting in increased stabilization. Nucleation-condensation model refers to this conceptual framework in solving the protein-folding challenge.
== Intramolecular Interactions Role in the Folding Mechanism ==
[[Structural Biochemistry/Proteins|Proteins]] folding forms energetically favorable structures stabilized by [[Structural Biochemistry/Chemical Bonding/Hydrophobic interaction|hydrophobic interactions]] clumping, [[Structural Biochemistry/Chemical Bonding/Hydrogen bonds|hydrogen bonding]] and [[Structural Biochemistry/Chemical Bonding/Van der Waals interaction|Van der Waals forces]] between [[Structural Biochemistry/Proteins/Amino Acids|amino acids]]. Protein folding first forms secondary structures, such as alpha helices, beta sheets, and loops. Different amino acids have different tendencies for whether they are going to form Alpha Helices, Beta sheets, or Beta Turns based upon polarity of the amino acid and rotational barriers. For example, the amino acids, valine, threonine, isoleucine, tend to destabilize the alpha helices due to steric hindrance. Thus, they prefer conformational shifts towards Beta sheets rather than alpha helices. The relative frequencies of the amino acids in secondary structures are grouped according to their preferences for alpha helices, beta sheets or turns (Table 1).
[http://imageshack.us/photo/my-images/803/screenshot20121028at940.png/ Table 1: Relative frequencies of amino acid residues in secondary structures]
These structures in turn, fold to form tertiary structures, stabilized by the formation of intramolecular hydrogen bonds. [[Structural Biochemistry/Chemical Bonding/Covalent bonds|Covalent]] bonding may also occur during the folding to a tertiary structure, through the formation of disulfide bridges or metal clusters. According to Robert Pain’s “Mechanisms of Protein Folding”, molecules also often pass through an intermediate “molten globule” state formed from a hydrophobic collapse (in which all hydrophobic side-chains suddenly slide inside the protein or clump together) before reaching their native confirmation. However, this means all the main chain NH and CO groups are buried in a non-polar environment, but they prefer an aqueous one, so secondary structures must fit together very well, so that the stabilization through hydrogen bonding and [[Structural Biochemistry/Chemical Bonding/Van der Waals interaction|Van der Waals forces]] interactions overrides their hydrophilic tendencies. The strengths of hydrogen bonds in a protein vary depending on their position in the structure; H-bonds formed in the hydrophobic core contribute more to the stability of the native state than H-bonds exposed to the aqueous environment.
Water-soluble proteins fold into compact structures with non-polar, hydrophobic cores. The inside of protein contains non-polar residues in center (i.e. - leucine, valine, methionine and phenylalanine), while the outside contains primarily polar, charged residues (i.e. - aspartate, glutamate, lysine and arginine). This way the polar, charged molecules can interact with the surrounding water molecules while the hydrophobic molecules are protected from the aqueous surroundings. Minimizing the number of hydrophobic side chains on the outer part of the structure makes the protein structure thermodynamically more favorable because the hydrophobic molecules prefer to be clumped together, when surrounded by an aqueous environment (i.e. – hydrophobic effect). Proteins that span biological membranes (i.e. - porin) have an inside out distribution, with respect to the water-soluble native structure, they have hydrophobic residue covered outer surfaces, with water filled centers lined with charged and polar amino acids.
== Folding of Membrane Proteins ==
In “Folding Scene Investigation: Membrane Proteins”, a paper written by Paula J Booth and Paul Curnow, the authors attempt to answer how the folding mechanisms of integral membrane proteins with α helical structures work.
Studying the folding of membrane proteins has always been difficult as these proteins are generally large and made of more than one subunit. The proteins possess a high degree of conformational flexibility—which is necessary for them to perform their function in the cell. Also, these proteins have both hydrophobic surfaces, facing the membrane, and hydrophilic surfaces, facing the aqueous regions on either side of the membrane. The proteins are move laterally and share the elastic properties of the lipid bilayer in which they are embedded. In order to study these proteins, Booth and Curnow believe that one must manipulate the lipid bilayer and combine kinetic and thermodynamic methods of investigation.
'''Reversible Folding and Linear Free Energy'''
The free energy of protein folding is measured by reversible chemical denaturation. The reversible folding of a protein depends on this free energy. For the α helix proteins that were being studied, it was proven that a reversible, two-state process is followed. bR (a α helical membrane protein called bacteriorhodopsin) reversibly unfolds if SDS (a denaturant which is an anionic detergent) is added to mixed lipid, detergent micells. The two-state reaction involves a partly unfolded SDS state and a folded bR state.
By comparing the logs of the unfolding and folding rate, and the SDS mole fraction, a linear plot was generated proving a linear relationship. This plot proved that bR had a very high stability outside of its membrane—proving that it was unexpectedly stable. Furthermore, bR was so stable outside of the membrane that it would not unfold during a reasonable period of time without addition of denaturant.
'''Comparison with Water-Soluble Proteins'''
Booth and Curnow studied the 3 membrane proteins about which the most information is held: bR, DGK (Escherichia coli diacylglycerol kinase) and KcsA (Sterptococcus lividans potassium channel). These three membrane proteins were compared to water-soluble proteins (which fold by 2 or 3 state kinetics).
The overall free energy change of unfolding in the absence of denaturant was the same for water-soluble proteins and membrane proteins of similar size. This proves that it is the balance of weak forces rather than the types of forces that stabilize the protein that determines its stability. It was proven that H-bonds in the membrane proteins were of similar strength to those of the water-soluble proteins, rather than being stronger in membrane proteins as was expected.
'''Mechanical Strength and Unfolding Under Applied Force'''
Dynamic force microscopy can be used to measure the mechanical response of a particular region of a protein under applied force. The unfolding force in this case depends on the activation barrier. This unfolding has nothing to do with the thermodynamic stability of a protein.
For unfolding under applied force, the membrane proteins (especially bR) seem to follow the rules of Hammond behavior. The energy difference between two consecutive states of this reaction is reduced and the states become similar in structure.
'''Influence of Surrounding Membrane'''
Membrane proteins are influenced greatly by the membranes they are surrounded by. If the lipids incorporate in detergent micells—-increasing the stability of the lipid structure—both the protein and its folding are stabilized. Different combinations of different lipids can result in different stabilities or folding of membrane proteins. The size of the membrane can also affect the membrane protein.
Different types of lipids cause different membrane properties. A type of lipids called PE lipids have higher spontaneous curvatures than a second type of lipid called a PC lipid. By adding PE lipids to PC lipids the monolayer curvature of the bilayer increases. Increasing the curvature of the lipid bilayer increases the stability of the protein folding.
==Protein translocation in biological membranes==
In [[Structural Biochemistry/Cell Organelles/Mitochondria|mitochondria]], the proteins that are made from the ribosomes are directly take in from the cytosol. Mitochondrial proteins are first completely synthesized in the cytosol as mitochondrial precursor proteins, then taken up into the [[Structural Biochemistry/Lipids/Biological Membranes|membrane]]. The Mitochondrial proteins contain specific signal sequence at their N terminus. These signal sequences are often removed after entering the membrane but proteins entering membranes that has outer, inner, inter membrane have internal sequences that play a major movement in the translocation within the inner membrane.
Protein translocation plays a major role in translocating proteins across the mitochondrial membranes. Four major multi-subunit protein complexes are found in the outer and the inner membrane. TOM complexes are found in the outer membrane, and two types of TIM complexes are found integrated within the inner membrane: TIM23 and TIM22. The complexes act as receptors for the mitochondrial precursor proteins.
TOM: imports all [[Structural Biochemistry/Cell Organelles/Nucleus|nucleus]] encoded proteins. It primarily starts the transport of the signal sequence into the inter membrane space and inserts the transmembrane proteins into outer membrane space. A Beta barrel complex called the SAM complex is then in charge of properly folding the protein in the outer membrane. TIM23 found in the inner membrane moderates the insertion of soluble proteins into the matrix, and facilitates the insertion of transmembrane proteins into the inner membrane. TIM23, another inner membrane complex facilitates the insertion inner membrane proteins comprised of transporters that move ADP, ATP, and phosphate across the mitochondrial membranes. OXA, yet another inner membrane complex, helps insert inner membrane proteins that were synthesized from the mitochondria itself and the insertion of inner membrane proteins that were first transported into the matrix space.
[[Image:translocation.jpg]]
== Folding on Ribosome ==
The place where the protein chain begins to fold is a topic that is greatly studied. As the nascent chain goes through the “exit tunnel” of the ribosome and into the cellular environment, when does the chain begin to fold? The idea of cotranslational folding in the ribosomal tunnel will be discussed. The nascent chain of the protein is bound to the peptidyl transferase centre (PTC) at its C terminus and will emerge in a vectorial manner. The tunnel is very narrow and enforces a certain rigidity on the nascent chain, with the addition of each amino acid the conformational space of the protein increases. Co translational folding can be a big help in reducing the possible conformational space by helping the protein to acquire a significant level of native state while still in the ribosomal tunnel. The length of the protein can also give a good estimate of its three dimensional structure. Smaller chains tend to favor beta sheets while longer chains (like those reaching 119 out of 153 residues) tend to favor the alpha helix.
The ribosomal tunnel is more than 80 Å in length and its width is around 10-20 Å. Inside the tunnel are auxiliary molecules like the L23, L22, and L4 proteins that interact with the nascent chain help with the folding. The tunnel also has hydrophilic character and helps the nascent chain to travel through it without being hindered. Although rigid, the tunnel is not passive conduit but whether or not it has the ability to promote protein folding is unknown. A recent experiment involving cryoEM has shown that there are folding zones in the tunnel. At the exit port (some 80 Å from the PTC), the nascent chain has assumed a preferred low order conformation. This enforces the suggestion that the chain can have degrees of folding at certain regions. Although some low order folding can occur, the adoption of the native state occurs outside the tunnel, but not necessarily when the nascent chain has been released. The bound nascent chain (RNC) adopts partially folded structure and in a crowded cellular environment, this can cause the chain to self-associate. This self-association, however, is relieved with the staggered ribosomes lined along the exit tunnel that maximizes the distances between the RNC.
'''Generation of RNC for studies:'''
One technique of generating RNC and taking snapshots as it emerges from the tunnel is to arrest translation. A truncated DNA without a termination sequence is used. This allows for the nascent chain to remain bound until desired. To determining the residues of the chain, they can be labeled by carbon-13 or nitrogen-15 and later detected by NMR spectroscopy. Another technique is the PURE method and it contains the minimal components required for translation. This method has been used to study the interaction of the chains and auxiliary molecules like the TF chaperone. This method is coupled with quartz-crystal microbalance technique to analyze the synthesis by mass. An in vivo technique in generating RNC chain can be done by stimulating it in a high cell density. This is initially done in an unlabeled environment, the cells are then transferred to a labeled medium. The RNC is generated by SecM. The RNC is purified by affinity chromatography and detected by SDS-PAGE or immunoblotting.
By generating the RNCs, many experiments can be done to study more about the emerging nascent chain. As mentioned above, the chain emerges from the exit tunnel in a vectorial manner. This enables the chain to sample the native folding and increases the probability of folding to the native state. Along with this vectorial folding, chaperones also help in favorable folding rates and correct folding.
== Protein Folding in the Endoplasmic Reticulum ==
'''Protein Entering the Mammalian ER:'''
The endoplasmic reticulum (ER) is a main checkpoint for protein maturation to ensure that only correctly folded proteins are secreted and delivered to the site of action. The protein entrance to the ER begins with recognition of a N’ terminus signal sequence. Specially, this sequence is detected by a signal recognition protein (SRP) causing the ribosome/nascent chain/SRP complex bind to the ER membrane. Then, the complex travels through a proteinaceous pore called Sec61 translocon which allows the polypeptide chain enter the lumen portion of the ER.
'''Processes in Conflict During Protein Folding:'''
After the protein enters the ER, the proteins break up into an ensemble of folding intermediates. These intermediates take three different routes. They are either folded properly and sent to be exported out of the endoplasmic reticulum (ER) into the cytosol, aggregated or picked out for degradation. These three processes are in competition to properly secrete a protein. In order for a protein to be properly secreted, the competition between folding, aggregation and degradation must be in favor of folding, so that folding occurs faster than the other processes. This balance is termed proteostasis. The balance of proteostasis can be tipped in favor of folding by either using smaller molecules to stabilize the protein (called co-factors) or increasing the concentrations of folding factors. This ability to control proteostasis allows scientists the power to overcome some of the protein folding diseases such as cystic fibrosis.
The proteins that are folded properly are ready for anterograde transport, and secreted through the membrane of the ER into the cytosol by a cargo receptor that recognizes the properly folded protein. The proteins that are incorrectly folded are not secreted and are either targeted for degradation or aggregated. The aggregated proteins are able to re-enter the stage of protein ensembles ready to be folded so that they may try again at being folded properly.
[[File:Protein in ER.jpg|thumb|Protein Folding in ER]]
'''Folding Factors in the Endoplasmic Reticulum:'''
Biochemical research on folding pathways has provided a comprehensive list of folding factors, or chaperones, involved with protein folding in the ER. Folding factors are categorized based on whether they catalyze certain steps or if they interact with intermediates in the folding pathway. General protein folding factors are typically separated into four different groups: heat shock proteins as chaperones or cochaperones, peptidyl prolyl cis/trans isomerases (PPIases), oxidoreductases, and glycan-binding proteins.
Many folding factors are great in that they are multi-functional. One folding factor can take care of different areas of the folding pathway. Unfortunately, this leads to redundancy due to different classes of proteins carrying out overlapping functions. This functional redundancy complicates the understanding of the specific roles of individual folding factors in aiding maturation of client proteins. Folding factors also prefer to act in concert during the maturation process, which further obscures the individual roles of each factor. Since these roles are not clear, it is difficult to confirm that even if one folding factor deals with a particular reaction in one protein, that same folding factor will carry out the same function in another.
In addition to aiding non-covalent folding and unfolding of proteins, folding factors in the ER sometimes delay interactions with the protein. This allows time for nascent proteins to fold properly and enables folded proteins to backtrack on its folding pathway, which prolongs equilibrium in a less folded state, preventing the protein from being held in a non-native state.
'''Folding after Endoplasmic Reticulum:'''
Although ER provides only correctly assembled proteins to be secreted, some examples exist in which proteins change conformation in the Golgi bodies and beyond. Typically, newly folded proteins are sensitive and prone to unfolding while in the ER but resistant to unfolding after exit. In an environment without chaperones and other folding enzymes, proteins are compact and relatively resistant to change after exiting the ER. However, this doesn’t necessarily mean that protein folding ends because some molecular chaperones like Hsp 70s and Hsp 90s continue to assist in protein conformation throughout the protein’s existence.
[[File:Table of Folding Factors in ER.jpg|thumb|Folding Factors in the ER and their Functions]]
== Techniques for Studying Protein Folding ==
A strategy for studying the folding of proteins is to unfold the protein molecules in high concentrations of a chemical denaturant like guanidinium chloride. The solution is then diluted rapidly until the denaturant concentration is lowered to a level where the native state is thermodynamically stable again. Afterwards, the structural changes of the protein folds may be observed. In theory, this sounds simple. However, such experiments are complex, since unfolded proteins have random coil states in chemical denaturants. Moreover, analyzing the structural changes taking place in a sample may is difficult, since all of the molecules may have significantly different conformations until the final stages of a reaction. As such, the analysis would have to be performed in a matter of seconds rather than days or weeks that are normally allowed to deduce the structure of a single conformation of a native protein. To avoid this problem, the disulphide bonds can be reduced after the protein is unfolded and reformed under oxidative conditions. The protein can then be identified by standard techniques such as mass spectroscopy to draw conclusions about the structure present at stages of folding where disulfide bonds are formed.
Multiple techniques are used to monitor structural changes during the refolding. For instance, in circular dichorism, UV is used from far away to provide a measurement of the appearance of the secondary structure during folding. UV at a close distance monitors the formation of the close-packed environment for aromatic residues. [[Structural Biochemistry/Proteins/NMR Spectroscopy|NMR]] is also a useful technique for characterizing conformations at the level of individual amino-acid residues. It can also be used to monitor how the development of structures protect amide hydrogens from solvent exchanges.
'''Circular Dichroism:''' This type of spectroscopy measures the absorption of circularly polarized light since the structures of protein such as the alpha helix and beta sheets are chiral and can absorb this sort of light. The absorption of light indicates the degree of the protein’s foldedness. This technique also measures equilibrium unfolding of protein by measuring change of absorption against denaturant concentration or temperature. The denaturant melt measures the free energy of unfolding while the temperature melt measures the melting point of proteins. This technique is the most general and basic strategy for studying protein folding.
'''Dual Polarization Interferometry:''' This technique uses an evanescent wave of a laser beam confined to a waveguide to probe protein layers that have been absorbed to the surface of the waveguide. Laser light is focused on two waveguides, one that senses the beam and has an exposed surface, and one that is used to create a reference beam and to excite the polarization modes of the waveguides. The measurement of the interferogram can help calculate the protein density or fold, the size of the absorbed layer, and to infer structural information about molecular interactions at the subatomic resolution. A two-dimensional pattern is obtained in the far field when the light that has passed through the two waveguides is combined.
'''Mass Spectrometry:''' The advantages of using [[Structural Biochemistry/Protein sequence determination techniques/Mass Spectroscopy|Mass Spectroscopy]] to study protein folding include the ability to detect molecules with different amounts of deuterium, which allows the heterogeneity of the protein folding reactions to be studied. It can also measure the conformation of folding intermediates bound to molecular chaperones without disrupting the complex. Mass spectrometry can also directly compare refolding properties, since mixtures of proteins can be studied without separation if the two proteins have sufficiently different molecular weights.
'''High Time Resolution:''' These are fast time-resolved techniques where a sample of unfolded protein is triggered to fold rapidly. The resulting dynamics are then studied. Ways to accomplish this include fast mixing of solutions, photochemical methods, and laser temperature jump spectroscopy.
'''Computational Prediction of Protein Tertiary Structure:''' This is a distinct form of protein structure analysis in that it involves protein folding. These programs can simulate the lengthy folding processes, provide information on statistical potential, and reproduce folding pathways.
== Protein Misfolding ==
Protein misfolding refers to the failure of a protein to achieve its tightly packed native conformation efficiently or the failure to maintain that conformation due to reduction in stability as a result of environmental change or mutation. It has been established that failure of protein folding is a general phenomenon at elevated temperatures and under other stressful circumstances. The two most common results of misfolded proteins are degradation and aggregation. When a polypeptide emerges from the cell, it may fold to the native state, degraded by proteolysis, or form aggregates with other molecules. Proteins are in constant dynamic equilibrium so even if the folding process is complete, unfolding in the cellular environment can occur. Unfolded proteins usually refold back into their native states but if control processes fail, misfolding leads to cellular malfunctioning and consequently diseases. Diseases associated with misfolding cover a wide array of pathological conditions such as cystic fibrosis where mutations in the gene encoding the results in a folding to a conformer whose secretion is prevented by quality-control mechanisms in the cell. About 50% of cancers are associated with mutations of the [[Structural Biochemistry/p53|p53]] protein that eventually lead to the loss of cell-cycle control and causing the growth of tumors. Failure of proteins to stay folded can result in aggregation, a common characteristic of a group of genetic, sporadic, and infectious conditions known as amyloidoses. Aggregation usually results in disordered species that can be degraded within the organism but it may also result in highly insoluble fibrils that accumulate in tissue. There are about twenty known diseases resulting from the formation of amyloid material including Alzheimer’s, Type II diabetes, and Parkinson’s disease. Amyloid fibrils are ordered protein aggregates that have an extensive beta sheet structure due to intermolecular hydrogen bonds and have an overall similar appearance to the proteins they are derived from. The formation of the amyloid fibrils are the result of prolonged exposure to at least partially denatured conditions.
[[File:Imagealzheimers.jpg|left|thumb|An abnormal amount plaques and tangles can kill surrounding neurons.]]'''Alzheimer's:''' This neurological degeneration is caused by the accumulation of [[Wikipedia:Senile plaques|Plaques]] and [[Wikipedia:Neurofibrillary tangle|Tangles]] in the nerve cells of the brain.<ref>{{cite web | year = 2009 | title = Alzheimer's Disease | url = http://medicalcenter.osu.edu/patientcare/healthcare_services/alzheimers/Pages/index.aspx | publisher=[http://medicalcenter.osu.edu/Pages/index.aspx Ohio State University Medical Center] | accessdate = 2009-10-09 }}</ref> Plaques, composed of almost entirely a single protein, are aggregation of the protein beta-amyloid between the spaces of the nerve cells and Tangles are aggregation of the protein tau inside the nerve cells. Tangles are common in extensive nerve cell diseases whereas neuritic plaque is more specific to Alzheimer's. Although scientists are unsure what role Plaques and Tangles play in the formation of Alzheimer's, one theory is that these accumulated proteins impede the nerve cell's ability to communicate with each other and makes it difficult for them to survive. Studies have shown that Plaques and Tangles naturally occur as people age, but more formation is observed in people with Alzheimer's. The reasons for this increase is still unknown.
'''Creutzfeldt-Jakob Disease (Mad Cow Disease):''' This disease is caused by abnormal proteins called [[Wikipedia: Prion|prions]] which eat away and form hole-like lesions in the brain. Prions ('''''pr'''oteinaceous '''i'''nfectious viri'''on''''') were discovered to be proteins with an altered conformation. Scientists hypothesize that these infectious agents could bind to other similar proteins and induce a change in their conformation as well, propagating new, infectious proteins.<ref>{{cite web | author = Lindquist, Susan | year = 1999 | title = What is a Prion? | url = http://www.scientificamerican.com/article.cfm?id=what-is-a-prion-specifica | accessdate = 2009-10-09 }}</ref> Prions are highly resistant to heat, ultraviolet light, and radiation which makes them difficult to be eliminated. In Creutzfeldt-Jakob Disease there is an incubation period for years which is then followed by rapid progression of depression, difficulty walking, dementia and death. Currently there is no effective treatment for prion diseases and all are fatal.<ref>{{cite web|url=http://www.emedicinehealth.com/mad_cow_disease_and_variant_creutzfeldt-jakob_dis/article_em.htm#Geo|title=Mad Cow Disease and Variant Creutfeldt-Jakob Disease|publisher=[http://www.emedicinehealth.com/script/main/hp.asp eMedicine Health] |accessdate=2009-10-09}}</ref>
'''Parkinson's disease:'''A mutation in the gene which codes for alpha-synuclein is the cause of some rare cases of familial forms of Parkinson's disease. Three point mutations have been identified thus far: A53T, A30P and E46K. Also, duplication and triplication of the gene may be the cause of other lineages of Parkinson's disease.Victims of [[Wikipedia:Parkinson's disease|Parkinson's disease]] have primary symptoms that result from decreased stimulation of the motor cortex by the basal ganglia, normally caused by the insufficient formation and action of [[Wikipedia:dopamine|dopamine]]. Dopamines are produced in the dopaminergic neurons of the brain. People who suffer from this disease have brain cell loss (death of dopaminergic neurons), which may be caused by abnormal accumulation of the protein [[Wikipedia:alpha-synuclein|alpha-synuclein]]binding to ubiquitin in the damaged cells. This makes the alpha-synuclein-ubiquitin complex unable to be directed to the proteosome. New research shows that the mistransportation of proteins between endoplasmic reticulum and the Golgi apparatus might be the cause of losing dopaminergic neurons by alpha-synuclein.
'''Cystic Fibrosis:''' Francis Collins first identified the hereditary genetic mutation in 1989. The problem occurs in the [[Wikipedia:cystic fibrosis transmembrane conductance|regulator cystic fibrosis transmembrane conductance regulator (CFTR)]], which regulates salt levels and prevents bacterial growth, when the dissociation of CFTR is disturbed as a protein regulating the chloride ion transport across the cell membrane.<ref>{{cite web|url=http://opa.faseb.org/pdf/protfold.pdf |title=Unraveling the Mystery of Protein Folding | publisher=[Thomasson, W.A. "Unraveling the Mystery of Protein Folding] | accessdate=2009-10-18}}</ref> The deleted amino acid doesn't allow bacteria in the lungs to be killed thereby causing chronic lung infections eventually leading to an early death.<ref>{{cite web|url=http://www.hopkinsmedicine.org/hmn/F99/mu_8.html |title=Folding Away Cystic Fibrosis| publisher=[http://www.hopkinsmedicine.org/hmn/F99/top.html] | accessdate=2009-10-18}}</ref> Scientists have used [[Wikipedia: NMR spectroscopy|nuclear magnetic resonance spectroscopy (NMR)]] to study [[Wikipedia: Cystic Fibrosis|Cystic Fibrosis]] and its effects.
[[Image:sicklecells.jpg|left|thumb| link=sickle cell anemia|Normal and sickle-shaped red blood cells.]] '''Sickle Cell Anemia:''' Sickle-shaped red blood cells cling to walls in narrow blood vessels obstructing the flow of blood define [[Wikipedia: sickle cell anemia, a molecular disease|sickle cell anemia]]. The shortage of red blood cells in the blood stream in addition to the lack of oxygen-carrying blood causes serious medical problems. The defect in the [[Structural Biochemistry/Hemoglobin|Hemoglobin]] gene is detected with the presence of two defective inherited genes. The sickle cell shape is formed as hemoglobin give up their oxygen resulting in stiff red blood cells forming rod-like structures. Some symptoms include: fatigue, shortness of breath, pain to any joint or body organ lasting for varying amounts of time, eye problems potentially leading to blindness, and yellowing of the skin and eyes which is due to the rapid breakdown of red blood cells. Luckily, sickle cell anemia can be detected by a simple blood test via hemoglobin electrophoresis. Even though there is no cure, [[Wikipedia: blood transfusion|blood transfusions]], oral antibiotics, and hydroxyurea are treatments that reduce pain caused.<ref>{{cite web|url=http://www.ornl.gov/sci/techresources/Human_Genome/posters/chromosome/sca.shtml |title=Genetic Disease Profile: Sickle Cell Anemia| publisher=[http://genomics.energy.gov/] | accessdate=2009-10-18}}</ref>
'''Huntington's Disease:''' Also known as the trinucleotide repeat disorder, [[Wikipedia: Huntington's Disease|Huntington's disease]] results from [[Wikipedia: glutamine|glutamine]] repeats in the Huntingtin protein. Roughly 40 or more copies of C-A-G (glutamine) will result in Huntington's disease as the normal amount is between 10 and 35 copies. During the post-translational modification of mutated Huntingtin protein(mHTT), small fractions of polyglutamine expansions misfold to form inclusion bodies. Inclusion bodies are toxic for brain cell. This alteration of the Huntingtin protein does not have a definite effect except that it affects nerve cell function.<ref>{{cite web|url=http://hopes.stanford.edu/basics/basichd/a2.html |title=The Basics of Huntington's Disease| publisher=[http://hopes.stanford.edu/index.html] | accessdate=2009-10-18}}</ref> This incurable disease affects muscle coordination and some cognitive functions.
[[Image:cataract in human eye.png|left|thumb| link=cataract in human eye|Cataract in human eye]]'''Cataracts:''' Eye lens are made up of proteins called [[Wikipedia: crystallins|crystallins]]. Crystallins have a jelly-like texture in a lens cytoplasm. The current leading cause of blindness in the world, cataracts occurs when crystallin molecules form aggregates scattering visible light causing the lens of the eye to become cloudy. UV light and oxidizing agents are thought to contribute to cataracts as they may chemically modify crystallins. In children, it has been observed that the deletion or mutation of αB-crystallin facilitates cataracts formation. The likelihood of developing cataracts exponentially increases with age. {{cite book |title= Mechanisms of Protein Folding |last=Pain |first=Roger H. |year=2000 |publisher=Oxford University Press |isbn=019963788 |pages=420–421 |url=http://books.google.com/books?id=DvJygJkNCYkC&pg=PA420&lpg=PA420&dq=cataract+protein+folding&source=bl&ots=lDazpccGH2&sig=aHxuSkC1XNmcOnJYnmW4rZPuUvg&hl=en&ei=Z7rbSv3_OJG-sgOvpOGRBg&sa=X&oi=book_result&ct=result&resnum=2&ved=0CBUQ6AEwAQ#v=onepage&q=cataract%20protein%20folding&f=false |accessdate=2009-10-18}}
===Amyloid Fibrils===
Protein misfolding caused by impairment in folding efficiency leads to a reduction in number of the proteins available to conduct its normal role and formation of amyloid fibrils, protein structures that aggregate, resulting in a cross-β structure that can generate numerous biological functions. Protein aggregation can come from different processes occurring after translation including the increase in likelihood of degradation through the quality control system of the endoplasmic reticulum (ER), improper protein trafficking, or conversion of specific peptides and proteins from its soluble functional states into their highly organized aggregate fibrils.
'''''Structures'''''
'''X-ray Crystallography'''
From X-ray crystallography, three-dimensional crystals of amyloid fibril structures were formed and the structure of the peptide formation and how the molecule is packed together were examined. In one particular fragment, the crystal was found to contain parts of parallel β-sheets where each peptide contributes one single β-strand. The β-strands are stacked and β-sheets formed are parallel and side chains Asn2, Gln4 and Asn6 interact with each other in a way that water is kept out of the area in between the two β-sheets with the rest of the side chains on the outside are hydrated and further away from the next β-sheet.
'''Solid State Nuclear Magnetic Resonance (SSNMR)'''
Through solid-state nuclear magnetic resonance (SSNMR) and the help of other methods such as computational energy minimization, electron paramagnetic resonance and site-directed fluorescence labeling and hydrogen-deuterium exchange, mass spectrometry, limited proteolysis and proline-scanning mutagenesis the structure of an amyloid fibril was suggested to be four β-sheets separated by approximately 10Å.
Through NMR with computational energy minimization, a 40-residue form of amyloid β peptide at pH 7.4 and 24˚Celius was determined to contribute one pair of β-strand to the core of the fibril which is connected by a protein loop. The amyloid β peptides are stacked on each other in a parallel fashion.
From experiments of site-directed spin labeling coupled to electron paramagnetic resonance (SDSL-EPR), the molecule was found to be very structured in the fibrils and in parallel arrangement. SDSL-EPR along with hydrogen-deuterium exchange, mass spectrometry, limited proteolysis and proline-scanning mutagenesis suggests that the structure has high flexibility and exposure to solvent of N-terminal side, but is rigid in the other parts of the structure.
Experiments through SSNMR with fluorescence labeling and hydrogen-deuterium exchange determined that the C-terminals are involved in the core of the fibril structure with each molecule contributing four β-strands with strands one and three forming one β-sheet and strands two and four forming another β-sheet about 10Å apart.
[[File:SmallAmyloidFibril.PNG|thumb|SmallAmyloidFibril]]
Further experimentation approaching the atomic level with SSNMR techniques resulted in very narrow resonance lines in the spectra, showing that the molecules within fibrils hold some uniformity with peptides that display extended β-strands with the fibrils.
'''Conclusion'''
The structures determined from X-ray crystallography or SSNMR were similar to previously proposed structures from cryo-electron microscopy (EM) formed from insulin. EM, which uses electron density maps, revealed untwisted β-sheets in the structure. The similarities of the structures found in these experiments suggest a lot of amyloid fibrils can have similar characteristics such as the side-chain packing, aligning of β-strands and separation of the β-sheets.
<ref name="annu"/> Annu. Rev. Biochem. 2006.75:333-366. www.annualreviews.org. Retrieved 24 Oct 2011</ref>
'''''Formation'''''
The capability to form amyloidal protein structures that are considered to be genetic is from the findings that an increasing number of proteins show no signs of protein related diseases. It has been found that amyloidal proteins can be converted from its own protein that has a function rather than disease- related characteristics in living organisms.
In these protein mutations, different factors that affect the formation of amyloid fibril formation and different chains form amyloid fibrils at different speeds. In different polypeptide molecules, hydrophobicity, hydrophillicity, changes in charge, degree of exposure to solvent, the number of aromatic side chains, surface area, and dipole moment can affect the rate of aggregation of protein. It has been found that the concentration of protein, pH and ionic strength of the solution the protein is in as well as the amino acid sequence it is in determines the aggregation rate from the unstructured, non-homologous protein sequences.
As the hydrophobicity of the side chains increases or decreases can change the tendency for the protein to aggregate.
Charge in a protein can create aggregations through interaction of the polypeptide chain with other macromolecules around it.
Also, the low tendency for β-sheets to form along with the high tendency for α-helixes to form contributes in facilitating amyloid formation.
It was found that the degree in which the protein sequence are exposed to solvent tend to affect the formation of amyloids. Proteins that are exposed to solvent seem to promote aggregation. Even though some other parts of the protein that had a high tendency to aggregate were not involved in the aggregation, they seem to at least be partially unexposed to the solvent but other regions that were exposed to solvent that were not involved in the aggregation had a low tendency to form amyloid fibrils.
It has even been raised that protein sequences have evolved over time to avoid forming clusters of hydrophobic residues by alternating the patterns of hydrophobic and hydrophillic regions to lower the tendency for protein aggregation to occur.
<ref name="annu"/>
'''''The Affects of Sequence on the Formation of Amyloid Proteins'''''
Amyloid formation arises mostly from the properties of the polypeptide chain that are similar in all peptides and proteins, but sometimes, the sequence affects the relative stabilities of the conformational states of the molecules. In that case, the polypeptide chains with different sequences form amyloid fibrils at various rates. Sequence difference affects the behavior of the protein aggression instead of affecting the stability of the protein fold. Various physicochemical factors affect the formation of amyloid structure by unfolded polypeptide chains.
Hydrophobicity of the side chains affects the aggregation of unfolded polypeptide chains. The amino acid in the regions of the aggregation site can change the ability of aggregation of a sequence when they increase or decrease the hydrophobicity at the site of the mutation or folding site. Over time, sequences have evolved to avoid creating clumps of hydrophobic residues by alternating hydrophobic areas of the protein.
Charge affects the aggregation of amyloid protein folding. A high net charge can have the possibility of impeding self association of the protein. Mutations in decreasing the positive net charge may result in the opposite effect of aggregate formation as increasing the positive net charge. It has been seen found that polypeptide chains can be run by interactions with highly charged macromolecules, displaying the importance of charge of a protein aggregation.
Secondary structures of proteins affect the amyloid aggregation as well. Studies show that a low probability to form α-helix structures and a high probability to form β-sheet structures are contributive factors to amyloid formation. However, it has been found that β-sheet formation is not particularly favored by nature since there are little alternation of hydrophilic and hydrophobic residue sequence patterns to be found.
The characteristics of the amino acid sequences affect the amyloid fibril structure and rate of aggregation. Different mutations, including changes in the number of aromatic side chains, the amount of exposed surface area and dipole moment, have been said to change the aggregation rates of lots of polypeptide chains.
Unfolded regions play vital roles in promoting the aggregation of partially folded proteins. Some regions that were found to be flexible or exposed to solvent were fond of aggregation. Other regions that are not involved in the aggregation were found to not be exposed, but rather half buried even though they have high possibility of aggregating while the exposed regions of the structure that are not involved in the aggregation have a low probability of aggregating amyloid fibrils. The fibrils tend to come together by association of unfolded polypeptide segments rather than by docking the structural elements.
Overall, it has been found that unfolded proteins have lower less hydrophobicity and higher net charge than that of a folded protein. Residues that tend not to form the secondary structure of β-sheet structured proteins seem to inhibit the occurrence of amyloid aggregation. Concentration of protein, pH and ionic strength were found to be associated with the amino acid sequence, which affects the rate of aggregation.
<ref name="annu"/>
== Environmental Effects ==
It is understood that the primary structure (the amino acid sequence) of a protein predisposes the protein for a specific three dimensional structure and how it will fold from the unfolded form to the native state. The concentration of salts, the temperature, the nature of the primary solvent, macromolecular crowding, and the presence of chaperones are all factors that affect the mechanism of folding and the ratio of unfolded proteins to those in the native state. More than anything, these environmental factors affect the likelihood of any single protein reaching the correct final structure.
Isolated proteins placed in proper environments (specific solvent, solute concentrations, pH, temperature, etc.) tend to "self-fold" into the correct native conformation. Altering any of these environmental characteristics can disrupt the structure and/or interfere with the folding mechanism. A pH outside the "normal" range of a given protein can ionize specific amino acids or interfere with both polar and dipole-dipole intramolecular forces that would otherwise stabilize the structure. Excess heat (cooking) proteins can break hydrogen bonds essential to the secondary structure of proteins.
Extreme environments or the presence of chemical denaturants (such as reducing agents that can break disulfide bonds) can cause proteins to denature and lose its secondary and tertiary structure, forming into a "random coil." Under certain conditions fully denatured proteins can return to their native state. Intentional denaturing is used in various methods to analyze biomolecules.
The complex environments within cells often necessitate chaperones and other biomolecules for proteins to properly form the native state.
=== Environmental Control Failures and Protein Misfolding ===
While typical environmental factors correspondingly promote proper protein folding, disruptions in these conditions—or inherent defects in the folding process itself—can lead to protein misfolding. This phenomenon represents one of the most significant challenges in protein biochemistry, as misfolded proteins can cause severe diseases in humans, animals, and other living organisms, including Alzheimer's disease and bovine spongiform encephalopathy (BSE, commonly known as Mad Cow disease). Understanding protein misfolding has become increasingly important in biomedical research due to its wide-ranging health implications.
Proteins typically go through several intermediate states during their folding pathway to reach a stable conformation. Scientists have categorized protein folding outcomes into three distinct states: properly folded, partially folded, and misfolded. During the folding process, specialized proteins called chaperones associate with the target protein to assist in proper folding. Once folding is complete, these chaperones dissociate from the target protein and move on to assist other proteins in their folding processes.
Research by American biochemist Christian Anfinsen provided crucial insights into protein misfolding, establishing that misfolding occurs when the normal folding process is disrupted. Current research on protein misfolding often focuses on temperature-sensitive mutations, with researchers observing bacteriophage P22 under varying temperature conditions to induce mutations. These studies have revealed that mutant proteins are inherently less stable than their normal counterparts. Specifically, research on the tailspike protein of bacteriophage P22 has shown that misfolded proteins are less stable than correctly folded proteins and have greater difficulty achieving their proper folded state. When protein misfolding occurs, it can lead to protein aggregation, particularly in brain tissue, which is associated with neurodegenerative diseases.
==== Human Disease Consequences of Misfolding ====
Alzheimer's disease represents one of the most significant consequences of protein misfolding, primarily affecting elderly populations. This neurodegenerative condition occurs when the amyloid precursor protein (APP) undergoes improper folding. During normal processing, APP is cleaved to produce a soluble peptide called amyloid-beta (Aβ). However, when misfolding occurs, this process is disrupted. A critical factor in Alzheimer's pathogenesis is apolipoprotein E (apoE), a protein found in the bloodstream. ApoE exists in three major forms: apoE2, apoE3, and apoE4. While the specific effects of each apoE variant on Aβ processing are not fully understood, research suggests that apoE can bind to Aβ peptides and influence disease progression.
During the misfolding process, β-amyloid aggregates form neuritic plaques characteristic of Alzheimer's disease. The disease typically manifests in older individuals because the formation of the initial nucleus for amyloid aggregation occurs very slowly over time. The instability of these misfolded proteins contributes to progressive neurodegeneration. Research on apolipoprotein E continues to yield complex results, with some studies indicating that certain apoE variants may accelerate disease progression while others appear to be protective. The investigation of apoE's role remains active, as researchers work to clarify the relationship between apoE variants and Aβ processing to develop effective treatments for Alzheimer's disease.
Bovine spongiform encephalopathy (Mad Cow disease) represents another serious consequence of protein misfolding and is particularly concerning because it can be transmitted from animals to humans, causing variant Creutzfeldt-Jakob disease. This disease is caused by the misfolding of prion proteins. Prions are unique infectious agents composed primarily of misfolded protein, unlike typical pathogens that contain DNA or RNA. The pathogenic mechanism involves the self-replicating propagation of misfolded prion proteins. When a misfolded prion encounters a normal prion protein, it can induce the normal protein to adopt the misfolded conformation, creating a chain reaction of protein misfolding. This self-replicating process allows prions to multiply rapidly, converting increasing numbers of normal proteins to the pathogenic misfolded state. Prion diseases demonstrate that protein misfolding can occur through mechanisms that do not require genetic mutations, as evidenced by transmission studies in sheep and other animal models.
== Molecular Chaperones ==
Molecular Chaperones are known mainly for assisting the folding of proteins. Chaperones are not just involved in the initial stages of a protein’s life. Molecular Chaperones are involved in producing, maintaining, and recycling the structure and units of protein chaperones. Chaperones are present in the cytosol but are also present in cellular compartment such as the membrane bounded mitochondria and endoplasmic reticulum. The role or necessity of chaperones to the proper folding of proteins varies. Many prokaryotes have few chaperones and less redundancy in the types of chaperones and whereas eukaryotes have large families of chaperones containing some redundancy. It is hypothesized that some chaperones are essential to proper protein folding such as the example of the prokaryote which has less variations of a chaperone family available. Other chaperones play less of an essential role such as in eukaryotes where more variations within a family of chaperones exist and gradients of efficiency or affinity are produced. This redundancy or existence of less efficient chaperones may exist in one state but the effectiveness of chaperones is also a function of their environment. The pH, space, temperature, protein aggregation and other external factors may render a chaperone that was once ineffective into a more essential chaperone. These environmental factors show why it is important to simulate cellular in vivo conditions, or native states, in order to grasp the conditions that require use of chaperones. This briefly summarizes the difficulties in analyzing and comparing chaperone function in vivo vs. in vitro.
Simulating in vivo, or the environment within the cell, is important not just because of physical factors such as pH or temperature but also because the time in which the chaperone begins to conform the polypeptide. Some chaperones are nearby the [[Structural Biochemistry/Cell Organelles/Ribosome|ribosome]] and attach immediately to the polypeptide to prevent misconformation. Other chaperones allow the polypeptide to begin folding by itself and attach later on. Thus the role of each chaperone becomes specific to its vicinity to the polypeptide and time and place in which it assists folding. Recent research has implicated that chaperones within the nucleolus not only catalyze protein folding but also catalyze other functions important to maintain a healthy cell. These nucleolar chaperones are called Nucleolar Multitasking Proteins (NoMP's). Heat shock proteins, for example, not only help other proteins fold but also act during moments of stress to regulate protein homeostatis. Furthermore, there is evidence that chaperones work together in networks to oversee certain functions like dealing with toxins, starvation or infection.
The nucleolar chaperone network is divided into different branches that have specific functions. The network is dynamic and can vary in concentration or location of the network components depending on changes in the physiology and environment of the cell. Heat shock proteins (HSPs), which are classified based on their molecular weights, are integral components of the chaperone network. HSP 70s and 90s maintain proteostasis by ensuring that proteins are properly folded and preventing proteotoxicity, which is the damage of a cell function due to a misfolded protein. HSP70s help to fold recently synthesized proteins, while HSP90s help later in the folding process. The nucleolar network also contains chaperones that are part of ribosome biogenesis, or the synthesis of ribosomes in the cells. Proteins in the HSP70 and DNAJ families, which help to process pre-rRNA, are regularly found in protein complexes that process pre-rRNA in Saccharomyces cerevisiae (a species of yeast). Other HSPs are important in ribosome biogenesis as well, including HSP90 which works together with TAH1 and PIH1 to create small nucleolar ribonucleoproteins. The nucleolar chaperone network provide the organization and assistance needed to complete the biological taks necessary for cell survival, and if it does not function properly there can be many problems. For instance, when cancer cells have increased levels of rRNA synthesis, ribosome biogenesis is increased. Scientists are researching the compound CX-3543, which can stop nucleolin from binding with rDNA and impede RNA synthesis, leading to cell death. It is possible to potentially use drugs designed to target specific branches of the nucleolar chaperone network in malfunctioning cells. Other networks of chaperones include networks that specifically participate in de novo protein folding, meaning they help to fold newly made proteins, and the refolding of proteins that have been damaged. One chaperone network that exists in tumor cell mitochondria contains HSP90 and TRAP1, which protect the mitochondria and prevent cell death, allowing the cancer cells to continue to spread uncontrollably.<ref>{{cite web | author = Piotr Banski, Mohamed Kodiha and Ursula Stochaj | year = 2010 | title = Chaperones and multitasking proteins in the nucleolus: networking together for survival? | url = http://www.ncbi.nlm.nih.gov/pubmed/20363631 | accessdate = 2010-10-16 }}</ref>
=== Example: Molecular Chaperone (HSP 70) ===
HSP 70 is a protein in the Heat Shock Protein family along with HSP 90. It works together with HSP 90 to support protein homeostasis. It binds to newly synthesized proteins early in the folding process. It has three major domains, the N-terminal ATPase domain, the Substrate binding domain, and C-terminal domain. The N-terminal ATPase binds and hydrolyzes ATP, the substrate binding domain hold an affinity for neutral, hydrophobic amino acid residues up to seven residues in length while the c-terminal domain acts as a sort of lid for the substrate binding domain. This lid is open when HSP 70 is ATP bound and closes when hsp 70 is ADP bound. HSP70, or DnaK, are bacterial chaperones and can help in folding by clamping down on a peptide.<ref name="ReferenceA">Joan L. Slonczewski, John W. Foster. "Microbiology: An Evolving Science."</ref>
<gallery>
File:PDB_3hsc_EBI.jpg| HSP 70
</gallery>
===Example: GroEL and GroES===
GroEL and GroES, or 60kDa and 10kDa, are both bacterial chaperones. Both GroEL and GroES are structured so that they are a stacked ring with an empty center. The protein fits in this hollow center. Conformational changes within the chamber can then change the shape and folding of the protein.<ref name="ReferenceA"/>
=== Example: Molecular Chaperone (HSP 90) ===
HSP 90 is a protein in the Heat Shock Protein family. This particular protein, however, is different from other chaperones in that HSP90 is limited in the folding aspect of molecular chaperones. Instead, Hsp 90 is vital to study and understand because many cancer cells have been able to take over and utilize the Hsp 90 in order to survive in many virulent surroundings. Therefore, if one were to structurally study and somehow target Hsp90 inhibitors, then there could be a way to stop cancer cells from spreading. Furthermore, many studies have been performed in order to test whether or not the Hsp 90 chaperone cycle is driven by ATP binding and hydrolysis or some other factor. But after much research by Southworth and Agard, there was enough evidence to state that HSP90 protein could conformationally change without nucleotide binding but rather the stabilization of an equilibrium is the factor that will change the Hsp90 to a closed or compact or open state. The three conformations of the Hsp90 were found through x-ray crystallography and also through single electron particle microscopy and by studying the three-state conformational changes in yeast Hsp90, human Hsp90 and bacteria Hsp 90 (HtpG) it was clear that there are distinct conformational changes for specific species. Overall, Hsp90 is a chaperone that is more involved with maintaining homeostasis within a cell rather than the involvement of protein folding. Hsp90 has rising potential in the area of drug development in the future since it plays such an essential role in aiding the survival for cancer cells.
<gallery>
File:Hsp90.jpg| HSP 90
</gallery>
=== Example: Molecular Chaperone (TF) ===
This is the first chaperone to interact with the nascent chain as it exits the ribosome tunnel. Without the nascent chain, the TF cycles on and off but once the nascent chain is present, it binds onto the chain, forming a protecting cavity around. In order to do its function, TF scans for any exposed hydrophobic segment of the nascent chain and it can also re-associate with the chain. Folding is found to be more efficient in the presence of the TF, however, this is done at the expense of speed, it can stay with the chain for more than 30 seconds. The release of the chain is triggered when the hydrophobic portions is buried as the folding progresses toward the native state.
[[File:Http://www.jbc.org/content/280/13/12996/F2.medium.gif|thumbnail]]
=== Example: Molecular Chaperone (YidC, Alb3, Oxa1) ===
YidC, Alb3, and Oxa1 are proteins that facilitate the insertion of proteins in the plasma membrane. YidC is a protein that has only two polypeptide chains. The formation of its structure has been supported by particular phospholipids. YidC proteins can be found in Gram-negative and Gram-positive bacteria. Oxa1 can be found in the inner membrane of the mitochondria. Alb3 locates in the membrane of the thylakoid inside the chloroplast. Experiments showed that YidC protein actively contributes to the insertion of Pf3 coat protein. In addition, YidC also has direct contact with the hydrophobic segment of Pf3 coat protein. Although Oxa1 can only be found in the mitochondria it can also facilitate the insertion of membrane proteins in the nucleus. The role of YidC and Alb3 seems to be interchangeable because Alb3 can replace YidC in E. coli. Moreover, YidC, Oxa1, and Alb3 all support the insertion of Sec-independent proteins. Oxa1 only supports the insertion of Sec-independent proteins because the mitochondria in yeast cell do not have Sec proteins.
===NLR===
Nucleotide-binding domains that are leucine- rich (NLR) provide a pathogen-sensing mechanism that is present in both plants and animals. They could either be triggered directly or indirectly by a derivation of pathogen molecules via elusive mechanisms. Researches show that molecular chaperones like HSP90, SGT1, and RAR1 are main stabilizing components for NLR proteins. HSP90 can monitor the function of its corresponding clients that apply to NLR proteins in three practical ways: promotion of steady-state of functional threshold, activating stimulus-dependent activity, and raising the capacity to evolve.
Plants contain many NLR genes that considered being polymorphic in the LRR domain in order to be familiar with the highly diversified pathogen effectors. The NLR sensor stability will be the mechanism that will determine the pathogen recognition. The HSP90 system is advantageous for plants because it will couple metastable NLR proteins and stabilize them in a signaling competent condition. This will allow for the masking of mutations that would be detrimental.
=== Molecular Chaperone Mechanism for Substrate Binding in Protein Folding ===
It is known that chaperones work together to aid in the folding of protein in order to prevent misfolding. However, the mechanism of how chaperones help in protein folding was not fully understood. Recent studies on Hsp40 and Hsp70 have provided more insights into the mechanism of chaperones and their substrate. The Hsp40 family consists of many Hsp40 with different J-domain. Different J-domain will carry out different Hsp70 ATPase activities when Hsp40 binds to Hsp70. In protein folding, an unfolded polypeptide binds to a Hsp40 co-chaparone. From there, the J-domain of Hsp40 binds to the nucleotide-binding domain (NBD) of Hsp70. A conformation change in the Hsp70 substrate-binding domain occurs when the hydrolysis of ATP to ADP takes place on the HSP70 NBD. This causes Hsp70 to have a higher affinity for the polypeptide substrate and unbind the substrate from Hsp40. When ADP is exchange for ATP, the polypeptide substrate is released from Hsp40. Studies have shown that nucleotide exchange factors make changes to the lobe on the Hsp70 ATPASE domain in way that decreases Hsp70’s affinity for ADP. Once the polypeptide is released from Hsp70, it can fold to its native state or it can be refolded by the chaperones if there is a misfolding. If a polypeptide that is bounded to Hsp70 is recognized by E3 ubiquitin ligase CHIP, it will be degraded.<ref>{{cite web | author = Summers, Daniel W., and Peter M. Dougla | year = 2009 | title = Polypeptide Transfer from Hsp40 to Hsp70 Molecular Chaperones. | url = http://www.ncbi.nlm.nih.gov/pubmed/19359181 | accessdate = 2010-10-24 }}</ref>
=== Small Heat Shock Proteins & α-crystallins as Molecular Chaperones ===
It is known that small heat shock proteins (sHSPs) and the related α-crystallins (αCs) are virtually ubiquitous proteins that are strongly induced by a variety of stresses, but that also function constitutively in multiple cell types in many organisms. Extensive research has demonstrated that a majority of sHSPs and αCs can act as ATP-independent molecular chaperones by binding denaturing proteins and reversing denaturation. This approach thereby protects cells from damage due to irreversible protein aggregation. Many inherited diseases have been discovered to result from defects in sHSP/αCs, and these proteins accumulate in neurodegenerative disorders and other diseases linked to aberrant protein folding. sHSP/αC proteins range in size from ~12 to 42 kDa and is a C-terminally located domain of ~90 amino acids, known as the αC domain. sHSP-substrate complexes can be observed by size exclusion chromatography . They are large and heterogenous, and their size distribution depends on the ratio of sHSP/αC to substrate as well as the rate of substrate aggregation, which is affected by concentration and temperature. Substrate binding is generally facilitated by an increase in available hydrophobic surface on the sHSP/αC, which seem to occur without significant loss of defined sHSP/αC secondary and tertiary structure. There is no single, specific substrate binding surface on sHSP/αCs. It rather appears that many sites contribute to substrate interactions, and binding is probably different for different substrates dependent on the conformation of surfaces exposed when a substrate unfolds. However, some sHSP/αCs recognize almost any unfolding protein, which suggests that they act on any labile or damaged cellular component.
== The Energy Landscape for Protein Folding ==
If proteins folded randomly and unpredictably, the amount of time taken to reach the native conformation would be much larger than the actual time it takes. The current theory on how protein folding occurs naturally and efficiently involves a "funnel" of sorts-the idea being that there exists not a step by step means of reaching the correct 3-D structure, but rather a number of paths that become progressively narrower from top to bottom. The funnel starts at the top and proceeds downward from energetically disfavorable folding at the top to energetically favoring proper folding at the bottom.
The experiment that sparked the idea of proteins relying on energetics and thermodynamics to reach their native folding was conducted by Christian Anfinsenf in 1961, when he discovered that ribonuclease could spontaneously refold into its proper structure after being denatured without the help of other molecules. Further theoretical proof that protein folding is not random is seen in Levinthal's Paradox, which states that it would take roughly 10^81 years for a protein 100 amino acids long to reach the proper conformation, when in reality, it takes anywhere from a millisecond to a day.
[[Image:Energy Landscape.jpg]]
These funnel models (such as the Go-type model) show funnels with hills and bumps that represent the protein taking the path of least resistance when moving down the energy funnel. These bumps are termed "points of frustration". It is believed that funnels with the fewest frustration points or bumps fold into their native forms faster since fewer energy boundaries exist. Although these models are simplified attempts and do not account for misfoldings, they nonetheless prove accurate in the case of many proteins.
Another model that uses algorithms and computers is the empirical force field. This model uses hundreds of thousands of computers running idly to compute folding scenarios of proteins under 50 amino acids with surprising accuracy. However, these computer models will sometimes overestimate unlikely folding structures or produce folding patterns that are rarely or never seen. For example, some simulations/algorithms have a tendency of getting stuck in the local minima and are unable to reach the global minima, which is the correctly folded protein. Simple models such as Go-type models not only predict the folded protein, but also the transition states that determine the rate of the protein folding.
These models are just beginning to show the dynamics of the intermediate stages of protein folding. As such, this is an area under further investigation. The understanding of the kinetics of protein folding is less established, and the movement of proteins between initial amino acid strands and the final product is also an area under investigation. The energy landscape model also has trouble accounting for external factors like crowding and aggregates. One such example of external interaction, called "domino swapping", involves the swapping of monomers from one protein to another in order to activate the correct folding of both proteins.
Recent studies have combined human and computer power to correctly predict the protein conformation. Websites like fold.it, overseen by the University of Washington's Computer Science department, turn the folding problem into a video game, allowing people around the world to solve protein folding problems like puzzle games. Users are given partially folded proteins, usually those stuck in a locally favorable conformation that seems optimal to a computer, and asked to reconfigure the protein into a shape that looks more stable. Utilizing a computer's computing power and speed along with a human's ability to manipulate objects in space shows promise in helping to solve protein folding problems more efficiently.
==Co-operativity and Protein Folding Rates==
The cooperative nature expressed in protein folding is one of the most remarkable aspects of protein folding. Contrary to the traditional viewpoint of complex and heterogeneous mechanisms involved in the folding of a protein, the cooperative two-state folding kinetics shown by many proteins is relatively simple. Due to its simplicity, efforts to understand what determine the co-operativity and the diversity of protein folding rates are made recently by means of applying the cooperative two-state folding kinetics.
The co-operativity of the protein is usually referred to the mechanism by which the presence of a structural region makes additional order more favorable in protein folding. As mentioned previously, the cooperative two-state folding kinetics of small globular proteins is relatively simple and become an interest of study of many scientists. The experiment that excites single molecule that is sensitive enough to allow estimation of transition time reveals two-state co-operativity.
The general trends revealed by two-state folding proteins may be summarized as the following two points. Firstly, more topologically complex proteins tend to fold more slowly than proteins with simpler, local topology; secondly, larger proteins tend to fold more slowly than smaller proteins. The largeness and smallness of a protein here are defined base on its chain length.
Protein folding kinetics is controlled by the free energy barrier determined by the gain of energy and the loss of entropy in the transition state. In describing the pattern, scientists introduce principle of ''minimum frustration of energy landscape theory''. The theory refers to the concept that native-like structures have lower free energy than other random configurations during protein folding. Thus, native-like structures encourage fast folding of the protein and serve as a driving force toward native state, the functional form or the tertiary structure of the protein. This principle can be expressed by the ''funnel energy landscape''.
'''Funnel Energy Landscape'''
Funnel energy landscape depicts the energy landscape of a folding protein as a rough funnel. The roughness comes from non-native contacts in protein folding process.The landscape is inherently many-dimensional, so funnel is a projection on the two-dimensional graph. The depth of the funnel represents the energy of a conformational state; the width of the funnel represents the measure of l entropy. The bottleneck of the funnel represents the transition state configuration of the folding protein, whereas the bottom of the funnel represents the native state of the protein. As the protein goes toward its native state, it experiences entropy loss and it achieves lower energy state. The funnel energy landscape serves as a convenient illustration for scientists to envision the thermodynamics and kinetics of the protein folding process.
'''φ (phi)value'''
Another concept that plays a role in the study of protein folding kinetics is the ''φ (phi) value''. The value refers to the approximate measurement of native structure content in transition state configuration. The comparison with φ value serves as one of the ways to examine various models that studies protein folding kinetics.
'''General observations'''
The fist trend mentioned may be easily understood from an entropic point of view. More topologically complex proteins, or proteins that have long-range contacts, are expected to have higher entropic cost compared with proteins have short-range contacts in terms of folding. The second trend was recently confirmed by experiments focused on the influence of protein size on folding rates. It was found that simple model based only on chain length could roughly predict a protein’s folding rate and stability.
'''Go¯model'''
Coarse-grained topology models (Go¯model) are widely used to study the co-operativity and kinetics of protein folding, as it is noted that the topology of native protein determines the folding mechanism. Typical Go¯model simplifies the protein where there is only one interactions stabilizing the folding protein. Early models often examine the non-additive force acting in the protein folding, such as side-chain ordering and hydrophobic effects. Recently, more variety of Go¯models is used to study the protein folding kinetics.
* Bulleted list item
* The Go¯model (this refers to Eastwood and Wolynes’ model here) with nonpairwise-additive interactions between the native contacts of the protein demonstrates that short-ranged multi-body interaction can increase the free energy barrier and make the transition state configuration more localized.
*The lattice Go¯model, on the other hand, demonstrates the coupling local and core burial interactions promoting co-operativity as well as increasing the correlation with contact order.
*The Go¯model with pairwise-additive interactions, particularly the ones focusing on the effects of varying strength of three-body interactions and φ values, shows that three-body interactions increase energy barrier and increases the agreement with measured φ values.
*In addition, solvent-mediated interactions are also introduced into Go¯model. Where the interactions between contacts are replaced by solvent separated minimum and desolvation barrier, it is observed that kinetics and co-operativity of protein function increase as a function of the height of desolvation barrier. The advantage of solvent-mediated Go¯model is that it is useful in distinguishing short-ranged contacts and long-ranged contacts and therefore differentiating proteins with simple topologies and the ones with more complex topologies. In study of solvent-mediated Go¯model the ''chevron plot'' is often used. The chevron plot is a way to represent protein folding kinetic datas in varying concentration of denaturation that disrupts the native structure of the protein.
*Variational Go¯model improves co-operativity by excluding volume force between the residues that are in close contacts in native state. In this model it is achieved that a) the Co-operativity is stronger for long-ranged contacts; b) the range of calculated rate is broaden; c) the calculated φ values are improved. There is also Go¯models that entirely focus on the funnel aspect of the protein folding energy landscape and ignore the non-native contact effects.
Other model, such as capillarity model, assumes the volume of folding nuclei scales with number of monomers. In such model, it is shown that increased co-operativity tends to slow down kinetics and smooth the energy landscape.
'''Conclusion'''
The recent development of topological models with non-additive forces is becoming a more popular and reliable way to understand the co-operativity of protein folding rates. Refinement of this model has shown its promising future on a more explicit and through understanding of what determines protein folding rates and mechanism. Go¯models that enables long-ranged contacts become more cooperative, and φ values more accurate need further improvement and more attention in the study of protein folding kinetics and the folding mechanism.
==Relationship between Protein Sequence, Structure, and Function==
There have been several protein prediction methods developed in the past 20 years. A universal method has not been developed that applies to all proteins because each method has its advantages and disadvantages. The difficulty of developing such a method is due to our incomplete understanding of the highly intricate relationship between protein sequence, structure, and function.
The theory of correlating amino acid sequence to its structure was shown by Anfinsen. He demonstrated that a denatured (unfolded) protein could regain its native tertiary structure spontaneously. This method is also a useful contributor for assigning function to protein structure. A protein researcher could predict that hydrophobic substrates could potentially bind to hydrophobic regions of the protein and vice versa for charged regions. The problem with this method is that it doesn’t take into account certain factors such as atypical environmental conditions.
It was thought that similar sequencing implies related structures. This theory only holds true for a handful of proteins. Researchers saw that similarities in protein folds aren’t always related to its protein sequence. Due to these findings, the ‘Paracelsus Challenge’ was purposed in 1995. The theory behind the ‘Paracelsus Challenge’ was to develop two proteins that were more than 50% identical in sequence, but they both had completely different folds. The challenge was satisfied in 1997 by with two protein sequences that shared 88% sequence identity (GA88 and GB88). Recent studies show that as little as 3 mutations are enough to induce different folding patterns. Although the outcomes of the ‘Paracelsus’ challenge are very interesting, they rarely occur in nature.
Functional convergence causes problems in assigning a specific function to a structure. Various structures can adopt similar functions, but some can adopt very different functions as well. However, there is a significant correlation between certain folds and specific functions. There are two major variables in function prediction: (1) the locations of binding site, and (2) the range of functions at the site. Metal, ions, cofactors, and other proteins that contribute to functions must be taken into considerations as well. One problem that arises with these factors is when determining a structure via crystallography. The PROCOGNATE resource and PIDA database offers a solution to this problem.
A widely used method by which protein function is defined is derived from the Gene Ontology, which consists of three graph structures in which functional terms and relationships between them are defined. Limitations of gene ontology arise with proteins that are non-positional and when proteins have no defined relationship between ligand in its crystal structure. Other developments that attempt to bridge this gap includes The Protein Feature Ontology (PFO [29]) and The Distributed Annotation System (DAS[30]).
Two approaches are used to determine a functional site: (1) either with no knowledge of where the site is or what it binds, or (2) with prior knowledge of the interaction partner. The most highly used methods involve bioinformatics such as the SOIPPA method. A very important contributor to assigning function to protein is sequence conservation, but it is difficult to determine if residues are conserved for structural or functional reasons. Another method involves energy-based approach. A recent development is the ProFunc server, which combines methods such as InterProScan and BLAST search.
Predicting binding sites (which are immensely complex in its own nature) is only the first step of the puzzle. The next step is to determine the overall function in terms of biochemical function, and even more challenging is determining its biological role. The difficulties with analyzing protein function increased another magnitude of complexity when researchers came across the fact that protein function may not only depend on its final folded product. A protein could have functionalities in its partially denatured state and it fully denatured state. With all of this said, it is safe to say that there is still a lot to learn about the relationship between sequence, structure, and function of proteins.
==Domain Swapping, Folding and Misfolding==
The domain swapping that occurs in proteins may be important in the folding or misfolding process in proteins. Domain swapping occurs when two or more identical protein chains swap with each other. The domain swapping can be thought of as a mechanism for the interchanging of monomers and oligomers. What happens in oligomeric swapping is that one monomer from one protein will swap with another identical monomer from a different protein. This domain swapping mechanism has been observed in various proteins, more than 40 different proteins. The swapping mechanism is important for some protein functions. For a specific protein for example, p13suc1 it has been seen that the swapping and aggregation correlate meaning that they have a common mechanism. P13suc1 is required for cyclin-dependent kinase (Cdk) during the cell cycle progression. P13suc1 has two different states, one being a monomer and the other a swapped dimmer. The domain swapped part is a β strand is not an independently folded domain. While studying this, it was found that β4 has a critical role when in contact with β2 because they pair with each other early on in the folding process. Therefore, for p13suc1, it has been shown that the regions that have been interchanged are responsible for the folding and misfolding of the protein. There seems to be a competition between folding and misfolding in proteins because polypeptide chains can fold into structures or misfold into amyloid fibrils. What seems to be even more crucial in protein folding is the presence of a folding nucleus which forms part of the protein chain in the transition state. A correlation between residues involved in protein folding nuclei location and amyloidogenic regions have been found as well as important information that fibril formation and protein folding may contain key residues. By using the modeling of folding of proteins and looking at the exchangeable regions in the oligomeric form, the relationship can be seen as responsible for folding and misfolding. This may take researchers one step closer to solving the protein solving problem and understand how proteins get their folding instructions.
Reference: http://www.benthamscience.com/open/tobiocj/articles/V005/27TOBIOCJ.pdf
<gallery>
File:PDB_1ug0_EBI.jpg | Domain Swapping
</gallery>
==Death-fold Superfamily<ref>11. Kersse K, Verspurten J, Vanden Berghe T, Vandenabeele P. The death-fold superfamily of homotypic interaction motifs. Trends in biochemical sciences. 2011;36(10):541–52. Available at: http://www.ncbi.nlm.nih.gov/pubmed/21798745. Accessed October 29, 2012.</ref>==
There are 4 subfamily structures in the death-fold superfamily. They consist of Death Domains (DDs), Death Effector Domains (DEDs), CAspase Recruitment Domains (CARDs) and PYrin Domains (PYDs). These subfamily structures are involved in the assembly of multimeric complexes which may be implicated in cell inflammation and death.
'''''Structure and Function of a Death-Fold Domain'''''
There are currently 102 known proteins that have death-fold superfamily domains. These domains contain homotypic interactions. These proteins consist of 39 DDs, 8 DEDs, 33 CARDs, and 22 PYDs. Although these domains have up to a 90% difference in sequence, they all have the characteristic death-fold. This fold consist of a "globular structure where 6 amphipathic alpha-helices are arranged in an anti-parallel alpha-helix bundle with Greek key topology" (Peter Vandenabeele et al., 2012). The difference between these death-domains which constitute either of the subfamilies is found in the alpha-helices length and orientation and the distribution of hydrophobic and charged residues along the surfaces of the complexes.
The believed function of the death-fold domains is to mediate the assembly of large oligomeric signaling complexes. At these complexes, caspases and kinases activity is increased. Before now, little was known about the structural conformation of protein assemblies with death-fold domains.
'''''Three distinct Interaction Types'''''
Type I Interaction:
Residues from helices 1 and 4 (Patch Ia) of one death-fold domain interact with residues from helices 2 and 3 (Patch Ib) of another death-fold domain.
Type II Interaction:
Residues from helix 4 and the loop between helices 4 and 5 (Patch IIa) of one death-fold domain interact with residues of the loop between helices 5 and 6 (Patch IIb) of another death-fold domain.
Type III Interaction:
Residues from helix 3 (Patch IIIa) of one death-fold domain interact with residues located on the loops between helices 1 and 2 and between helices 3 and 4 (Patch IIIb) of another death-fold domain.
Previous theory suggested that the three interaction types were conserved throughout the death-fold superfamily but it now seems that there are differences seen between interactions of the same type of death-fold domains.
'''''Crystal Analysis of Death-Fold Domains'''''
Only three DD complexes have had their crystal structure analyzed. They are PIDDosome, MyDDosome, and the Fas/FADD-DISC. The analyses of these structures have shown that DDs can engage in up to six interactions.
'''''Death-Domains and Medicine'''''
Death-domains have been shown to facilitate the assembly of multimeric complexes that lead to inflammation and cell death. Understanding of these structures can generate therapeutic benefit by preventing or triggering the formation of these oligomeric complexes. Diseases that may be affected by these interactions can include neurodegenerative and inflammatory disorders as well as many others that have characteristic of inflammation or excessive cell death.
==Disordered Proteins==
While folding is typically a major contributor to protein function, some proteins do not fold into a specific structure, yet still possess a function. Instead of a specific structure, these proteins often shift between different forms and/or have disordered regions that do not hold to a particular shape.
Just as a protein's folding is determined by its amino acid sequence, non-folding proteins are non-folding because of their sequence. These proteins tend to have much less of certain amino acids than folding proteins, and much more of others. Specifically, non-folding have less of the amino acids that form the hydrophobic cores of folding proteins and more of the surface amino acids. The formation of a hydrophobic core is one of the first steps in most protein folds and, once formed, the core tends to provide the driving force for stable final structures. Without the amino acids to form a core, proteins are not driven towards a specific structure.
= = = CONCEPT = = =
Several molecular chaperons that are fully folded and inactive under non-stress conditions have been known as conditionally disordered proteins. These chaperons have a partially disordered conformation when they exposed to distinct stress conditions. This disorder is very important because they are able to protect cells against stressors. The study of these disordered chaperons lead to more understanding of the functional role for protein disorder in molecular recognition.
X-ray crystallography is a useful technique that helps visualize the structures of the proteins. Based on this technique, over 95% of the entire molecule is represented by 25% of crystal structures and all others have missing electron density for more than 5% of their sequence due to the multiple conformations on these regions.
Proteins actually have some disordered conformation and these disordered proteins lie at one extreme part from very flexible to static structural states on a continuous spectrum. Either only a part of the protein or the whole complete polypeptide chain is found in this disorder. Therefore, investigating only some parts of the proteins would not help summarize the flexibility of the protein. The term “conditionally disordered” means the disorder of proteins may happen under some certain conditions and may not happen under other conditions.
It is very common to see the intrinsic disorder within proteins. For example, between 30% and 50% of eukaryotic proteins are estimated to have more than 30 amino acids that violate the defined secondary structure in vitro and many complete unstructured proteins have been predicted to exist too. It is still very challenging to verify the status of folding of proteins within the region of cells despite a lot of computational methods that have been used. There is a chance that many proteins which are seen either partially or fully folded happen to be unstructured in cells. The number of these chances is still uncertain.
It is however thought that the presence of the appropriate binding pairs would make the disordered proteins come into their folded state, which means that the percentage of intrinsically disordered proteins in vitro might be lower in the cell. The extent of the disorder might be decreased by the stabilizing interactions within the cells.
Through chemical shift, residual dipolar coupling, and paramagnetic resonance enhancement measurements, NMR serves as a good method to provide the detailed information on extent of disorder of the proteins.
= = = CONDITIONALLY DISORDERED PROTEINS = = =
There are two states of disordered proteins. One shows a high degree of flexibility and the other state is where the protein is found more ordered. Thus, in order to know the cause and effect relationships between disorder and function, it is essential to study both states. Many disordered proteins like DNA, proteins, and membranes refold once they find a partner to bind to. Also, order-to-disorder-to-order transitions can occur. Proteins that are involved into multiple binding are very good examples of conditional disorder. Binding surfaces that are disordered before binding are able to fold into distinct conformations with other partners better than the binding surfaces that are already well-organized. The ‘conformational selection hypothesis’ suggests that different members of conformational ensemble can be stabilized by the binding of different partners. On the other hand, the ‘folding upon binding’ model proposes that proteins may be able to fold into different conformations when they bind with different partners.
===Frequency===
Predictions done on whole proteomes suggest that the frequency of disordered proteins in eukaryotes is much larger than in prokaryotes, with the frequencies in the two groups of prokaryotes, archaea and eubacteria, being similar. In mammals, about half of all proteins are predicted to have large unordered regions, with about a quarter being fully disordered.
===Function===
Disordered proteins are prevalent in signaling and regulation, especially in interactions with biomolecules such as nucleic acids and other proteins. Molecular recognition and protein assembly and modification frequently involve proteins with disordered regions. The ability of these proteins to interact with multiple molecular partners means that they are also common in protein-protein networks, either as hub proteins or as proteins interacting with hub proteins.
===Diseases===
Disordered proteins are implicated in a number of human diseases. In particular, the amyloid diseases, which involve the accumulation of misfolded proteins, seem to be associated with disordered proteins, probably because their variable regions make them more likely to have a structure that favors their accumulation. This category includes many neurodegenerative diseases, such as Alzheimer's and Parkinson's.
== The Role of Computers in Determining Structure and Function of Proteins ==
The structure or folding of an amino acid and by extension its function can be analyzed and compared through its primary structure or amino acid sequence using computer algorithms. Comparisons of amino acid sequences of unknown folding patterns with similar amino acid sequences of known folding is enhanced using computers. A computer automated tool called Protein Basic Local Alignment Search Tool, or [http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?PAGE=Proteins&PROGRAM=blastp protein BLAST], is a free search tool open to the public that allows quick comparison of amino acid sequences in an online database. The output of this tool is the percent match of amino acids and the known properties of the sequence matches. Furthermore, because amino acid sequences are based on DNA sequences, three bases code for one amino acid, the protein under scrutiny can be analyzed on a DNA level using [http://blast.ncbi.nlm.nih.gov/Blast.cgi?PAGE=Nucleotides&PROGRAM=blastn&MEGABLAST=on&BLAST_PROGRAMS=megaBlast&PAGE_TYPE=BlastSearch&SHOW_DEFAULTS=on DNA BLAST]. The integration of public databases of amino acid and DNA sequences along with computer algorithms has accelerated the genome and proteome field by allowing scientists around the world to share and analyze sequences.
<u>Appendix</u>
'''The Role of Computers'''
The scientists credited for creating the BLAST program are [http://en.wikipedia.org/wiki/Webb_Miller Webb Miller], [http://en.wikipedia.org/wiki/David_J._Lipman David J. Lipman], [http://en.wikipedia.org/wiki/Warren_Gish Warren Gish], [http://en.wikipedia.org/wiki/Eugene_Myers Eugene Myers], and [http://en.wikipedia.org/wiki/Stephen_Altschul Stephen Altschul] from the NIH
'''Molecular Chaperones'''
Pain, Roger H. Mechanisms of Protein Folding. 2nd ed. 364-85
{{BookCat}}
'''The Energy Landscape for Protein Folding'''
Cho, Samuel S. "Energy Landscapes for Protein Folding, Binding, and Aggregation: Simple Funnels and Beyond." UCSD Dissertation (2007).
Cheung, Margaret S. "Energy Landscape Aspects of Protein Folding Dynamics Relevant to Molecular Functions." UCSD Dissertation (2003).
Yang, Sichun. "Extending the Theoretical Framework of Protein Folding Dynamics." UCSD Dissertation (2006).
'''Intramolecular Interactions'''
Pain, Roger H. "Mechanisms of Protein Folding" 2nd ed.
http://www.nature.com/horizon/proteinfolding/background/importance.html
Berg "Biochemistry" 6 Edition
== Co-translational protein folding ==
In silico modeling studies have helped identify several characteristics of co-translational folding pathway. First, it was determined that in vivo protein folding is a vectorial process, which is a dispersion change. Second, co-translational vectorial folding of the developing polypeptide from its N-terminal end to its C-terminal end results in a sequential structuring of the distinct regions of the polypeptide emerging from the ribosomal tunnel. Third, attachment to the developing polypeptide chain to the ribosome during protein synthesis reduces the conformational space and the degrees of freedom of the growing chain. This limits the number of possible intermediates and reduces the number of possible folding pathways. Fourth, co-translational protein folding begins early during the process of polypeptide chain synthesis on the ribosome, with some elements forming inside the ribosomal tunnel. Fifth, folding catalysis and molecular chaperones interact with the growing developing chain as soon as it emerges from the tunnel. This accelerates the slow steps in protein folding and prevents misfolding of proteins.
{{BookCat}}
==References==
<references/>
12. Small heat shock proteins and α-crystallins: dynamic proteins with flexible functions.
Basha E, O'Neill H, Vierling E.
Trends Biochem Sci. 2012 Mar;37(3):106-17. Epub 2011 Dec 14
Conditional disorder in chaperone action. Bardwell JC, Jakob U.
Trends Biochem Sci. 2012 Sep 24. pii: S0968-0004(12)00127-2. doi: 10.1016/j.tibs.2012.08.006. [Epub {{PMID|23018052}} [PubMed - as supplied by publisher]
"Molecular Biology of the cell." Fifth Ed-Alberts, Johnson, Lewis, Raff, Roberts, Walter. pg. 716-717
Braakman, Ineke, and Neil J. Bulleid. "Protein Folding and Modification in the Mammalian Endoplasmic Reticulum." Annual Review of Biochemistry. 80. (2011): 71-99. Web. 29 Oct. 2011. <http://www.annualreviews.org/doi/pdf/10.1146/annurev-biochem-062209-093836>.
Cabrita LD, Dobson CM, Christodoulou J. Protein folding on the ribosome. Current Opinion in Structural Biology 2010, doi:10.1016/j.sbi.2010.01.005
A Keith Dunker, Israel Silman, Vladimir N Uversky, Joel L Sussman. "Function and structure of inherently disordered protein." Curr Opin Struct Biol. 2008 Dec;18(6):756-64
Booth Paula J, Curnow Paul. Folding Scene Investigation: Membrane Proteins. Current Opinion in Structural Biology 2009, doi:10.1016/j.sbi.2008.12.005
Heijne, Gunnar Von. "Membrane Protein Folding and Insertion." Annual Review of Biochemistry 80 (2011): 157-60. 26 Oct. 2011 <http://www.annualreviews.org/doi/full/10.1146/annurev-biochem-111910-091345?url_ver=Z39.88-2003&rfr_id=ori:rid:crossref.org&rfr_dat=cr_pub%3dpubmed>
Kuhn, Andreas, Rosemary Stuart, Ralph Henry, and Ross E. Dalbey. "The Alb3/Oxa1/YidC protein family: membrane-localized chaperones facilitating membrane protein insertion?" TRENDS in Cell Biology 13 (2003): 510-16. 26 Oct. 2011 <http://www.cell.com/trends/cell-biology/abstract/S0962-8924(03)00196-X>
Table 1: Berg, Jeremy. Relative Frequencies of Amino Acid Residues in Secondary Structures. 2012. Biochemistry, New York . Print.
Voet, Donald, Judith G. Voet. Biochemistry 3rd ed. New Jersey: John Wiley & Sons, Inc, 2004. Print.
ht9cge0blbtqsegzjefckmmqdzcpbb1
Radiation Oncology/Protons/Economics
0
174701
4675970
1793905
2026-10-14T05:31:42Z
Jcb
90773
4675970
wikitext
text/x-wiki
{{:Radiation_Oncology:TOC}}
<big>'''Economic Issues Related to Proton Therapy'''</big>
*'''Lyon, France; 2010''' {{PMID|20452693}} -- "Simulating demand for innovative radiotherapies: An illustrative model based on carbon ion and proton radiotherapy." (Pommier P, Radiother Oncol. 2010 May 7. [Epub ahead of print])
**Probabilistic model developed to allocate patients to the optimal treatment strategy and facility
**Conclusion: Modelling patient recruitment may aid decision-making when planning new and expensive treatments
*'''Maastricht, The Netherlands'''
**'''Cost Effectiveness; 2008''' {{PMID|18707784}} -- "Cost-effectiveness of particle therapy: Current evidence and future needs." (Pijls-Johannesma M, Radiother Oncol. 2008 Nov;89(2):127-34. Epub 2008 Aug 15.)
***Literature review of cost and cost-effectiveness of proton therapy
***Outcome: Literature scarce, non-comparable, and not performed according to standard health technology assessment criteria
***Conclusion: Model-based economic evaluations may help gain evidence-based insight into cost-effectiveness
**'''Facilities; 2010''' {{PMID|20106540}} -- "How costly is particle therapy? Cost analysis of external beam radiotherapy with carbon-ions, protons and photons." (Peeters A, Radiother Oncol. 2010 Jan 25. [Epub ahead of print])
***Estimate of capital and operational costs, cost per fraction, and 4 tumor-specific treatment costs. Facilities: carbon/proton facility, proton only, and photon only
***Outcome:
****Capital costs: Euro 139 M vs 95 M vs 23 M
****Operational costs: Euro 37 M vs 25 M vs 10 M
****Cost per fraction: Euro 1,128 vs 743 vs 233
***Conclusion: Costs evaluated
**'''NSCLC; 2010''' {{PMID|20303217}} -- "The cost-effectiveness of particle therapy in non-small cell lung cancer: Exploring decision uncertainty and areas for future research." (Grutters JP, Cancer Treat Rev. 2010 Mar 17. [Epub ahead of print])
***Markov model. Comparative treatments carbon-ion, protons, conventional RT, and SBRT for Stage I NSCLC
***Outcome: For inoperable NSCLC, Carbon cost euro 67,257 per QALY compared to SBRT; both carbon and SBRT dominated protons and conventional RT. For operable NSCLC, SBRT dominated carbon ion. Considerable uncertainity in estimates
***Conclusion: It is recommended not to adopt particle therapy in Stage I NSCLC until more evidence is available
*'''Fox Chase; 2007''' {{PMID|17704408}} -- "Is proton beam therapy cost effective in the treatment of adenocarcinoma of the prostate?" (Konski A, J Clin Oncol. 2007 Aug 20;25(24):3603-8.)
**Markov model. Cost-effectiveness evaluation of 91.8 CGE proton beam vs. 81 CGE photon IMRT, using cost, bNED, utility data
**15 year model: 70 year old: cost of protons $63,500 vs. IMRT $36,800; 60 year old: protons $65,000 vs. photons $39,400. Incremental cost/QALY 70-year old $63,6000 and 60-year old $55,700
**Conclusion: Assuming 10 Gy additional dose-escalation, proton beam not cost-effective for most patients
**Editorial ({{PMID|17704400}}): PT legitimate form of EBRT for prostate cancer, but if dose escalation cannot be achieved over existing therapies, economic utility relies on clear and meaningful difference in quality of life. This area should be investigated urgently
*'''Yale; 2007''' {{PMID|17500444}} -- "Point/counterpoint. Proton therapy is too expensive for the minimal potential improvements in outcome claimed." (Schulz RJ, Med Phys. 2007 Apr;34(4):1135-8.)
*'''ENLIGHT; 2005'''
**[http://www.estroweb.org/ESTRO/frame/template.cfm?id=90 Workgroup reports]
*'''Sweden; 2005''' {{PMID|15885828}} -- "Economic evaluation of proton radiation therapy in the treatment of breast cancer." (Lundkvist J, Radiother Oncol. 2005 May;75(2):179-85.)
**Markov model simulation, 55 year old patient with left-sided BCA
**Outcome: Euro 67,000 cost per QALY gained; better if high risk cardiac patients treated
**Conclusion: Proton therapy for BCA can be cost-effective if appropriate risk groups are chosen
**Editorial ({{PMID|15890422}}): From global health care point of view, cost of proton therapy is not outrageous at all
*'''Sweden Acta Oncol Issue; 2005'''
**'''Editorial; 2005''' {{PMID|16332585}} -- "Swedish protons." (Goitein M, Acta Oncol. 2005;44(8):793-7.)
***Editorial for an issue of Acta Oncologica dedicated to protons
**'''Eligible patients; 2005''' {{PMID|16332591}} -- "Number of patients potentially eligible for proton therapy." (Glimelius B, Acta Oncol. 2005;44(8):836-49.)
***Estimate of number of patients in Sweden suitable for proton beam. Assume facility focused on randomized and prospective studies to show benefit
***Outcome: 2200-2500 patients annually eligible with sufficient therapeutic benefit; ~15% of all patients undergoing RT annually
**'''Cost-effectiveness; 2005''' {{PMID|16332592}} -- "Proton therapy of cancer: potential clinical advantages and cost-effectiveness." (Lundkvist J, Acta Oncol. 2005;44(8):850-61.)
***Markov simulation. Cost per QALY Euro 10,130. If value of QALY set at Euro 55,000 then total annual benefit to treating 925 patients is Euro 20.8 million
***Conclusion: Investment in a proton facility may be cost-effective
**'''Breast; 2005''' {{PMID|16332597}} -- "The potential of proton beam radiation therapy in breast cancer." (Bjork-Eriksson T, Acta Oncol. 2005;44(8):884-9.)
***Estimates for ~300 breast cancer patients annually, out of 3425 total
**'''GI; 2005''' {{PMID|16332599}} -- "The potential of proton beam radiation therapy in gastrointestinal cancer." (Ask A, Acta Oncol. 2005;44(8):896-903.)
***Estimate for 345 patients, mainly nonresectable rectal/esophageal, and liver cancers
**'''GU/GYN; 2005''' {{PMID|16332598}} -- "The potential of proton beam radiation therapy in prostate cancer, other urological cancers and gynaecological cancers." (Johansson B, Acta Oncol. 2005;44(8):890-5.)
***Estimates for ~300 prostate patients and ~50 GYN patients annually
**'''Head & Neck; 2005''' {{PMID|16332595}} -- "The potential of proton beam radiation therapy in head and neck cancer." (Ask A, Acta Oncol. 2005;44(8):876-80.)
***Estimate ~300 patients annually with H&N cancers
**'''Intracranial/Ocular; 2005''' {{PMID|16332593}} -- "The potential of proton beam radiation therapy in intracranial and ocular tumours." (Blomquist E, Acta Oncol. 2005;44(8):862-70.)
***Estimates for CNS and ocular tumors, 130-180 total per year
**'''Lymphoma/Sarcoma; 2005''' {{PMID|16332601}} -- "The potentials of proton beam radiation therapy in malignant lymphoma, thymoma and sarcoma." (Bjork-Eriksson T, Acta Oncol. 2005;44(8):913-7.)
***Estimates for lymphoma ~20 patients/year, and sarcoma (not skull base) ~40/year
**'''Medulloblastoma; 2005''' {{PMID|15637691}} -- "Cost-effectiveness of proton radiation in the treatment of childhood medulloblastoma." (Lundkvist J, Cancer. 2005 Feb 15;103(4):793-801.)
***Markov simulation, children age 5 followed for tumor control and adverse events
***Outcome: Proton therapy 23,600 cost saving, 0.68 additional QALY per patient. Biggest benefit due to reduction in IQ and GHD loss
***Conclusion: Proton therapy can be cost-effective and cost-saving compared with conventional RT
**'''Palliation/Reirradiation; 2005''' {{PMID|16332602}} -- "The potential of proton beam radiation for palliation and reirradiation." (Bjork-Eriksson T, Acta Oncol. 2005;44(8):918-20.)
***Estimates for palliation and irradiation; ~100 palliative treatments and ~150 re-irradiation treatments might benefit
**'''Pediatric; 2005''' {{PMID|16332594}} -- "The potential of proton beam therapy in paediatric cancer." (Bjork-Eriksson T, Acta Oncol. 2005;44(8):871-5.)
***Estimates 80-100 pediatric cases/year, ~20 with medulloblastoma
**'''Thorax; 2005''' {{PMID|16332596}} -- "The potential of proton beam radiation therapy in lung cancer (including mesothelioma)." (Bjelkengren G, Acta Oncol. 2005;44(8):881-3.)
***Estimate ~350 patients with lung cancer and ~20 patients with mesothelioma annually may benefit from proton beam therapy
*'''France; 2004''' {{PMID|15974560}} -- "A "one-day survey": as a reliable estimation of the potential recruitment for proton- and carbon- ion therapy in France." (Baron MH, Radiother Oncol. 2004 Dec;73 Suppl 2:S15-7.)
**Survey. Performed in 1 day, all new starts in 5 RT centers
**Outcome: 77/532 (14%) of patients might be potential candidates for hadrontherapy
*'''MedAustron, Austria'''
**'''2004''' {{PMID|15971304}} -- "Epidemiological aspects of hadron therapy: a prospective nationwide study of the Austrian project MedAustron and the Austrian Society of Radiooncology (OEGRO)." (Mayer R, Radiother Oncol. 2004 Dec;73 Suppl 2:S24-8.)
***Nationwide survey, over period of 3 months. See below for full detail
***Outcome: Potential patients 2044 per year, which is 13% of irradiated patients and 6% of newdly diagnosed cancer patients
***Conclusion: There is a place for hadron therapy facility in Austria
**'''2004''' {{PMID|15971305}} -- "The med AUSTRON/OGRO patterns of care study on radiotherapy indications in Austria." (Mock U, Radiother Oncol. 2004 Dec;73 Suppl 2:S29-34.)
***National survey, 12 RT departments in Austria, over period of 3 months
***Outcome: 3783 patients registered. Indications reviewed (breast CA ~26%, urologic tumors ~12%, bone metastases ~10%)
***Conclusion: Most common indications established, variations among departments observed
**'''1999''' {{PMID|10394411}} -- "Cancer epidemiology and patient recruitment for hadron therapy." (Engles H, Strahlenther Onkol. 1999 Jun;175 Suppl 2:95-9.)
***Review of cancer incidence; estimate of potential patients suitable for hadron therapy
***Conclusion: Sufficient and adequate recruitment can be expected
*'''CNAO Italy'''
**'''2004''' {{PMID|15971303}} -- "Medical aspects of the National Centre For Oncological Hadrontherapy (CNAO-Centro Nazionale Adroterapia Oncologica) in Italy." (Krengli M, Radiother Oncol. 2004 Dec;73 Suppl 2:S21-3.)
***Review of Centro Nazionale Adroterapia Oncologica (CNAO) rationale
***Updated estimate of 10-15% irradiated patients would benefit from ion therapy
**'''1998''' {{PMID|9620246}} -- "Number of potential patients to be treated with proton therapy in Italy." (Orecchia R, Tumori. 1998 Mar-Apr;84(2):205-8.)
***Estimate of patients who might benefit from proton therapy in Italy.
***Outcome: Category A (clear benefit) = 825 patients. Category B (potential benefit) = >10,000
***Conclusion: ~16% of irradiated patients might be candidates for proton therapy
*'''Switzerland; 2003''' {{PMID|12602563}} -- "The relative costs of proton and X-ray radiation therapy." (Goitein M, Clin Oncol (R Coll Radiol). 2003 Feb;15(1):S37-50.)
**Estimated costs for both 2-room proton and photon based facilities, both currently and in the future with improved efficiency and costs.
**Cost estimate: facility proton 62.5 M euro vs. linac 16.8 M euro (3.7x). Per fraction 1025 euro vs. 425 euro (2.4x). Future costs could be 370 euro vs 230 euro (1.6x)
**Conclusion: Ratio of costs is ~2.4x at present, and could come down to 2.1x and even 1.7x over the next 5-10 years
cn787jlssb5q9abovfoxn4fpkzshnpl
Radiation Oncology/Randomized/Protons
0
175336
4675985
1726386
2026-10-14T06:05:43Z
Jcb
90773
4675985
wikitext
text/x-wiki
{{:Radiation_Oncology:TOC}}
<big>'''Randomized Evidence in Proton Therapy'''</big>
==Ocular melanoma==
*'''MGH; 2000''' (1989-1998) {{PMID|10865313}} -- "A randomized controlled trial of varying radiation doses in the treatment of choroidal melanoma." (Gragoudas ES, Arch Ophthalmol. 2000 Jun;118(6):773-8.)
**Randomized. 188 patients with small/medium choroidal melanoma (<15mm diameter, <5mm height), within 4 disc diameters of optic disc or macula. Arm 1) 50 CGE vs. Arm 2) 70 CGE
**5-year outcome: visual acuity >20/200 similar at 55%; tumor regrowth similar at ~3%; mets similar at ~8%
**Toxicity: 50 CGE significantly less visual loss; no difference in radiation papillopathy or maculopathy
**Conclusion: Lower dose resulted in similar outcome, similar visual acuity loss, but improved visual field loss
==Prostate==
*'''PROG 95-09''' (1996-1999) -- Proton/photon 70.2 Gy vs. proton/photon 79.2 Gy
**Randomized. 2 institutions (Harvard and Loma Linda). 392 patients, stage T1b-T2b, PSA <15 ng/mL (median PSA 6.3). Arm 1) proton boost 19.8/11 GyE followed by photons 50.4/28 vs. Arm 2) proton boost 28.8/16 followed by photons 50.4/28. Proton CTV = prostate + 5 mm margin. PTV = CTV + 7-10 mm. Loma Linda used opposed lateral beams, 250 MeV protons; Harvard used perineal boost, 160 MeV protons. Rectal Lucite probe, inflated with 25-50 mL saline. Photons were 4F plan, photon CTV = prostate/SV + 10 mm margin.
**'''5-years; 2005''' {{PMID|16160131}} -- "Comparison of conventional-dose vs high-dose conformal radiation therapy in clinically localized adenocarcinoma of the prostate: a randomized controlled trial." (Zietman AL, JAMA. 2005 Sep 14;294(10):1233-9.) Median F/U 5.5 years
***Outcome: 5-year bNED 70.2 Gy 61% vs. 79.2 Gy 80% (SS), 50% reduction in risk of failure. LC (defined as PSA <1.0) 48% vs. 67% (SS) No difference in OS 97% vs 96% (NS)
***Risk stratification: low risk (PSA <10, stage <=T2a, GS <7) 60% vs. 80% (SS); high risk 63% vs. 79% (SS). Contemporary intermediate risk 63% vs. 81% (SS), but contemporary high risk (NS, but small number)
***Late toxicity: Grade 3+ 70.2 Gy 1% vs. 79.2 2%; GU Grade 2 18% vs. 20% (NS), GI Grade 2 8% vs. 17% (SS). Most GI toxicity by 3 years; GU toxicity continuous
***Conclusion: Men with clinically localized PCA have better bNED with high dose, without worse severe toxicity
**'''10-years; 2010''' {{PMID|20124169}} -- "Randomized Trial Comparing Conventional-Dose With High-Dose Conformal Radiation Therapy in Early-Stage Adenocarcinoma of the Prostate: Long-Term Results From Proton Radiation Oncology Group/American College of Radiology 95-09." (Zietman AL, J Clin Oncol. 2010 Mar 1;28(7):1106-11.) Median F/U 8.9 years
***Outcome: 10-year ASTRO (backdating) bPFS low-dose 68% vs. high-dose 83% (SS). For low-risk disease 72% vs 93% (SS); for intermediate-risk 58% vs. 70% (p=0.06). No difference in OS (78% vs 83%)
***Toxicity: Late Grade 2+ low-dose 29% vs. high-dose 39% (SS); Grade 3+ 2% in both arms (NS)
***Conclusion: Long-term advantage for high dose in low/intermediate risk PCA patients, with comparable Grade 3 toxicity
*'''Harvard''' (1982-1992) -- Proton (dose escalated) vs. photon boost
**Randomized. 202 patients, Stage T3-T4Nx,0-2. Standard photons 50.4 Gy four-field, then Arm 1) Conformal protons 25.2 CGE (total 75.6 CGE) vs. Arm 2) Photons 16.8 Gy (total 67.2 Gy). Median F/U 5.1 years
**'''5-years; 1995''' {{PMID|7721636}} -- "Advanced prostate cancer: the results of a randomized comparative trial of high dose irradiation boosting with conformal protons compared with conventional dose irradiation using photons alone." (Shipley WU, Int J Radiat Oncol Biol Phys. 1995 Apr 30;32(1):3-12.)
***Outcome: 5-year LC photon+proton 92% vs. photons 80% (NS), no difference in OS, DSS, TRFS. GS 4/5 patients 94% vs. 64% (SS)
***Toxicity: Rectal bleeding photon+proton 32% vs. photons 12% (SS), urethral stricture 19% vs. 8% (p=0.07)
***Conclusion: Boosting dose with protons increased LC in poorly differentiated tumors, but also worsened late toxicity
sjndrlmacxy82dvt3vp2lpd40s2phex
Haskell/Monoids
0
181604
4675964
4656136
2026-10-14T01:30:11Z
~2026-54868-50
3628373
4675964
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Advanced Haskell}}
In earlier parts of the book, we have made a few passing allusions to monoids and the <code>Monoid</code> type class (most notably when discussing [[Haskell/MonadPlus#Relationship with monoids|MonadPlus]]). Here we'll give them a more detailed look and show what makes them useful.
== What is a monoid? ==
The operation of adding numbers has a handful of properties which are so elementary we don't even think about them when summing numbers up. One of them is ''associativity'': when adding three or more numbers it doesn't matter how we group the terms.
<syntaxhighlight lang="haskell">
GHCi> (5 + 6) + 10
21
GHCi> 5 + (6 + 10)
21
</syntaxhighlight>
Another one is that it has an ''identity element'', which can be added to any other number without changing its value. That element is the number zero:
<syntaxhighlight lang="haskell">
GHCi> 255 + 0
255
GHCi> 0 + 255
255
</syntaxhighlight>
Addition is not the only binary operation which is associative and has an identity element. Multiplication does too, albeit with a different identity.
<syntaxhighlight lang="haskell">
GHCi> (5 * 6) * 10
300
GHCi> 5 * (6 * 10)
300
GHCi> 255 * 1
255
GHCi> 1 * 255
255
</syntaxhighlight>
We needn't restrict ourselves to arithmetic either. <code>(++)</code>, the appending operation for Haskell lists, is another example. It has the empty list as its identity element.
<syntaxhighlight lang="haskell">
GHCi> ([1,2,3] ++ [4,5,6]) ++ [7,8,9]
[1,2,3,4,5,6,7,8,9]
GHCi> [1,2,3] ++ ([4,5,6] ++ [7,8,9])
[1,2,3,4,5,6,7,8,9]
GHCi> [1,2,3] ++ []
[1,2,3]
GHCi> [] ++ [1,2,3]
[1,2,3]
</syntaxhighlight>
It turns out there are a great many associative binary operations with an identity. All of them, by definition, give us examples of ''monoids''. We say, for instance, that the integer numbers form a monoid under addition with <code>0</code> as identity element.
== Semigroups ==
Before we can look into how Haskell implements monoids, we must first examine a closely related concept, semigroups. If we remove the requirement to have an identity element from a monoid and keep only the associative binary operation, we get a semigroup. Monoids are just semigroups with an identity element, but not all semigroups are monoids. Haskell defines a typeclass <code>Semigroup</code> that represents them:
<syntaxhighlight lang="haskell">
class Semigroup a where
(<>) :: a -> a -> a
sconcat :: NonEmpty a -> a
</syntaxhighlight>
The first method, the operator <code>(<>)</code> represents the binary operation that characterises a semigroup.
The second method, <code>sconcat</code>, takes a ''non-empty'' list and reduces it using <code>(<>)</code>. Recall that semigroups do not have an identity element we can use as a default, and so the list must not be empty. The <code>NonEmpty</code> type is just a way of enforcing a non-empty list.
Both methods have default implementations in terms of each other, that is, it is sufficient to define a <code>Semigroup</code> by providing at least one of the two methods of your choice. For clarity of illustration, though, we will only be defining <code>(<>)</code> for the most part.
We previously alluded to the existence of semigroups that are not monoids (i.e. do not have an identity element). Most of the semigroups you will encounter in Haskell are also monoids, although there are exceptions. The <code>Min</code> newtype from <code>Data.Semigroup</code> is an example:
<syntaxhighlight lang="haskell">
newtype Min a = Min { getMin :: a }
instance (Ord a) => Semigroup (Min a) where
(Min a) <> (Min b) = Min (min a b)
</syntaxhighlight>
The <code>Min</code> newtype wraps two instances of <code>Ord</code> (elements that have an order, e.g. integers), and <code>(<>)</code> results in the minimum of the two operands. We can confirm that this binary operation is associative:
<syntaxhighlight lang="haskell">
GHCi> getMin $ (Min 1 <> Min 2) <> Min 3
1
GHCi> getMin $ Min 1 <> (Min 2 <> Min 3)
1
</syntaxhighlight>
There is no requirement for an identity element. If you add an extra requirement for <code>a</code> to have a minimum value (via a constraint on <code>Bounded</code>), <code>Min</code> does provide an instance of the <code>Monoid</code> typeclass, and this brings us into discussing <code>Monoid</code> itself.
== The <code>Monoid</code> class ==
Monoids show up very often in Haskell, and so it is not surprising to find there is a type class for them in the core libraries. Here it is:
<syntaxhighlight lang="haskell">
class Semigroup a => Monoid a where
mempty :: a
mconcat :: [a] -> a
mconcat = foldr (<>) mempty
</syntaxhighlight>
Unsurprisingly, <code>Semigroup</code> is a superclass of <code>Monoid</code>.
Note that we did not have to define the binary operation again, since it's already provided from the <code>Semigroup</code> constraint. In older code, you may instead see a method with a name of <code>mappend :: a -> a -> a</code>, but this is a historical artifact from when <code>Semigroup</code> was not a superclass of <code>Monoid</code> (analogous to the relation between <code>return</code> and <code>pure</code> in <code>Monad</code> and <code>Applicative</code>). Nowadays, <code>mappend</code> has a default implementation in terms of <code>(<>)</code> to ease the transition, and is slated for removal in a future release of the GHC. If you see a use of <code>mappend</code>, mentally interchange it with <code>(<>)</code>.
The method <code>mempty</code> is the identity of the monoid. The second method, <code>mconcat</code>, is provided as a bonus; it runs down a list and <code>(<>)</code>s its elements together in order.
As an example, this is the monoid instance for lists:
<syntaxhighlight lang="haskell">
instance Semigroup [a] where
(<>) = (++)
instance Monoid [a] where
mempty = []
</syntaxhighlight>
Note that, in this case, <code>mconcat = foldr (++) []</code> is equivalent to <code>concat</code>, which explains the name of the method.
It is legitimate to think of monoids as types which support ''appending'' in some sense, though a dose of poetic licence is required. The <code>Monoid</code> definition is extremely general and not at all limited to data structures, so "appending" will be just a metaphor at times.
As we suggested earlier on, numbers (i.e. instances of <code>Num</code>) form monoids under both addition and multiplication. That leads to the awkward question of which one to choose when writing the instance. In situations like this one, in which there is no good reason to choose one possibility over the other, the dilemma is averted by creating one <code>newtype</code> for each instance:
<syntaxhighlight lang="haskell">
-- | Monoid under addition.
newtype Sum a = Sum { getSum :: a }
-- | Monoid under multiplication.
newtype Product a = Product { getProduct :: a }
instance Num a => Semigroup (Sum a) where
Sum x <> Sum y = Sum (x + y)
instance Num a => Monoid (Sum a) where
mempty = Sum 0
instance Num a => Semigroup (Product a) where
Product x <> Product y = Product (x * y)
instance Num a => Monoid (Product a) where
mempty = Product 1
</syntaxhighlight>
Here is a quick demonstration of <code>Sum</code> and <code>Product</code>:
<syntaxhighlight lang="haskell">
GHCi> import Data.Monoid
GHCi> Sum 5 <> Sum 6 <> Sum 10
Sum {getSum = 21}
GHCi> mconcat [Sum 5, Sum 6, Sum 10]
Sum {getSum = 21}
GHCi> getSum . mconcat . fmap Sum $ [5, 6, 10]
21
GHCi> getProduct . mconcat . fmap Product $ [5, 6, 10]
300
</syntaxhighlight>
=== <code>Monoid</code> laws ===
The laws which all instances of <code>Monoid</code> must follow simply state the properties we already know: <code>(<>)</code> is associative and <code>mempty</code> is its identity element.
<syntaxhighlight lang="haskell">
(x <> y) <> z = x <> (y <> z) -- associativity
mempty <> x = x -- left identity
x <> mempty = x -- right identity
</syntaxhighlight>
{{Exercises|
# There are several possible monoid instances for <code>Bool</code>. Write at least two of them using <code>newtype</code>s, as in the <code>Sum</code> and <code>Product</code> examples. Be sure to verify the monoid laws hold for your instances <ref>You will later find that two of those instances are defined in <code>Data.Monoid</code> already.</ref>.<!-- Suppressed for silliness
# It is possible, though very unnatural, to define <code>mempty</code> and <code>mappend</code> in terms of <code>mconcat</code>. Write the definition of this. Figure out whether or not your definition automatically fulfils the above laws.
# There is a third basic property of both addition and multiplication which is just as familiar as associativity or the existence of an identity element. However, we made no mention of it in the discussion above. What is it? Explain in a few words (perhaps with an example) why it is not relevant to the discussion above.-->
}}
== Uses ==
<!-- The beginning of this section might be too slow, depending on where this chapter will end up in the book.-->
Which advantages are there in having a class with a pompous name for such a simple concept? As usual in such cases, the key gains are in two associated dimensions: recognisability and generality. Whenever, for instance, you see <code>(<>)</code> being used you know that, however the specific instance was defined, the operation being done is associative and has an identity element. Moreover, you also know that if there is an instance of <code>Monoid</code> for a type you can take advantage of functions written to deal with monoids in general. As a toy example of such a function, we might take this function that concatenates three lists..
<syntaxhighlight lang="haskell">
threeConcat :: [a] -> [a] -> [a] -> [a]
threeConcat a b c = a ++ b ++ c
</syntaxhighlight>
... and replace all <code>(++)</code> with <code>(<>)</code>...
<syntaxhighlight lang="haskell">
mthreeConcat :: Monoid m => m -> m -> m -> m
mthreeConcat a b c = a <> b <> c
</syntaxhighlight>
... thus making it work with any <code>Monoid</code>. When used on other types the generalised function will behave in an analogous way to the original one, as specified by the monoid laws.
<syntaxhighlight lang="haskell">
GHCi> mthreeConcat "Hello" " " "world!"
"Hello world!"
GHCi> mthreeConcat (Sum 5) (Sum 6) (Sum 10)
Sum {getSum = 21}
</syntaxhighlight>
Monoids are extremely common, and have many interesting practical applications.
; The <code>Writer</code> monad : A computation of type <code>Writer w a</code> computes a value of type <code>a</code> while producing extra output of type <code>w</code> which must be an instance of <code>Monoid</code>, and the bind operator of the monad uses <code>(<>)</code> to accumulate the extra output. A typical use case would be logging, in which each computation produces a log entry for later inspection. In the logging use case, that would mean all entries generated during a series of computations are automatically combined into a single log output.
<!--TODO: Trim this entry once there actually is a Foldable chapter. -->
; The <code>Foldable</code> class : Monoids play an important role in generalising list-like folding to other data structures. We will study that in detail in the upcoming [[Haskell/Foldable|chapter about the <code>Foldable</code> class]].
; Finger trees : Moving on from operations on data structures to data structure implementations, monoids can be used to implement ''finger trees'', an efficient and versatile data structure. Its implementation makes use of monoidal values as tags for the tree nodes; and different data structures (such as sequences, priority queues, and search trees) can be obtained simply by changing the involved <code>Monoid</code> instance.<ref>[http://apfelmus.nfshost.com/articles/monoid-fingertree.html This blog post], based on a [http://www.soi.city.ac.uk/~ross/papers/FingerTree.html paper by Ralf Hinze and Ross Patterson], contains a brief and accessible explanation on how monoids are used in finger trees.</ref>
; Options and settings: In a wholly different context, monoids can be a handy way of treating application options and settings. Two examples are Cabal, the Haskell packaging system ("Package databases are monoids. Configuration files are monoids. Command line flags and sets of command line flags are monoids. Package build information is a monoid.") and [http://xmonad.org XMonad], a tiling window manager implemented in Haskell ("xmonad configuration hooks are monoidal.") <ref>Sources of the quotes (Haskell Cafe mailing list): [http://www.haskell.org/pipermail/haskell-cafe/2009-January/053602.html], [http://www.haskell.org/pipermail/haskell-cafe/2009-January/053603.html].</ref>. Below are snippets from a XMonad configuration file (which is just a Haskell program) showing the monoidal hooks in action <ref>The snippets were taken from [https://wiki.haskell.org/Xmonad/Config_archive/ivy-foster-xmonad.hs Ivy Foster's example config in the HaskellWiki] and XMonad's {{Haskell lib|p=xmonad|v=0.11|XMonad|ManageHook}} module as of version 0.11.</ref>.
<syntaxhighlight lang="haskell">
-- A ManageHook is a rule, or a combination of rules, for
-- automatically handling specific kinds of windows. It
-- is applied on window creation.
myManageHook :: ManageHook
myManageHook = composeAll
[ manageConkeror
, manageDocs
, manageEmacs
, manageGimp
, manageImages
, manageTerm
, manageTransient
, manageVideo
, manageWeb
, myNSManageHook scratchpads
]
-- manageEmacs, for instance, makes a duplicate of an Emacs
-- window in workspace 3 and sets its opacity to 90%. It
-- looks like this:
-- liftX lifts a normal X action into a Query (as expected by -->)
-- idHook ensures the proper return type
manageEmacs :: ManageHook
manageEmacs =
className =? "Emacs"
--> (ask >>= doF . \w -> (copyWindow w "3:emacs"))
<+> (ask >>= \w -> liftX (setOpacity w 0.9) >> idHook)
-- The hooks are used as fields of the XMonad configuration,
-- which is passed to the IO action that starts XMonad.
myConfig xmproc = defaultConfig
{ -- Among other fields...
, manageHook = myManageHook
}
-- idHook, (<+>), composeAll and (-->) are just user-friendly
-- synonyms for monoid operations, defined in the
-- XMonad.ManageHook module thusly:
-- | The identity hook that returns the WindowSet unchanged.
idHook :: Monoid m => m
idHook = mempty
-- | Infix 'mappend'. Compose two 'ManageHook' from right to left.
(<+>) :: Monoid m => m -> m -> m
(<+>) = mappend
-- | Compose the list of 'ManageHook's.
composeAll :: Monoid m => [m] -> m
composeAll = mconcat
-- | @p --> x@. If @p@ returns 'True', execute the 'ManageHook'.
--
-- > (-->) :: Monoid m => Query Bool -> Query m -> Query m -- a simpler type
(-->) :: (Monad m, Monoid a) => m Bool -> m a -> m a
p --> f = p >>= \b -> if b then f else return mempty
</syntaxhighlight>
[[File:Monoids diagrams demo.svg|thumb|A simple <code>diagrams</code> example. The code for it is:<syntaxhighlight lang="haskell">
mconcat (fmap
(circle . (/20)) [1..5])
<> triangle (sqrt 3 / 2)
# lwL 0.01 # fc yellow
<> circle 0.5 # lwL 0.02
# fc deepskyblue
</syntaxhighlight>]]
; <code>diagrams</code>: The [http://projects.haskell.org/diagrams <code>diagrams</code>] package provides a powerful library for generating vectorial images programatically. On a basic level, <code>(<>)</code> appears often in code using <code>diagrams</code> because squares, rectangles and other such graphic elements have <code>Monoid</code> instances which are used to put them on the top of each other. On a deeper level, most operations with graphic elements are internally defined in terms of monoids, and the implementation takes full advantage of their mathematical properties.
== Homomorphisms ==
Given any two monoids <code>A</code> and <code>B</code>, a function <code>f :: A -> B</code> is a '''monoid homomorphism''' if it preserves the monoid structure, so that:
<syntaxhighlight lang="haskell">
f mempty = mempty
f (x <> y) = f x <> f y
</syntaxhighlight>
In words, <code>f</code> takes <code>mempty :: A</code> to <code>mempty :: B</code>, and the result of <code>(<>)</code> for <code>A</code> to the result of <code>(<>)</code> for <code>B</code> (after using <code>f</code> to turn the arguments to <code>(<>)</code> into <code>B</code> values).
As an example, <code>length</code> is a monoid homomorphism between (<code>[a]</code>,<code>++</code>) and (<code>Int</code>,<code>+</code>):
<syntaxhighlight lang="haskell">
length [] = 0
length (xs ++ ys) = length xs + length ys
</syntaxhighlight>
When attempting to determine if a given function is a homomorphism do not concern yourself with the actual implementation; although its definition clearly influences whether or not it is a homomorphism, a homomorphism is defined by a function's ability to preserve the operations of the two underlying structures involved in the mapping and is not directly tied to implementation details.
An interesting example "in the wild" of monoids and homomorphisms was identified by Chris Kuklewicz amidst the Google Protocol Buffers API documentation.<ref>[http://www.haskell.org/pipermail/haskell-cafe/2009-January/053709.html Source (Haskell Cafe)]</ref> Based on the quotes provided in the referenced comment, we highlight that the property that (in C++):
<syntaxhighlight lang="c++">
MyMessage message;
message.ParseFromString(str1 + str2);
</syntaxhighlight>
... is equivalent to...
<syntaxhighlight lang="c++">
MyMessage message, message2;
message.ParseFromString(str1);
message2.ParseFromString(str2);
message.MergeFrom(message2);
</syntaxhighlight>
... means that <code>ParseFromString</code> is a monoid homomorphism. In a hypothetical Haskell implementation, the following equations would hold:
<syntaxhighlight lang="haskell">
parse :: String -> Message
-- these are just equations, not actual code.
parse [] = mempty
parse (xs ++ ys) = parse xs `mergeFrom` parse ys
</syntaxhighlight>
(They wouldn't hold ''perfectly'', as parsing might fail, but roughly so.)
Recognising a homomorphism can lead to useful refactorings. For instance, if <code>mergeFrom</code> turned out to be an expensive operation it might be advantageous in terms of performance to concatenate the strings before parsing them. <code>parse</code> being a monoid homomorphism would then guarantee the same results would be obtained.
== Further reading ==
* Dan Piponi (Sigfpe) on monoids: [http://sigfpe.blogspot.com/2009/01/haskell-monoids-and-their-uses.html a blog post overview]; [http://www.haskell.org/pipermail/haskell-cafe/2009-January/053798.html a comment about intuition on associativity].
* [http://groups.google.com/group/bahaskell/browse_thread/thread/4cf0164263e0fd6b/42b621f5a4da6019 Many monoid related links]
* Additional comment on finger trees (Haskell Cafe): [http://www.haskell.org/pipermail/haskell-cafe/2009-January/053689.html FingerTrees].
* Additional comments on <code>Monoid</code> usage in Cabal (Haskell Cafe): [http://www.haskell.org/pipermail/haskell-cafe/2009-January/053626.html]; [http://www.haskell.org/pipermail/haskell-cafe/2009-January/053721.html].
* On <code>diagrams</code> and monoids: [http://dept.cs.williams.edu/~byorgey/publications.html ''Monoids: Theme and Variations (Functional Pearl)''], by Brent Yorgey.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Advanced Haskell}}
r0ih2itkwukd9vlte9fe7fpj5regjys
Talk:Radiation Oncology/Head & Neck/Post-op
1
185351
4675975
1402862
2026-10-14T05:59:04Z
Jcb
90773
4675975
wikitext
text/x-wiki
To Add:
*Phase III surgery vs RT
**{{PMID|113626}}
**{{PMID|113627}}
*Phase III trials preop RT vs. surgery alone
**{{PMID|14115324}}, {{PMID|5931768}}, {{PMID|5925257}}
**{{PMID|5347088}}
**{{PMID|7010651}}
**{{PMID|4812753}}
*Phase III trials preop vs post RT
**{{PMID|718066}}
**{{PMID|7382709}}, {{PMID|7270130}}
**{{PMID|3449477}}
**{{PMID|1993628}}
**{{PMID|322836}}
o3xgykprb60mdcimv5xbs8jcho4pvin
Talk:Radiation Oncology/NSCLC/Locally Advanced Unresectable
1
187757
4675976
1732322
2026-10-14T05:59:27Z
Jcb
90773
4675976
wikitext
text/x-wiki
To Add:
*{{PMID|19081652}}
mm0dvv6xxc2dmrz86v8gvc9ceqis3at
Radiation Oncology/Radiobiology/Growth Factors
0
195802
4675980
2715246
2026-10-14T06:01:38Z
Jcb
90773
4675980
wikitext
text/x-wiki
{{Radiation_Oncology:TOC}}
<big>'''Growth Factors'''</big>
==ErbB==
*Family of 4 receptor tyrosine kinases
**ErbB-1 ([[w:Epidermal_growth_factor_receptor|EGFR]])
**ErbB-2 ([[w:her2|her2]])
**ErbB-3
**ErbB-4
*Transmembrane proteins, existing as monomers at surface
*When a ligand binds, dimerisation arm becomes untethered, and the proteins dimerize
*Tyrosine kinase activity
==EGFR==
[[File:MAPKpathway diagram.svg|thumb|right]]
*Ligands:
**[[w:Epidermal_growth_factor|Epidermal growth factor (EGF)]]: produced by platelets, macrophages, salivary glands, kidneys
**[[w:TGF_alpha|Transforming growth factor alpha (TGF-α)]]: produced by macrophages, brain cells, keratinocytes
**[[w:HB-EGF|HB-EGF]], [[w:Amphiregulin|Amphiregulin]], [[w:Betacellulin|betacellulin]], [[w:Epigen|epigen]], [[w:Epiregulin|epiregulin]]: produced by various cells around the body
'''Review:''' {{PMID|15142631}}, Herbst R, IJROBP 2004
==EGFR Pathways==
*EGFR -> Ras -> Raf -> MEK -> MAPK -> myc -> transcription
*EGFR -> Ras -> Raf -> MEK -> MAPK -> RSK -> S6 -> transcription
*EGFR -> PI3K -> AKT -> mTOR
==PTEN==
*PTEN gene encodes a phosphatase, which uses PIP-3, which is also produced by PI3K above. Loss of PTEN therefore increases PIP-3 levels, leading to inappropriate AKT activity, and subsequent protection of cancer cells from apoptosis
*PTEN is a tumor suppressor
*PTEN loss confers resistance to EGFR inhibitors
*Please see [[Radiation Oncology/Cancer Syndromes/PTEN|PTEN Hamartoma Tumor Syndrome]]
1qiuovuienvoblxjwv1dm50musddqo5
Radiation Oncology/Radiobiology/Hypoxia
0
195803
4675981
3718282
2026-10-14T06:02:37Z
Jcb
90773
4675981
wikitext
text/x-wiki
{{Radiation_Oncology:TOC}}
<big>'''Hypoxia'''</big>
==Overview==
*Oxygen "fixes" (makes permanent) damage caused by free radicals (ion pair -> free radical -> DNA damage -> O2 fixation by making permanent DNA-peroxide bond)
**Must be present during or immediately (~5 msec) after RT
*Oxygen enhancement ratio (OER) ~2.5x
**Decreases with increasing LET: photons 2.5, neutrons 1.5, alpha 1.0
**Similarly, decreases with increasing RBE
**For photons, increases with dose and dose rate. If dose/fx <2 Gy OER ~1.5x, if dose/fx >2 Gy OER ~3x
*Measurements of oxygenation
**Evaluated directly by polarographic Eppendorf oxygen probes
**Exogenous: Nitroimidazoles (reduced and irreversibly bound under low O2 tension), EF5, carbon black
**Endogenous compounds: carbonic anhydrase (CA9), HIF, GLUT1 (need biopsy)
**Noninvasive imaging: PET F-18-miso, PET Cu-64-Cu-ATSM, SPECT I-123-azomycin arabinoside
*Hypoxia markers:
*O2 concentration
**Air 155 mmHg, 100% oxygen 760 mmHg
**O2 tension in tissues varies between 1 - 100 mmHg, venous blood ~30 mmHg. Many tissues normally borderline hypoxic
**Cell survival very sensitive to low level O2. At 0.2% O2 (1 mm Hg), survival curve noticeably different
**At 0.5% O2 (3 mm Hg), survival halfway to aerated
**Most rapid change between 0 and 30 mmHg
**Virtually no change in survival curve from venous to arterial to 100% oxygen
*O2 diffusion distance in metabolic active tissue 100-200 µm (Tomlinson-Gray hypothesis, {{PMID|13106296}})
*Hypoxia varies
**Spatially: within tumor
**Temporary: chronic (diffusion-mediated due to distance from blood vessels) vs acute (perfusion-mediated due to transient fluctuations in blood flow due to malformed vascular supply)
**From patient to patient
*Hypoxic fraction
**Can estimate by extrapolating back from shallow portion of the biphasic survival curve (steep portion is for oxygenated and shallow portion is for hypoxic cells)
**Ranges from 0-50%, on average ~15%
*Reoxygenation
**RT preferentially kills oxygenated cells. Hypoxic cells survive, but typically become re-oxygenated within 24 hours, just in time for the next fraction
**Therefore, if re-oxygenation is achieved, hypoxic cells do not have a significant effect on outcome of fractionated RT
**Lack of reoxygenation is potentially a concern for single fraction SRS/SBRT treatment approaches
**The extent and rapidity of re-oxygenation varies dramatically from tumor to tumor, and depend on proportion of chronic vs acute hypoxia present
*Hypoxic conditions may play a role in malignant progression, by decreasing apoptosis, increasing genomic instability and gene amplification, and by promoting angiogenesis
*Radiosensitization of hypoxic cells
**Improved oxygen delivery: Hyperbaric oxygen, perfluorocarbons, carbagen
**Tobacco cessation
**Drugs: nitroimidazoles (misonidazole showed limited effect, nimorazole significant improvement in a Danish H&N trial) for chronic hypoxia, nicotinamide for acute hypoxia
**Concurrent chemo: Mitomycin C, Tirapazamine
*Hypoxia imaging ({{PMID|28540739}}): the principal noninvasive approaches to imaging tumor hypoxia currently include magnetic resonance and radionuclides (PET and single-photon emission computed tomography), but other techniques, such as optical imaging or electron spin resonance, are under investigation
*Angiogenesis (see more below):
**Pro-angiogenesis: HIF-1α, VEGF, PDGF, FGF
**Anti-angiogenesis:
***Natural: VHL, TSP-1, Angiostatin, Endostatin, Heparin
***Drugs: bevacizumab, sunitinib, sorafenib, thalidomide
==Hypoxia Inducible Factor (HIF)==
*HIF proteins are a constitutively expressed family, including HIF-1α, HIF-1β, and HIF-2α
*[[w:EGLN2|EGLN2]] enzyme acts as a cellular oxygen sensor. It is a prolyl hydroxylase (PHD)
**Under normoxic conditions, it hydroxylates [[w:Hypoxia_inducible_factor_1a|HIF-1α]] using available oxygen
**Hydroxylated HIF-1α is recognized by [[w:VHL|Von Hippel-Lindau (VHL)]] protein, and marked for degradation by ubiquination
**Under hypoxic conditions EGLN2 does not have access to oxygen, and thus does not hydroxylate HIF-1α
*HIF-1α subsequently binds to HIF-1β, and the complex acts as a transcription factor on DNA hypoxia-responsive elements (HREs). Targets include
**[[w:Vascular_endothelial_growth_factor|VEGF]]: promotes angiogenesis
**[[w:GLUT1|GLUT-1]]: promotes glycolysis and oxygen-independent ATP production
**Stimulation of erythropoiesis
**Increase in apoptosis by interaction with Bcl-2 protein family and p53
*However, HIF-1α levels are also influenced by [[w:Ras_(protein)|Ras]] and [[w:PI3K|PI3K]] pathways, so that HIF-1α activity may not directly correlate with hypoxia
'''''Review'''''
*'''Duke 2005''' {{PMID|16098463}} -- "Pleiotropic effects of HIF-1 blockade on tumor radiosensitivity." (Moeller BJ, Cancer Cell. 2005 Aug;8(2):99-110.)
**Radiation increases HIF-1 activity in tumors, both sensitizing and protective:
***Radiosensitization: promotes ATP metabolism, proliferation, p53 activation
***Radioresistance: stimulates endothelial cell survival
**Net effect of HIF-1 blockade highly dependent on treatment sequencing, with "radiation first" being more effective due to preventing development of radioresistance effect
**Comment from '''MSKCC''' {{PMID|16098459}}
==Vascular Endothelial Growth Factor (VEGF)==
*Family of proteins resulting from alternate splicing of mRNA from a single VEGF gene
*Bind to tyrosine kinase receptors (VEGF-R) on cell surface, causing them to dimerize
*VEGF-R2 appears to modulate most known cellular responses
**Angiogenesis (endothelial cell migration, mitosis, creation of blood vessel lumen, fenestrations, etc)
**Chemotaxis for macrophages and granulocytes
**Vasodilation through NO release
*VEGF-R3 appears to mediate lymphangiogenesis
*Anti-VEGF therapies
**Monoclonal antibodies: [[w:bevacizumab|bevacizumab]] for cancer indications, [[w:ranibizumab|ranibizumab]] for macular degeneration
**Small molecule TKIs: [[w:sunitinib|sunitinib]], [[w:sorafenib|sorafenib]]
==Lymphangiogenesis==
*'''2007''' {{PMID|17878481}} -- "Role of lymphangiogenesis in cancer." (Sundar SS, J Clin Oncol. 2007 Sep 20;25(27):4298-307.)
**Review
bbn7hsnkeq1q6khtlxcb949bsbbymhg
Radiation Oncology/Radiobiology/Cell Cycle
0
197383
4675977
1725544
2026-10-14T05:59:54Z
Jcb
90773
4675977
wikitext
text/x-wiki
{{Radiation Oncology:TOC}}
<big>'''Cell Cycle'''</big>
==Overview==
*Decision to proliferate and enter cell cycle highly regulated process
*Binding of extrinsic growth factors typically necessary
*[[w:MTOR|mTOR]] integrates input from growth factor receptors, cellular nutrient and energy levels, and redox status to stimulate new protein synthesis in preparation for cell cycle entry via [[w:P70-S6_Kinase_1|S6K]] to regulate translational machinery and [[w:EIF4E|eIF4E]] to regulate cyclin D
*Regulation of cell cycle through complex of cyclins with cyclin-dependent kinases (cdk)
**cdk levels constant throughout cell cycle
**cdk activity regulated by concentration of cyclins, cdk phosphorylation, and cdk inhibition
**Cyclin concentrations are cyclical
*Progression is unidirectional from G1 -> S -> G2 -> M
*Cell cycle checkpoints
**Prevent or delay progression through cell cycle when critical events have not been completed
**Provide time for DNA repair
**4 main checkpoints (please see [[Radiation_Oncology/Radiobiology/DNA_Damage_Response|DNA damage response]] for information about effect of RT on the checkpoints
***G1 (stop)
***S (slow)
***Early G2 (stop)
***Late G2/M (stop)
==G1 Phase==
*Preparation for synthesis: Is cell big enough, is environment favorable, is DNA undamaged?
*G1 checkpoint is integrated at p53. Please see [[Radiation_Oncology/Radiobiology/DNA_Damage_Response|DNA damage response]] for more information
**If there is a G1 arrest, p53 increases levels of p21, which inhibits cyclinD-cdk4/6 complex
*If there is no arrest (low p53 levels), the cyclinD-CDK4/6 complex becomes active, and phosphorylates Rb protein
*Rb protein is normally associated with E2F, but upon phosphorylation dissociates from it
*E2F is a DNA transcription factor, which triggers entry into S phase
*Cyclin D and E2F levels are promoted by myc and by eIF4E
==S Phase==
*CDK2 kinase plays a major role in maintaining the pace of S-phase; it is a transcription target of E2F
*S phase checkpoint serves to insure that there is no replication through DNA damage that could result in double strand DNA break
**S phase checkpoint is triggered by DNA damage -> ATM -> Chk2 -> CDC25A -> CDK2 phosphorylation
**If there is an S phase arrest, CDC45 fails to load onto DNA, and DNA replication halts
*If there is no arrest, CDK2 remains dephosphorylated and CDC45 begins DNA replication
*CyclinD/CDK2 also inhibits p27<sup>kip1</sup>, which promotes expression of Cyclin A and progression through S-phase
*CyclinA/CDK2 plays a key role in duplication of centromeres
==G2 Phase==
*CyclinB/CDK1 kinase is called the Maturation-Promoting Factor (MPF), and promotes entry into mitosis by phosphorylating multiple proteins. The complex also includes Cyclin A and CDC 20
*G2/M checkpoint is triggered by DNA damage -> ATR -> Chk1 -> CDC25C -> CDK1 phosphorylation
*Prior to mitosis, cyclin B is primarily located in the cytoplasm. When the cell is ready, Cyclin B is phosphorylated, which results in its accumulation in the nucleus
*At the same time, CDK1 must be dephosphorylated to trigger mitosis
*Targets of MPF complex include:
**condensins, which enable chromatin condensation
**microtubule-associated proteins involved in mitotic spindle formation
**lamins, contributing to degradation of the nuclear envelope
**histones H1 and H3
**Golgi matrix, which leads to fragmentation
**Dephosphorylation of Rb protein, prior to start G1 of the next cycle
*There are two distinct G2/M checkpoints ({{PMID|11809797}})
**A very rapid, dose-independent, ATM-dependent arrest of cells that were in G2 at the time of irradiation (and consequent failure to enter mitosis), which can be assayed using flow cytometry against phosphorylated histone H3 (a marker of mitosis)
**A slower, dose-dependent, ATM-independent accumulation in G2 of cells which were in earlier stages of the cell cycle at the time of irradiation, which can be assayed using standard propidium iodide flow cytometry
**Please see the [[Radiation_Oncology/Radiobiology/DNA_Damage_Response#Cell_Cycle_Checkpoints|cell cycle checkpoints]] for further information
==Viral cell cycle promoters==
*These block Rb, which leads to dissociation of E2F and cell entry into S phase
**SV40 T Antigen
**Adenovirus E1A
**HPV E7
==Cell cycle inhibitors==
*Block cyclins to prevent entry into next cell cycle phase. They act primarily in G1 to stop progression into S
*Kip inhibitors:
**p21<sup>WAF1/CIP1</sup> blocks cyclin D
**p27<sup>KIP1</sup> blocks cyclin D & E
**p57<sup>KIP2</sup> blocks cyclin E & A, and to lesser degree mitotic cyclin B
*INK inhibitors:
**p16<sup>Ink4a</sup>, p15<sup>Ink4b</sup>, p18<sup>Ink4c</sup>, p19<sup>Ink4d</sup>
*Structurally related, they destabilize association of cyclin D with CDK4/6
*p21 and p16 increase in senescence and contribute to G1 arrest
==Myc==
*DNA transcription factor
*Multiple actions to promote entry of cells into S phase
**Cyclin D transcription -> Rb phosphorylation -> E2F activity
**SCF gene transcription -> KIP family (p21, p27, p57) inhibitor degradation
**E2F transcription
==Ras==
*Activation of ras triggers two major pathways related to entry into cell cycle:
**Ras -> Raf -> MEK -> MAPK -> transcription of cyclin D and block of p27 inhibitor
**Ras -> PI3K -> PKB -> stabilization of cyclin D and block of p21 inhibitor
phjx2y50r4lxiud5nzbsrqaavsqc6rt
Haskell/Understanding monads/Maybe
0
209130
4676017
4012361
2026-10-14T11:09:36Z
Luciérnaga de conocimiento
3401314
4676017
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Monads|noexercises=1}}
We introduced monads using <code>Maybe</code> as an example. The <code>Maybe</code> monad represents computations which might "go wrong" by not returning a value. For reference, here are the definitions of <code>return</code> and <code>(>>=)</code> for <code>Maybe</code> as we saw in the last chapter:<ref>The definitions in the actual instance in <code>Data.Maybe</code> are written a little differently, but are fully equivalent to these.</ref>
<syntaxhighlight lang="haskell">
return :: a -> Maybe a
return x = Just x
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
(>>=) m g = case m of
Nothing -> Nothing
Just x -> g x
</syntaxhighlight>
== Safe functions ==
The <code>Maybe</code> datatype provides a way to make a safety wrapper around ''partial functions'', that is, functions which can fail to work for a range of arguments. For example, <code>head</code> and <code>tail</code> only work with non-empty lists. Another typical case, which we will explore in this section, is mathematical functions like <code>sqrt</code> and <code>log</code>; (as far as real numbers are concerned) these are only defined for non-negative arguments.
<pre>
> log 1000
6.907755278982137
> log (-1000)
''ERROR'' -- runtime error
</pre>
To avoid this crash, a "safe" implementation of log could be:
<syntaxhighlight lang="haskell">
safeLog :: (Floating a, Ord a) => a -> Maybe a
safeLog x
| x > 0 = Just (log x)
| otherwise = Nothing
</syntaxhighlight>
<pre>
> safeLog 1000
Just 6.907755278982137
> safeLog -1000
Nothing
</pre>
We could write similar "safe functions" for all functions with limited domains such as division, square-root, and inverse trigonometric functions (<code>safeDiv</code>, <code>safeSqrt</code>, <code>safeArcSin</code>, etc. all of which would have the same ''type'' as <code>safeLog</code> but definitions specific to their constraints)
If we wanted to combine these monadic functions, the cleanest approach is with monadic composition (which was mentioned briefly near the end of [[Haskell/Understanding monads#Associativity of bind|the last chapter]]) and point-free style:
<syntaxhighlight lang="haskell">
safeLogSqrt = safeLog <=< safeSqrt
</syntaxhighlight>
Written in this way, <code>safeLogSqrt</code> resembles a lot its unsafe, non-monadic counterpart:
<syntaxhighlight lang="haskell">
unsafeLogSqrt = log . sqrt
</syntaxhighlight>
== Lookup tables ==
A lookup table relates ''keys'' to ''values''. You ''look up'' a value by knowing its key and using the lookup table. For example, you might have a phone book application with a lookup table where contact names are keys to corresponding phone numbers. An elementary way of implementing lookup tables in Haskell is to use a list of pairs: <code>[(a, b)]</code>. Here <code>a</code> is the type of the keys, and <code>b</code> the type of the values.<ref>Check [[Haskell/Hierarchical libraries/Maps|the chapter about maps]] in Haskell in Practice for a different, and potentially more useful, implementation.</ref> Here's how the phone book lookup table might look:
<pre>
phonebook :: [(String, String)]
phonebook = [ ("Bob", "01788 665242"),
("Fred", "01624 556442"),
("Alice", "01889 985333"),
("Jane", "01732 187565") ]
</pre>
The most common thing you might do with a lookup table is look up values. Everything is fine if we try to look up "Bob", "Fred", "Alice" or "Jane" in our phone book, but what if we were to look up "Zoe"? Zoe isn't in our phone book, so the lookup would fail. Hence, the Haskell function to look up a value from the table is a <code>Maybe</code> computation (it is available from Prelude):
<syntaxhighlight lang="haskell">
lookup :: Eq a => a -- a key
-> [(a, b)] -- the lookup table to use
-> Maybe b -- the result of the lookup
</syntaxhighlight>
Let us explore some of the results from lookup:
<pre>
Prelude> lookup "Bob" phonebook
Just "01788 665242"
Prelude> lookup "Jane" phonebook
Just "01732 187565"
Prelude> lookup "Zoe" phonebook
Nothing
</pre>
Now let's expand this into using the full power of the monadic interface. Say, we're now working for the government, and once we have a phone number from our contact, we want to look up this phone number in a big, government-sized lookup table to find out the registration number of their car. This, of course, will be another <code>Maybe</code>-computation. But if the person we're looking for isn't in our phone book, we certainly won't be able to look up their registration number in the governmental database. What we need is a function that will take the results from the first computation and put it into the second lookup ''only'' if we get a successful value in the first lookup. Of course, our final result should be <code>Nothing</code> if we get <code>Nothing</code> from either of the lookups.
<syntaxhighlight lang="haskell">
getRegistrationNumber :: String -- their name
-> Maybe String -- their registration number
getRegistrationNumber name =
lookup name phonebook >>=
(\number -> lookup number governmentDatabase)
</syntaxhighlight>
If we then wanted to use the result from the governmental database lookup in a third lookup (say we want to look up their registration number to see if they owe any car tax), then we could extend our <code>getRegistrationNumber</code> function:
<syntaxhighlight lang="haskell">
getTaxOwed :: String -- their name
-> Maybe Double -- the amount of tax they owe
getTaxOwed name =
lookup name phonebook >>=
(\number -> lookup number governmentDatabase) >>=
(\registration -> lookup registration taxDatabase)
</syntaxhighlight>
Or, using the <code>do</code>-block style:
<syntaxhighlight lang="haskell">
getTaxOwed name = do
number <- lookup name phonebook
registration <- lookup number governmentDatabase
lookup registration taxDatabase
</syntaxhighlight>
Let's just pause here and think about what would happen if we got a <code>Nothing</code> anywhere. By definition, when the first argument to <code>>>=</code> is <code>Nothing</code>, it just returns <code>Nothing</code> while ignoring whatever function it is given. Thus, a <code>Nothing</code> at ''any stage'' in the large computation will result in a <code>Nothing</code> overall, regardless of the other functions. After the first <code>Nothing</code> hits, all <code>>>=</code>s will just pass it to each other, skipping the other function arguments. The technical description says that the structure of the <code>Maybe</code> monad ''propagates failures''.
== Extracting values ==
If we have a <code>Just</code> value, we can extract the underlying value it contains through pattern matching.
<syntaxhighlight lang="haskell">
zeroAsDefault :: Maybe Int -> Int
zeroAsDefault mx = case mx of
Nothing -> 0
Just x -> x
</syntaxhighlight>
The usage pattern of replacing <code>Nothing</code> with a default value is captured by the <code>fromMaybe</code> function in <code>Data.Maybe</code>.
<syntaxhighlight lang="haskell">
zeroAsDefault :: Maybe Int -> Int
zeroAsDefault mx = fromMaybe 0 mx
</syntaxhighlight>
The <code>maybe</code> Prelude function allows us to do it in a more general way, by supplying a function to modify the extracted value.
<syntaxhighlight lang="haskell">
displayResult :: Maybe Int -> String
displayResult mx = maybe "There was no result" (("The result was " ++) . show) mx
</syntaxhighlight>
<pre>
Prelude> :t maybe
maybe :: b -> (a -> b) -> Maybe a -> b
Prelude> displayResult (Just 10)
"The result was 10"
Prelude> displayResult Nothing
"There was no result"
</pre>
The possibility of, whenever possible, extracting the underlying values makes sense for <code>Maybe</code>: it amounts to either extracting a result from a successful computation or recovering from a failed computation by supplying a default. It is worth noting, though, that what we have just seen doesn't actually involve the fact of <code>Maybe</code> being a monad. <code>return</code> and <code>(>>=)</code>, on their own, do not enable us to extract the underlying value from a monadic computation, and so it is perfectly possible to make a "no-exit" monad, from which it is never possible to extract values. The most obvious example of that is the <code>IO</code> monad.
== Maybe and safety ==
We have seen how <code>Maybe</code> can make code safer by providing a graceful way to deal with failure that does not involve runtime errors. Does that mean we should always use <code>Maybe</code> for ''everything''? Not really.
When you write a function, you are able to tell whether it might fail to produce a result during normal operation of the program,<ref>With "normal operation" we mean to exclude failure caused by uncontrollable circumstances in the real world, such as memory exhaustion or a dog chewing the printer cable.</ref> either because the functions you use might fail (as in the examples in this chapter) or because you know some of the argument or intermediate result values do not make sense (for instance, imagine a calculation that is only meaningful if its argument is less than 10). If that is the case, by all means use <code>Maybe</code> to signal failure; it is far better than returning an arbitrary default value or throwing an error.
Now, adding <code>Maybe</code> to a result type without a reason would only make the code more confusing and no safer. The type signature of a function with unnecessary <code>Maybe</code> would tell users of the code that the function could fail when it actually can't. Of course, that is not as bad a lie as the opposite one (that is, claiming that a function will not fail when it actually can), but we really want honest code in ''all'' cases. Furthermore, using <code>Maybe</code> forces us to propagate failure (with <code>fmap</code> or monadic code) and eventually handle the failure cases (using pattern matching, the <code>maybe</code> function, or <code>fromMaybe</code> from <code>Data.Maybe</code>). If the function cannot actually fail, coding for failure is an unnecessary complication.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Monads|noexercises=1}}
{{BookCat}}
skyph2igfks9wawb4z351d6yfw211rk
Haskell/Understanding monads/IO
0
209132
4676020
4037255
2026-10-14T11:13:19Z
Luciérnaga de conocimiento
3401314
4676020
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Monads}}
Two defining features of Haskell are ''pure functions'' and ''lazy evaluation''. All Haskell functions are pure, which means that, when given the same arguments, they return the same results. Lazy evaluation means that, by default, Haskell values are only evaluated when some part of the program requires them – perhaps never, if they are never used – and repeated evaluation of the same value is avoided wherever possible.
Pure functions and lazy evaluation bring forth a number of advantages. In particular, pure functions are reliable and predictable; they ease debugging and validation. Test cases can also be set up easily since we can be sure that nothing other than the arguments will influence a function's result. Being entirely contained within the program, the Haskell compiler can evaluate functions thoroughly in order to optimize the compiled code. However, input and output operations, which involve interaction with the world outside the confines of the program, can't be expressed through pure functions. Furthermore, in most cases I/O can't be done lazily. Since lazy computations are only performed when their values become necessary, unfettered lazy I/O would make the order of execution of the real world effects unpredictable.
There is no way to ignore this issue, as any useful program needs to do I/O, even if it is only to display a result. That being so, how do we manage actions like opening a network connection, writing a file, reading input from the outside world, or anything else that goes beyond calculating a value? The main insight is: ''actions are not functions''. The <code>IO</code> type constructor provides a way to represent actions as Haskell values, so that we can manipulate them with pure functions. In the [[Haskell/Applicative prologue|Prologue]] chapter, we anticipated some of the key features of this solution. Now that we also know that <code>IO</code> is a monad, we can wrap up the discussion we started there.
== Combining functions and I/O actions ==
Let's combine functions with I/O to create a full program that will:
# Ask the user to insert a string
# Read their string
# Use <code>fmap</code> to apply a function <code>shout</code> that capitalizes all the letters from the string
# Write the resulting string
<syntaxhighlight lang=haskell>
module Main where
import Data.Char (toUpper)
import Control.Monad
main = putStrLn "Write your string: " >> fmap shout getLine >>= putStrLn
shout = map toUpper
</syntaxhighlight>
We have a full-blown program, but we didn't include any type definitions. Which parts are functions and which are IO actions or other values? We can load our program in GHCi and check the types:
<syntaxhighlight lang=haskell>
main :: IO ()
putStrLn :: String -> IO ()
"Write your string: " :: [Char]
(>>) :: Monad m => m a -> m b -> m b
fmap :: Functor m => (a -> b) -> m a -> m b
shout :: [Char] -> [Char]
getLine :: IO String
(>>=) :: Monad m => m a -> (a -> m b) -> m b
</syntaxhighlight>
Whew, that is a lot of information there. We've seen all of this before, but let's review.
<code>main</code> is <code>IO ()</code>. That's not a function. Functions are of types <code>a -> b</code>. Our entire program is an IO action.
<code>putStrLn</code> is a function, but it results in an IO action. The "Write your string: " text is a <code>String</code> (remember, that's just a synonym for <code>[Char]</code>). It is used as an argument for <code>putStrLn</code> and is incorporated into the IO action that results. So, <code>putStrLn</code> is a function, but <code>putStrLn x</code> evaluates to an IO action. The <code>()</code> part of the IO type (called a unit type) indicates that nothing is available to be passed on to any later functions or actions.
That last part is key. We sometimes say informally that an IO action "returns" something; however, taking that too literally leads to confusion. It is clear what we mean when we talk about ''functions'' returning results, but IO actions are not functions. Let's skip down to <code>getLine</code> — an IO action that ''does'' provide a value. <code>getLine</code> is not a function that returns a <code>String</code> because ''<code>getLine</code> isn't a function''. Rather, <code>getLine</code> is an IO action which, when evaluated, will materialize a <code>String</code>, which can then be passed to later functions through, for instance, <code>fmap</code> and <code>(>>=)</code>.
When we use <code>getLine</code> to get a <code>String</code>, the value is monadic because it is wrapped in <code>IO</code> functor (which happens to be a monad). We cannot pass the value directly to a function that takes plain (non-monadic, or non-functorial) values. <code>fmap</code> does the work of taking a non-monadic function while passing in and returning monadic values.
As we've seen already, <code>(>>=)</code> does the work of passing a monadic value into a function that takes a non-monadic value and returns a monadic value. It may seem inefficient for <code>fmap</code> to take the non-monadic result of its given function and return a monadic value only for <code>(>>=)</code> to then pass the underlying non-monadic value to the next function. It is precisely this sort of chaining, however, that creates the reliable sequencing that make monads so effective at integrating pure functions with IO actions.
=== ''do'' notation review ===
Given the emphasis on sequencing, the [[Haskell/do notation|<code>do</code> notation]] can be especially appealing with the <code>IO</code> monad. Our program
<syntaxhighlight lang="haskell">
putStrLn "Write your string: " >> fmap shout getLine >>= putStrLn
</syntaxhighlight>
could be written as:
<syntaxhighlight lang="haskell">
do putStrLn "Write your string: "
string <- getLine
putStrLn (shout string)
</syntaxhighlight>
== The universe as part of our program ==
One way of viewing the <code>IO</code> monad is to consider <code>IO a</code> as a computation which provides a value of type <code>a</code> while changing ''the state of the world'' by doing input and output. Obviously, you cannot literally set the state of the world; it is hidden from you, as the <code>IO</code> functor is abstract (that is, you cannot dig into it to see the underlying values, a situation unlike what we have seen [[Haskell/Understanding monads/Maybe#Extracting values|in the case of <code>Maybe</code>]]).
Understand that this idea of the universe as an object affected and affecting Haskell values through <code>IO</code> is only a metaphor; a loose interpretation at best. The more mundane fact is that <code>IO</code> simply brings some very base-level operations into the Haskell language.<ref>The technical term is "primitive", as in primitive operations.</ref> Remember that Haskell is an abstraction, and that Haskell programs must be compiled to machine code in order to actually run. The actual workings of IO happen at a lower level of abstraction, and are wired into the very definition of the Haskell language.<ref>The same can be said about all higher-level programming languages, of course. Incidentally, Haskell's IO operations can actually be extended via the ''Foreign Function Interface'' (FFI) which can make calls to C libraries. As C can use inline assembly code, Haskell can indirectly engage with anything a computer can do. Still, Haskell functions manipulate such outside operations only ''indirectly'' as values in <code>IO</code> functors.</ref>
== Pure and impure ==
The adjectives "pure" and "impure" often crop up while talking about I/O in Haskell. To clarify what they mean, we will revisit the discussion about referential transparency from the [[Haskell/Applicative prologue#Referential transparency|Prologue chapter]]. Consider the following snippet:
<syntaxhighlight lang="haskell">
speakTo :: (String -> String) -> IO String
speakTo fSentence = fmap fSentence getLine
-- Usage example.
sayHello :: IO String
sayHello = speakTo (\name -> "Hello, " ++ name ++ "!")
</syntaxhighlight>
In most other programming languages, which do not have separate types for I/O actions, <code>speakTo</code> would have a type akin to:
<syntaxhighlight lang="haskell">
speakTo :: (String -> String) -> String
</syntaxhighlight>
With such a type, however, <code>speakTo</code> would not be a function at all! Functions produce the same results when given the same arguments; the <code>String</code> delivered by <code>speakTo</code>, however, also depends on whatever is typed at the terminal prompt. In Haskell, we avoid that pitfall by returning an <code>IO String</code>, which is not a <code>String</code> but a promise that ''some'' <code>String</code> will be delivered by carrying out certain instructions involving I/O (in this case, the I/O consists of getting a line of input from the terminal). Though the <code>String</code> can be different each time <code>speakTo</code> is evaluated, the I/O instructions are always the same.
When we say Haskell is a purely functional language, we mean that all of its functions are ''really'' functions – or, in other words, that Haskell expressions are always referentially transparent. If <code>speakTo</code> had the problematic type we mentioned above, referential transparency would be violated: <code>sayHello</code> would be a <code>String</code>, and yet replacing it by any specific string would break the program.
In spite of Haskell being purely functional, <code>IO</code> actions can be said to be ''impure'' because their impacts on the outside world are ''side effects'' (as opposed to the regular effects that are entirely contained within Haskell). Programming languages that lack purity may have side-effects in many other places connected with various calculations. Purely functional languages, however, assure that ''even expressions with impure values are referentially transparent''. That means we can talk about, reason about and handle impurity in a purely functional way, using purely functional machinery such as functors and monads. While <code>IO</code> actions are impure, all of the Haskell functions that manipulate them remain pure.
Functional purity, coupled with the fact that I/O shows up in types, benefits Haskell programmers in various ways. The guarantees about referential transparency increase a lot the potential for compiler optimizations. <code>IO</code> values being distinguishable through types alone make it possible to immediately tell where we are engaging with side effects or opaque values. As <code>IO</code> itself is just another functor, we maintain to the fullest extent the predictability and ease of reasoning associated with pure functions.
== Functional and imperative ==
When we [[Haskell/Understanding monads#Notions of computation|introduced monads]], we said that a monadic expression can be interpreted as a statement of an imperative language. That interpretation is immediately compelling for <code>IO</code>, as the language around IO actions looks a lot like a conventional imperative language. It must be clear, however, that we are talking about an ''interpretation''. We are not saying that monads or <code>do</code> notation turn Haskell into an imperative language. The point is merely that you can view and understand monadic code in terms of imperative statements. The semantics may be imperative, but the implementation of monads and <code>(>>=)</code> is still purely functional. To make this distinction clear, let's look at a little illustration:
<syntaxhighlight lang="c">
int x;
scanf("%d", &x);
printf("%d\n", x);
</syntaxhighlight>
This is a snippet of C, a typical imperative language. In it, we declare a variable <code>x</code>, read its value from user input with <code>scanf</code> and then print it with <code>printf</code>. We can, within an <code>IO</code> do block, write a Haskell snippet that performs the same function and looks quite similar:
<syntaxhighlight lang="haskell">
x <- readLn
print x
</syntaxhighlight>
Semantically, the snippets are nearly equivalent.<ref>One difference is that <code>x</code> is a mutable variable in C, and so it is possible to declare it in one statement and set its value in the next; Haskell never allows such mutability. If we wanted to imitate the C code even more closely, we could have used an <code>IORef</code>, which is a cell that contains a value which can be destructively updated. For obvious reasons, <code>IORef</code>s can only be used within the <code>IO</code> monad.</ref> In the C code, however, the statements directly correspond to instructions to be carried out by the program. The Haskell snippet, on the other hand, is desugared to:
<syntaxhighlight lang="haskell">
readLn >>= \x -> print x
</syntaxhighlight>
The desugared version has no statements, only functions being applied. We tell the program the order of the operations indirectly as a simple consequence of ''data dependencies'': when we chain monadic computations with <code>(>>=)</code>, we get the later results by applying functions to the results of the earlier ones. It just happens that, for instance, evaluating <code>print x</code> leads to a string being printed in the terminal.
When using monads, Haskell allows us to write code with imperative semantics while keeping the advantages of functional programming.
== I/O in the libraries ==
So far the only I/O primitives we have used were <code>putStrLn</code> and <code>getLine</code> and small variations thereof. The standard libraries, however, offer many other useful functions and actions involving <code>IO</code>. We present some of the most important ones in the [[Haskell/Libraries/IO|IO chapter in Haskell in Practice]], including the basic functionality needed for reading from and writing to files.
== Monadic control structures ==
Given that monads allow us to express sequential execution of actions in a wholly general way, could we use them to implement common iterative patterns, such as loops? In this section, we will present a few of the functions from the standard libraries which allow us to do precisely that. While the examples are presented here applied to <code>IO</code>, keep in mind that the following ideas apply to ''every'' monad.
Remember, there is nothing magical about monadic values; we can manipulate them just like any other values in Haskell. Knowing that, we might think to try the following function to get five lines of user input:
<syntaxhighlight lang="haskell">
fiveGetLines = replicate 5 getLine
</syntaxhighlight>
That won't do, however (try it in GHCi!). The problem is that <code>replicate</code> produces, in this case, a list of actions, while we want an action which returns a list (that is, <code>IO [String]</code> rather than <code>[IO String]</code>). What we need is a ''fold'' to run down the list of actions, executing them and combining the results into a single list. As it happens, there is a Prelude function which does that: <code>sequence</code>.
<syntaxhighlight lang="haskell">
sequence :: (Monad m) => [m a] -> m [a]
</syntaxhighlight>
And so, we get the desired action with:
<syntaxhighlight lang="haskell">
fiveGetLines = sequence $ replicate 5 getLine
</syntaxhighlight>
<code>replicate</code> and <code>sequence</code> form an appealing combination, so {{Haskell/Lib|Control|Monad}} offers a <code>replicateM</code> function for repeating an action an arbitrary number of times. <code>Control.Monad</code> provides a number of other convenience functions in the same spirit - monadic zips, folds, and so forth.
<syntaxhighlight lang="haskell">
fiveGetLinesAlt = replicateM 5 getLine
</syntaxhighlight>
A particularly important combination is <code>map</code> and <code>sequence</code>. Together, they allow us to make actions from a list of values, run them sequentially, and collect the results. <code>mapM</code>, a Prelude function, captures this pattern:
<syntaxhighlight lang="haskell">
mapM :: (Monad m) => (a -> m b) -> [a] -> m [b]
</syntaxhighlight>
We also have variants of the above functions with a trailing underscore in the name, such as <code>sequence_</code>, <code>mapM_</code> and <code>replicateM_</code>. These discard any final values and so are appropriate when you are only interested in performing actions. Compared with their underscore-less counterparts, these functions are like the distinction between <code>(>>)</code> and <code>(>>=)</code>. <code>mapM_</code> for instance has the following type:
<syntaxhighlight lang="haskell">
mapM_ :: (Monad m) => (a -> m b) -> [a] -> m ()
</syntaxhighlight>
Finally, it is worth mentioning that <code>Control.Monad</code> also provides <code>forM</code> and <code>forM_</code>, which are flipped versions of <code>mapM</code> and <code>mapM_</code>. <code>forM_</code> happens to be the idiomatic Haskell counterpart to the imperative for-each loop; and the type signature suggests that neatly:
<syntaxhighlight lang="haskell">
forM_ :: (Monad m) => [a] -> (a -> m b) -> m ()
</syntaxhighlight>
{{Exercises|1=
# Using the monadic functions we have just introduced, write a function which prints an arbitrary list of values.
# Generalize the [[Haskell/Understanding_monads/List#Bunny_invasion|bunny invasion example]] in the list monad chapter for an arbitrary number of generations.
# What is the expected behavior of <code>sequence</code> for the <code>Maybe</code> monad?
}}
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Monads}}
{{BookCat}}
74gk1cjb0ym6p8qkuazuatmi52z5ey6
Haskell/Understanding monads/State
0
209133
4676021
4462742
2026-10-14T11:13:48Z
Luciérnaga de conocimiento
3401314
4676021
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Monads}}
If you have programmed in any other language before, you likely wrote some functions that "kept state". For those new to the concept, a ''state'' is one or more variables that are required to perform some computation but are not among the arguments of the relevant function. Object-oriented languages like C++ make extensive use of state variables (in the form of member variables inside classes and objects). Procedural languages like C on the other hand typically use global variables declared outside the current scope or static variables in the functions to keep track of state.
In Haskell, however, such techniques are not as straightforward to apply. Doing so will require mutable variables which would mean that functions will have hidden dependencies, which is at odds with Haskell's functional ''purity''. Fortunately, often it is possible to keep track of state in a functionally pure way. We do so by passing the state information from one function to the next, thus making the hidden dependencies explicit.
The <code>State</code> type is designed to simplify this process of threading state through functions. In this chapter, we will see how it can assist us in some typical problems involving state: modelling a state machine and generating pseudo-random numbers.
== State Machine ==
We will model a simple [[:wikipedia:Finite-state machine#Example:_coin-operated_turnstile|finite-state machine based on a coin-operated turnstile]]. Our model will be enhanced so that, in any state, it will create an output (in addition to a state transition) for each input<ref>Hence our finite-state machine is a [[:wikipedia:Finite-state machine#Transducers|transducer]].</ref>.
=== Turnstile Example ===
The finite-state model of our turnstile is shown in this state-transition diagram:
[[File:Turnstile finite-state machine with actions.svg|none|400px]]
The turnstile has two ''states'': '''Locked''' and '''Unlocked'''. (It starts in a '''Locked''' state). There are two types of ''input'': '''Coin''' (corresponding to someone putting a coin in the slot) and '''Push''' (corresponding to someone pushing the arm). Each input causes an ''output'' ('''Thank''', '''Open''' or '''Tut''') and a transition to a (new, or maybe the same) state. If someone puts a coin in when the turnstile is locked, they are thanked (yes, it can talk!) and the turnstile becomes unlocked. If they add more coins, they are thanked more but get no benefit (the turnstile simply remains unlocked with no memory of how many additional coins have been added). If someone pushes the arm when the turnstile is unlocked, the arm will open to let them through, then become locked to prevent anyone else going through. If someone pushes the arm when the turnstile is locked, it will politely tut at them but not let them through and remain locked.
=== Basic Model in Haskell ===
We will represent the states and outputs as follows:
<syntaxhighlight lang="haskell">
data TurnstileState = Locked | Unlocked
deriving (Eq, Show)
data TurnstileOutput = Thank | Open | Tut
deriving (Eq, Show)
</syntaxhighlight>
But what about the inputs? We can model them as functions. Here's a first attempt:
<syntaxhighlight lang="haskell">
coin, push :: TurnstileState -> TurnstileOutput
coin _ = Thank
push Unlocked = Open
push Locked = Tut
</syntaxhighlight>
These correctly return the output for each input in any state, but don't give any indication of the new state. (In an imperative program, these "functions" might also update a variable to indicate the new state, but that is not an option in Haskell, nor, we claim, desirable). The answer is easy and obvious: return the new state along with the output:
<syntaxhighlight lang="haskell">
coin, push :: TurnstileState -> (TurnstileOutput, TurnstileState)
coin _ = (Thank, Unlocked)
push Locked = (Tut , Locked)
push Unlocked = (Open, Locked)
</syntaxhighlight>
=== Sequencing Steps ===
How can we use this? One way is to list the set of outputs resulting from a sequence of inputs:
<syntaxhighlight lang="haskell">
monday :: TurnstileState -> ([TurnstileOutput], TurnstileState)
monday s0 =
let (a1, s1) = coin s0
(a2, s2) = push s1
(a3, s3) = push s2
(a4, s4) = coin s3
(a5, s5) = push s4
in ([a1, a2, a3, a4, a5], s5)
GHCi> monday Locked
([Thank,Open,Tut,Thank,Open],Locked)
</syntaxhighlight>
Note that, like <code>coin</code> and <code>push</code>, this <code>monday</code> function takes an initial state as a parameter and returns the final state alongside the list of outputs.
{{Exercises|1=
#Implement functions <code>regularPerson, distractedPerson, hastyPerson :: TurnstileState -> ([TurnstileOutput], TurnstileState)</code>. Given a <code>TurnstileState</code>, each should return the outputs (and updated state) of a different type of person. A <code>regularPerson</code> always inserts a coin then pushes the arm. A <code>distractedPerson</code> always inserts a coin then wanders off without going through. A <code>hastyPerson</code> first pushes the arm without having inserted a coin. If it opens (for example, they're following a <code>distractedPerson</code>) they go through. If not (for example they're following a <code>regularPerson</code>) they'll then insert a coin and push the arm to go through.
#Use these functions to implement <code>tuesday :: TurnstileState -> ([TurnstileOutput], TurnstileState)</code>, returning the outputs from this sequence of visitors: <code>regularPerson</code>, <code>hastyPerson</code>, <code>distractedPerson</code>, <code>hastyPerson</code>.
#Implement <code>luckyPair :: Bool -> TurnstileState -> (Bool, TurnstileState)</code> representing two people attempting to use the turnstile in succession. The first is either a <code>regularPerson</code> or a <code>distractedPerson</code> (depending on the <code>Bool</code> argument). The second person will simply push the arm without inserting a coin and give up if they don't get through. The <code>Bool</code> result should indicate whether the second person made it through.
}}
From the examples it can be seen that:
* the state (of some fixed type) is always passed from step to step, and (usually) included in the input to and output from a function: having the state as input to and output from functions allows us to chain them together as steps in bigger functions, in the same way the steps within these smaller functions are chained together;
* the (non-state) output of a step may or may not be used in deciding subsequent steps: <code>hastyPerson</code> uses the output of the first <code>push</code> to determine whether they need to insert a coin, but <code>regularPerson</code> always does the same two steps regardless of their outputs;
* the (non-state) output of a step may or may not be used in the final (non-state) return value from a function: the return value from <code>regularPerson</code> uses the output from each step, but the return value from <code>luckyPair</code> doesn't depend on the output from the first step;
* a function may take parameters in addition to the initial state: <code>luckyPair</code> takes a <code>Bool</code> parameter;
* the types of the (non-state) return values can be different for different functions: <code>coin</code> returns <code>TurnstileOutput</code>, <code>monday</code> returns <code>[TurnstileOutput]</code> and <code>luckyPair</code> returns <code>Bool</code>.
But all of this code is cumbersome, tedious to write and error prone. It would be ideal if we could automate the extraction of the second member of the tuple (i.e. the new state) and feed it to the next step, whilst also allowing the function to use the (non-state) values to make decisions about further steps and/or include in the (non-state) result(s). This is where <code>State</code> comes into the picture.
== Introducing <code>State</code> ==
The Haskell type <code>State</code> describes ''functions'' that consume a state and produce both a result and an updated state, which are given back in a tuple.
The state function is wrapped by a data type definition which comes along with a <code>runState</code> accessor so that pattern matching becomes unnecessary. For our current purposes, the <code>State</code> type might be defined as:
<syntaxhighlight lang="haskell">
newtype State s a = State { runState :: s -> (a, s) }
</syntaxhighlight>
Here, <code>s</code> is the type of the state, and <code>a</code> the type of the produced result. Calling the type <code>State</code> is arguably a bit of a misnomer because the wrapped value is not the state itself but a ''state processor''.
=== newtype ===
Note that we defined the data type with the <code>newtype</code> keyword, rather than the usual <code>data</code>. <code>newtype</code> can be used only for types with just one constructor and just one field. It ensures that the trivial wrapping and unwrapping of the single field is eliminated by the compiler. For that reason, simple wrapper types such as <code>State</code> are usually defined with <code>newtype</code>. Would defining a synonym with <code>type</code> be enough in such cases? Not really, because <code>type</code> does not allow us to define instances for the new data type, which is what we are about to do...
=== Where did the <code>State</code> constructor go? ===
In the wild, the <code>State</code> type is provided by <code>Control.Monad.Trans.State</code> in <code>transformers</code> (and is also reexported by <code>Control.Monad.State</code> in <code>mtl</code>). When you use it, you will quickly notice there is no <code>State</code> constructor available. The <code>transformers</code> package implements the <code>State</code> type in a different way. The differences do not affect how we use or understand <code>State</code>, except that instead of a <code>State</code> constructor, <code>Control.Monad.Trans.State</code> exports a <code>state</code> function,
<syntaxhighlight lang="haskell">
state :: (s -> (a, s)) -> State s a
</syntaxhighlight>
which does the same job. As for ''why'' the actual implementation is not the obvious one we presented above, we will get back to that a few chapters down the road.
{{body note|In all of the code below, <code>State</code> is a (parameterised) ''type'' (that we will make instances of <code>Monad</code>, etc), and <code>state</code> is a ''function'' that takes an argument (of type <code>s -> (a, s)</code>) and returns a value of type <code>State s a</code>. If you are creating your own version of <code>State</code> by following this text as a tutorial (which I recommend), please add this code after the <code>newtype</code> declaration:
<syntaxhighlight lang="haskell">
state :: (s -> (a, s)) -> State s a
state = State
</syntaxhighlight>
This will ensure the code below is valid whether you use your own <code>State</code> implementation or the one provided.
}}
=== Instantiating the Monad ===
So far, all we have done was to wrap a function type and give it a name. There is another ingredient, however: for every type <code>s</code>, <code>State s</code> ''can be made a <code>Monad</code> instance'', giving us very handy ways of using it.
To define a <code>Monad</code> instance, there must also be instances for <code>Functor</code> and <code>Applicative</code>. [[Haskell/Understanding monads#LiftM and Friends|As we explained previously]], these superclass instances can be derived as follows from the <code>Monad</code> instance that we are about to define in more detail.
<syntaxhighlight lang="haskell">
import Control.Monad -- you will need to put this towards the top of the file
instance Functor (State s) where
fmap = liftM
instance Applicative (State s) where
pure = return
(<*>) = ap
</syntaxhighlight>
In a [[#State_is_also_a_Functor_and_an_Applicative|later section]] we will discuss the implications of <code>State</code> also being a <code>Functor</code> and an <code>Applicative</code> in more detail. You will also get a chance to reimplement the above explicitly based on their behaviour, without simply deferring to the <code>Monad</code> instance.
So let's define this instance.
<syntaxhighlight lang="haskell">
instance Monad (State s) where
</syntaxhighlight>
Note the instance is <code>State s</code>, and not just <code>State</code> on its own; <code>State</code> can't be made an instance of <code>Monad</code>, as it takes two type parameters, rather than one.
That means there are actually ''many'' different <code>State</code> monads, one for each possible type of state - <code>State String</code>, <code>State Int</code>, <code>State SomeLargeDataStructure</code>, and so forth. However, we only need to write one implementation of <code>return</code> and <code>(>>=)</code>; the methods will be able to deal with all choices of <code>s</code>.
The <code>return</code> function is implemented as:
<syntaxhighlight lang="haskell">
return :: a -> State s a
return x = state ( \ s -> (x, s) )
</syntaxhighlight>
Giving a value (<code>x</code>) to <code>return</code> produces a function which takes a state (<code>s</code>) and returns it unchanged, together with the value we want to be returned. As a finishing step, the function is wrapped up with the <code>state</code> function.
{{Exercises|1=
#Try to write the bind method before looking at the solution below.
}}
As for binding, it can be defined like this:
<syntaxhighlight lang="haskell">
(>>=) :: State s a -> (a -> State s b) -> State s b
p >>= k = q where
p' = runState p -- p' :: s -> (a, s)
k' = runState . k -- k' :: a -> s -> (b, s)
q' s0 = (y, s2) where -- q' :: s -> (b, s)
(x, s1) = p' s0 -- (x, s1) :: (a, s)
(y, s2) = k' x s1 -- (y, s2) :: (b, s)
q = state q'
</syntaxhighlight>
We wrote the definition above in a quite verbose way, to make the steps involved easier to pinpoint. A more compact way of writing it would be:
<syntaxhighlight lang="haskell">
p >>= k = state $ \ s0 ->
let (x, s1) = runState p s0 -- Running the first processor on s0.
in runState (k x) s1 -- Running the second processor on s1.
</syntaxhighlight>
<code>(>>=)</code> is given a state processor (<code>p</code>) and a function (<code>k</code>) that is used to create another processor from the result of the first one. The two processors are combined into a function that takes the ''initial'' state (<code>s</code>) and returns the ''second'' result and the ''third'' state (i.e. the output of the second processor). Overall, <code>(>>=)</code> here allows us to run two state processors in sequence, while allowing the result of the first stage to influence what happens in the second one.
[[File:State Monad Bind.svg|thumb|Schematic representation of how bind creates a new state processor (<code>pAB</code>) from a state processor (<code>pA</code>) and a processor-making function (<code>f</code>). <code>s1</code>, <code>s2</code> and <code>s3</code> are states. <code>v1</code> and <code>v2</code> are values. <code>pA</code>, <code>pB</code> and <code>pAB</code> are state processors. The wrapping and unwrapping by <code>State</code>/<code>runState</code> is implicit.]]
One detail in the implementation is how <code>runState</code> is used to undo the <code>State</code> wrapping, so that we can reach the function that will be applied to the states. The type of <code>runState p</code>, for instance, is <code>s -> (a, s)</code>.
=== Understanding the Bind Operator ===
Another way to understand this derivation of the bind operator <code>>>=</code> is to consider once more the explicit but cumbersome way to simulate a stateful function of type <code>a -> b</code> by using functions of type <code>(a, s) -> (b, s) </code>, or, said another way: <code>a -> s -> (b,s) = a -> (s -> (b,s))</code>. These classes of functions pass the state on from function to function. Note that this last signature already suggests the right-hand side type in a bind operation where the abstract type is <code>S b = (s -> (b, s))</code>.
Now that we have seen how the types seem to suggest the monadic signatures, let's consider a much more concrete question: Given two functions <code>f :: s -> (a, s)</code> and <code>g :: a -> s -> (b, s)</code>, how do we chain them to produce a new function that passes on the intermediate state?
This question does not require thinking about monads: one option is to simply use function composition. It helps our exposition if we just write it down explicitly as a lambda expression:
<syntaxhighlight lang="haskell">
compose :: (s -> (a,s)) -> {- first function -}
(a -> (s -> (b,s))) -> {- second function, note type is similar to (a,s) -> (b,s) -}
s -> (b,s) {- composed function -}
compose f g = \s0 -> let (a1, s1) = f s0 in (g a1) s1
{-This lambda expression threads both intermediate results produced by f into those required by g -}
</syntaxhighlight>
Now, if in addition to chaining the input functions, we find that the functions of signature <code>s -> (a,s)</code> were all wrapped in an abstract datatype <code>Wrapped a</code>, and that therefore we need to call some other provided functions<code>wrap :: (s -> (a,s)) -> Wrapped a</code>, and <code>unwrap :: Wrapped a -> (s -> (a,s))</code> in order to get to the inner function, then the code changes slightly:
<syntaxhighlight lang="haskell">
{- what happens if the type s -> (a,s) is wrapped and this new type is called Wrapped a -}
composeWrapped :: Wrapped a -> (a -> Wrapped b) -> Wrapped b
composeWrapped wrappedf g = wrap (\s0 -> let (a1,s1) = (unwrap wrappedf) s0 in (unwrap (g a1)) s1)
{- or, reusing compose -}
composeWrapped wrappedf g = wrap (compose (unwrap wrappedf) (fmap unwrap g))
</syntaxhighlight>
This code is the implementation of <code>(>>=)</code> shown above, with <code>wrap = state</code> and <code>unwrap = runState</code>, so we can now see how the definition of bind given earlier is the standard function composition for this special kind of stateful function.
This explanation does not address yet where the original functions <code>Wrapped a</code> and <code>a -> Wrapped b</code> come from in the first place, but they do explain what you can do with them once you have them.
== Turnstile using <code>State</code> ==
We now look at how the <code>State</code> type can help with the turnstile example. Firstly, by comparing the type of <code>coin :: TurnstileState -> (TurnstileOutput, TurnstileState)</code> with <code>newtype State s a = State { runState :: s -> (a, s) }</code>, we can see that, by replacing <code>s</code> with <code>TurnstileState</code> and <code>a</code> by <code>TurnstileOutput</code> we can define:
<syntaxhighlight lang="haskell">
coinS, pushS :: State TurnstileState TurnstileOutput
coinS = state coin
pushS = state push
</syntaxhighlight>
{{body note|I've added S at the end of these names, just to distinguish them from those on this page that aren't based on the <code>State</code> monad. It's not something you'd normally do.}}
We can then use <code>runState</code> to extract the underlying functions and apply them to a state, for example:
<syntaxhighlight lang="haskell">
GHCi> :t runState coinS
runState coinS :: TurnstileState -> (TurnstileOutput, TurnstileState)
GHCi> runState coinS Locked
(Thank,Unlocked)
</syntaxhighlight>
<!-- is this interesting / useful? Should it be somewhere else? -->
{{body note|There is an interesting comparison here between <code>runState</code> and ''partial application'' of functions.
We normally consider, for example, <code>take :: Int -> [a] -> [a]</code> to be a function of two arguments. But we also saw (briefly, [[Haskell/Lists_II#Generalizing_even_further|here]]) that we can apply it to only one argument to get a function of the one remaining argument, e.g. <code>take 2 :: [a] -> [a]</code>. We could then do e.g. <code>map (take 2) ["every", "good", "boy"]</code> to get <code>["ev", "go", "bo"]</code>. In fact, Haskell always applies arguments one step at a time, so that <code>take 2 "every"</code> first applies the <code>2</code> to get a new function, to which it then applies <code>"every"</code>. It could be written <code>(take 2) "every"</code>.
<code>runState</code> is defined as a function that takes a single argument. And it returns a function that takes a single argument, to which we can then apply an initial state value. So <code>runState coinS Locked</code> ''means'' <code>(runState coinS) Locked</code>. But, as with <code>(take 2) "every"</code>, the brackets are not needed.
In terms of application of arguments, <code>take</code> and <code>runState</code> are similar: they take one argument and return a function that takes another. The big difference between them is in their definitions. When <code>take</code> is defined it declares two parameters and uses both of them in the function definition. <code>runState</code>, however, is (implicitly) defined as a function of a single parameter. The function it returns is defined separately (by a user of <code>State</code>), and the type of <code>State</code> requires it to be a function of one parameter. Each of these implementations reference only their own parameters directly.
}}
=== Using the Turnstile <code>State</code> monad ===
Not yet too exciting, but now <code>coinS</code> and <code>pushS</code> are monadic (they are functions — admittedly of zero parameters — that return Monad instances) we can do monadic stuff with them, including using <code>do</code> notation:
<syntaxhighlight lang="haskell">
mondayS :: State TurnstileState [TurnstileOutput]
mondayS = do
a1 <- coinS
a2 <- pushS
a3 <- pushS
a4 <- coinS
a5 <- pushS
return [a1, a2, a3, a4, a5]
GHCi> :t runState mondayS
runState mondayS :: TurnstileState -> ([TurnstileOutput], TurnstileState)
GHCi> runState mondayS Locked
([Thank,Open,Tut,Thank,Open],Locked)
</syntaxhighlight>
Note that we're no longer writing all the code to thread the output state from each step into the next: the <code>State</code> monad is doing that for us. A lot of the tedious and error-prone work has been removed. How? Remember that [[Haskell/do_notation|<code>do</code> is simply syntactic sugar for the bind <code>(>>=)</code> operator]] so the above is equivalent to:
<syntaxhighlight lang="haskell">
mondayS =
coinS >>= (\ a1 ->
pushS >>= (\ a2 ->
pushS >>= (\ a3 ->
coinS >>= (\ a4 ->
pushS >>= (\ a5 ->
return [a1, a2, a3, a4, a5] )))))
</syntaxhighlight>
This uses the <code>(>>=)</code> operator we defined for <code>State</code> above, unwraps each state-processing function from its <code>State</code> wrapper, applies the output state from it as an argument into the next step, and wraps the result back in a <code>State</code> wrapper. The sequence of <code>(>>=)</code> operators, along with <code>return</code> combines all the steps into a single combined state-processing function wrapped in a <code>State</code> wrapper, which we can access and run with <code>runState</code>.
A monad is sometimes described as providing a value in a ''context''. An <code>IO</code> monad can provide values from the real world when we ask it to. A <code>Maybe</code> monad can provide values if it's there, or not otherwise. What about the <code>State</code> monad? It can provide a value when we execute a step of a state-processor. (And the monad "automatically" ensures that state changes are passed from step to step without us having to worrying about it).
In this example, some tedium remains in obtaining the list of outputs from each step and combining them into a list. Can we do better? Yes we can:
<syntaxhighlight lang="haskell">
mondayS :: State TurnstileState [TurnstileOutput]
mondayS = sequence [coinS, pushS, pushS, coinS, pushS]
</syntaxhighlight>
We met <code>sequence</code> in the section on [[Haskell/Understanding_monads/IO#Monadic_control_structures|IO Monads]]. It creates a single action (in this case a state processing function) which, when executed, runs through each of the actions (in this case state processing steps) in turn, executing them and combining the results into a list.
{{Exercises|1=
#Implement the functions <code>regularPersonS, distractedPersonS, hastyPersonS :: State TurnstileState [TurnstileOutput]</code> using <code>sequence</code>. You will still need do notation for the third.<ref>This [[Haskell/Applicative_functors#A_sliding_scale_of_power|comparison of <code>Applicative</code> and <code>Monad</code>]] explains why you can't use just <code>sequence</code> for <code>hastyPersonS</code>. In summary, it's because the actions taken (and the number of values in the result list) depend on the outcome of the first action (the initial attempt to push the arm), whereas for the first two always execute two actions and return the corresponding two results.</ref>
#Implement <code>luckyPairS :: Bool -> State TurnstileState Bool</code>
}}
=== <code>evalState</code> and <code>execState</code> ===
We have seen how <code>runState</code> accesses the state processing function so that we can do, for example, <code>runState mondayS Locked</code>. (We also used it in the definition of <code>(>>=)</code>.)
Other functions which are used in similar ways are <code>evalState</code> and <code>execState</code>. Given a <code>State a b</code> and an initial state, the function <code>evalState</code> will give back only the result value of the state processing, whereas <code>execState</code> will give back just the new state.
<syntaxhighlight lang="haskell">
evalState :: State s a -> s -> a
evalState p s = fst (runState p s)
execState :: State s a -> s -> s
execState p s = snd (runState p s)
</syntaxhighlight>
OK, they're not much. But they're not nothing, and they allow us to do e.g.:
<syntaxhighlight lang="haskell">
GHCi> evalState mondayS Locked
[Thank,Open,Tut,Thank,Open]
</syntaxhighlight>
if we only want to see the output sequence, and not the final state.
=== Setting the State ===
What if we had an turnstile engineer who wanted to test the locking mechanism with code like this:
<syntaxhighlight lang="haskell">
testTurnstile :: State TurnstileState Bool
testTurnstile = do
--somehow set state to Locked
check1 <- pushS
--somehow set state to Unlocked
check2 <- pushS
--somehow set state to Locked again
return (check1 == Tut && check2 == Open)
</syntaxhighlight>
This handy function comes to the rescue:
<syntaxhighlight lang="haskell">
put :: s -> State s ()
put newState = state $ \_ -> ((), newState)
</syntaxhighlight>
<code>put</code> is a monadic function that can be bound with <code>(>>=)</code> operators or fit in do constructs in sequence with other actions. It takes a state parameter (the one we want to introduce) and generates a state processor which ignores whatever state it receives and gives back the new state we introduced as the next state. Since we don't care about the result of this processor (all we want to do is to replace the state), the first element of the tuple will be <code>()</code>, the universal placeholder value.<ref>The technical term for both <code>()</code> and its type is ''unit''.</ref>
Let's see how it helps the engineer:
<syntaxhighlight lang="haskell">
testTurnstile :: State TurnstileState Bool
testTurnstile = do
put Locked
check1 <- pushS
put Unlocked
check2 <- pushS
put Locked
return (check1 == Tut && check2 == Open)
GHCi> runState testTurnstile Locked
(True,Locked)
HHCi> runState testTurnstile Unlocked
(True,Locked)
</syntaxhighlight>
=== Accessing the State ===
In the definition of <code>pushS</code> above we made use of the existing code <code>push</code>. What if we wanted to write it without such pre-existing function? Obviously we could do this:
<syntaxhighlight lang="haskell">
pushS = state $ \s -> case s of
Locked -> (Tut , Locked)
Unlocked -> (Open, Locked)
</syntaxhighlight>
but could we write it all using a do construct? Yes, using this:
<syntaxhighlight lang="haskell">
get :: State s s
get = state $ \s -> (s, s)
</syntaxhighlight>
<code>get</code> is also monadic and creates a state processor that gives back the state <code>s</code> it is given both as a result and as the next state. That means the state will remain unchanged, and that a copy of it will be made available for us to use.<!-- Temporarily suppressed - it might be better to talk about that in the transformers chapter. <ref>In the <code>Control.Monad.State</code> module from the <code>mtl</code> package, <code>put</code> and <code>get</code> are methods of the <code>MonadState</code> class.</ref>-->
We could use <code>get</code> like this:
<syntaxhighlight lang="haskell">
pushS = do
s <- get
put Locked
case s of
Locked -> return Tut
Unlocked -> return Open
</syntaxhighlight>
{{Exercises|1=
#Rewrite <code>coinS</code> using a do construct with <code>get</code> and/or <code>put</code>.
#Extend <code>testTurnstile</code> so that it also checks the state is set to <code>Unlocked</code> after a coin is inserted, regardless of the state beforehand. And for good measure, have <code>testTurnstile</code> return the turnstile to it's original state when the testing is complete.
#Besides <code>put</code> and <code>get</code>, there are also<br><code>modify :: (s -> s) -> State s ()</code><br>which modifies the current state using a function, and<br><code>gets :: (s -> a) -> State s a</code><br>which produces a modified copy of the state while leaving the state itself unchanged. Write implementations for them.
}}
=== Monadic Control Structures ===
The second version of <code>mondayS</code> above shows another benefit of using the monad, in addition to the hiding of the state threading and ability to use do notation and the like: we are also able to use great functions like <code>sequence</code>. In this section we look at some more of these functions. (You will need to <code>import Control.Monad</code>, or do <code>GHCi> :m Control.Monad</code> to ensure all of these are in scope).
First, here's <code>replicateM</code>:
<syntaxhighlight lang="haskell">
GHCi> evalState (replicateM 6 pushS) Unlocked
[Open,Tut,Tut,Tut,Tut,Tut]
</syntaxhighlight>
Which is pretty self-explanatory.
Before we look at any more, we need a slightly different (arguably better) implementation of the turnstile finite-state machine, using an input type and a single processing function:
<syntaxhighlight lang="haskell">
data TurnstileInput = Coin | Push
deriving (Eq, Show)
turnS :: TurnstileInput -> State TurnstileState TurnstileOutput
turnS = state . turn where
turn Coin _ = (Thank, Unlocked)
turn Push Unlocked = (Open, Locked)
turn Push Locked = (Tut, Locked)
GHCi> runState (turnS Coin) Locked
(Thank,Unlocked)
</syntaxhighlight>
We can now use <code>mapM</code>, like this:
<syntaxhighlight lang="haskell">
GHCi> evalState (mapM turnS [Coin, Push, Push, Coin, Push]) Locked
[Thank,Open,Tut,Thank,Open]
</syntaxhighlight>
This very nicely illustrates how the finite-state machine is a ''transducer'': it converts an ordered sequence of inputs to an ordered sequence of outputs, maintaining the state as it goes along.
Now we'll look at <code>filterM</code>:
<syntaxhighlight lang="haskell">
getsThroughS :: TurnstileInput -> State TurnstileState Bool
getsThroughS input = do
output <- turnS input
return $ output == Open
GHCi> evalState (filterM getsThroughS [Push, Coin, Coin, Push, Push, Coin, Push]) Locked
[Push,Push]
</syntaxhighlight>
We can see two people made it through (not surprisingly, when they pushed the arm). If we switch the order of the first two inputs more people get through:
<syntaxhighlight lang="haskell">
GHCi> evalState (filterM getsThroughS [Coin, Push, Coin, Push, Push, Coin, Push]) Locked
[Push,Push,Push]
</syntaxhighlight>
Here's a different way of counting the number of openings using <code>foldM</code>:
<syntaxhighlight lang="haskell">
countOpens :: [TurnstileInput] -> State TurnstileState Int
countOpens = foldM incIfOpens 0 where
incIfOpens :: Int -> TurnstileInput -> State TurnstileState Int
incIfOpens n i = do
g <- getsThroughS i
if g then return (n+1) else return n
GHCi> evalState (countOpens [Coin, Push, Coin, Push, Push, Coin, Push]) Locked
3
</syntaxhighlight>
Note that <code>sequence</code>, <code>mapM</code> and <code>filterM</code> always execute all of the actions in the input list, but <code>foldM</code> could skip some.
{{Exercises|1=
#Modify <code>regularPersonS</code>, <code>distractedPersonS</code> and <code>hastyPersonS</code> to use <code>turnS</code> and <code>mapM</code>.
#Implement <code>tuesdayS</code> using <code>sequence</code> or <code>mapM</code>.
#Implement <code>saveCoinsS :: [TurnstileInput] -> State TurnstileState Int</code> that potentially processes all of the given inputs, but will skip a <code>Coin</code> input if the previous input generated a <code>Thanks</code>. It returns the number of <code>Coin</code> inputs that were skipped. E.g. <code>evalState (saveCoinsS [Push, Coin, Coin, Coin, Push, Push, Coin, Push]) Locked</code> should give <code>2</code>.
#Implement <code>sequenceUntil :: (a -> Bool) -> [State s a] -> State s [a]</code>. It processes each of the inputs until one of them generates a value that matches the predicate, then processes no more. E.g. <code>evalState (sequenceUntil (== Open) [coinS, coinS, coinS, pushS, pushS, coinS]) Locked</code> should give <code>[Thank,Thank,Thank,Open]</code>
#Modify <code>sequenceUntil</code> so that it works with any <code>Monad</code> instance.
}}
== Pseudo-Random Numbers ==
Suppose we are coding a game in which at some point we need an element of chance. In real-life games that is often obtained by means of dice or similar. For a computer program we need something to emulate such an object, and most programming languages provide some concept of ''random numbers'' that can be used for this purpose<ref>Random numbers can also be used for many other things, for example simulation, statistical analysis and cryptography</ref>.
Generating [[:wikipedia:Random number generation|actual random numbers]] is hard. Computer programs almost always use [[:wikipedia:Pseudorandom number generator|''pseudo''-random numbers]] instead.
They are "pseudo" because they are not ''actually'' random, and that they are ''known in advance''. Indeed, they are generated by algorithms (the pseudo-random number generators) which take an initial state (commonly called the ''seed'') and produce from it a sequence of numbers that have the appearance of being random.<ref>A common source of seeds is the current date and time as given by the internal clock of the computer. Assuming the clock is functioning correctly, it can provide unique seeds suitable for most day-to-day needs (as opposed to applications which demand high-quality randomness, as in cryptography or statistics).</ref> Every time a pseudo-random number is requested, state somewhere must be updated, so that the generator can be ready for producing a fresh, different random number the next time.
Sequences of pseudo-random numbers can be replicated exactly if the initial seed and the generating algorithm are known.
=== Haskell Global Pseudo-Random Number Generator ===
Producing a pseudo-random number in most programming languages is very simple: there is a function somewhere in the libraries that provides a pseudo-random value (and also updates an internal mutable state so that it produces a different value next time, although some implementations perhaps produce a truly random value). Haskell has a similar one in the <code>System.Random</code> module from the <code>random</code> package:
<syntaxhighlight lang="haskell">
GHCi> :m System.Random
GHCi> :t randomIO
randomIO :: Random a => IO a
</syntaxhighlight>
What is <code>Random</code>? It's the class of types that can have pseudo-random values generated by the <code>System.Random</code> module functions. <code>Int</code>, <code>Integer</code>, <code>Bool</code> and others are all instances of <code>Random</code>. You can "request" any of these by specifying the result type:
<syntaxhighlight lang="haskell">
GHCi> randomIO :: IO Int
-1557093684
GHCi> randomIO :: IO Int
1342278538
GHCi> randomIO :: IO Bool
True
</syntaxhighlight>
More interestingly, <code>randomIO</code> is an <code>IO</code> action. It couldn't be otherwise, as it makes use of mutable state, which is kept out of reach from our Haskell programs. Thanks to this hidden dependency, the pseudo-random values it gives back can be different every time.
However, we're here to study the <code>State</code> monad, so let's look at functions that take and return an explicit representation of the random number generator state.
=== Haskell Pseudo-Random Number Generator with Explicit State ===
Here's a slightly different function in the <code>System.Random</code> module:
<syntaxhighlight lang="haskell">
GHCi> :t random
random :: (Random a, RandomGen g) => g -> (a, g)
</syntaxhighlight>
Now there's no <code>IO</code>, and we should recognise the <code>g -> (a, g)</code> pattern as something we could put inside a <code>State</code> wrapper.
What is <code>RandomGen</code>? It is another class defined in the <code>System.Random</code> module. The module also provides a single instance <code>StdGen</code>. There are a couple of ways to create values of this type. The one we will use first is <code>mkStdGen :: Int -> StdGen</code> which creates a <code>StdGen</code> value from a given seed:
<syntaxhighlight lang="haskell">
GHCi> mkStdGen 666
667 1
GHCi> mkStdGen 666
667 1
</syntaxhighlight>
Note that, given the same seed, you get the same StdGen. What is <code>StdGen</code>? The documentation calls it "the standard pseudo-random number generator", but it might be better to call it the ''state'' of the standard pseudo-random number generator. We can see that here:
<syntaxhighlight lang="haskell">
GHCi> let s = mkStdGen 666
GHCi> s
667 1
GHCi> random s :: (Int, StdGen)
(6438947685955577547,392509921 2103410263)
</syntaxhighlight>
The first function (<code>mkStdGen 666</code>) returns an initial state, based on a given seed of 666. The second function (<code>random s</code>) takes the initial <code>StdGen</code> state and returns a pair: a random value (we've requested an <code>Int</code>) and a new <code>StdGen</code> state. How is the state represented internally? The <code>System.Random</code> module does it somehow, and we don't really care how. (We can see <code>StdGen</code> implements <code>show</code>, which displays two funny numbers. We could go and look at the source code if we really wanted to see how it works, but some clever person might go and change it one day anyway). How does <code>random</code> calculate a new state? We also don't care; we can just be happy that it does.
=== Example: Rolling Dice ===
[[File:Dice.jpg|thumb|<code>randomR (1,6)</code>]]
We are going to build a dice-throwing example. And for this, we'll use a slightly different function:
<syntaxhighlight lang="haskell">
GHCi> let s = mkStdGen 666
GHCi> randomR (1,6) s
(6,26689338 40692)
</syntaxhighlight>
<code>randomR</code> takes a range (in this case 1 to 6) and returns a pseudo-random number in the range (we were lucky: we got a 6!).
Suppose we want a function that rolls two dice and returns a pair representing the result of each throw. Here's one way:
<syntaxhighlight lang="haskell">
import System.Random --put this towards the top of the file
rollPair :: StdGen -> ((Int, Int), StdGen)
rollPair s0 =
let (r1, s1) = randomR (1,6) s0
(r2, s2) = randomR (1,6) s1
in ((r1, r2), s2)
GHCi> rollPair (mkStdGen 666)
((6,1),647839921 1655838864)
</syntaxhighlight>
Doesn't this remind us of the tedious and error-prone approach we first tried in the [[#Sequencing_Steps|turnstile example]]? Not convinced it's tedious? Try the first exercise:
{{Exercises|1=
#Implement <code>rollSix :: StdGen -> ([Int], StdGen)</code> using <code>randomR (1,6)</code> that returns a list representing the result of six consecutive throws.
#Implement <code>rollN :: Int -> StdGen -> ([Int], StdGen)</code>. This is a bit tricky! But possible using <code>iterate</code> and <code>take</code>, for example.
#We're about to define <code>rollDieS :: State StdGen Int</code>. Why don't you have a go at it first, and contemplate what it is and how it could help.
}}
=== Dice with <code>State</code> ===
So, a better way, using <code>State</code>:
<syntaxhighlight lang="haskell">
rollDieS :: State StdGen Int
rollDieS = state $ randomR (1,6)
GHCi> runState rollDieS (mkStdGen 666)
(6,26689338 40692)
</syntaxhighlight>
This is very similar to the original versions of <code>coinS</code> and <code>pushS</code>: there was already a function of form <code>s -> (a, s)</code>, and we just wrapped in in a <code>State</code> wrapper. Now we have monadic power! We can write:
<syntaxhighlight lang="haskell">
rollPairS :: State StdGen (Int, Int)
rollPairS = do
r1 <- rollDieS
r2 <- rollDieS
return (r1, r2)
GHCi> runState rollPairS (mkStdGen 666)
((6,1),647839921 1655838864)
</syntaxhighlight>
And we avoid all the tedious threading of state from one step to the next.
{{Exercises|1=
#Implement <code>rollSixS :: State StdGen [Int]</code> with the same behaviour as <code>rollSix</code>. Use do notation and <code>rollDieS</code>.
#Implement <code>rollNS :: Int -> State StdGen [Int]</code> using <code>replicateM</code>
#Implement <code>luckyDoubleS :: State StdGen Int</code>. It does a first throw. If it's a 6 it throws again and returns the total of the two throws, else it just returns the first throw.
}}
=== <code>State</code> is also a <code>Functor</code> and an <code>Applicative</code> ===
Here's another dice throwing function:
<syntaxhighlight lang="haskell">
rollDieDoubledS :: State StdGen Int
rollDieDoubledS = do
r <- rollDieS
return (r * 2)
</syntaxhighlight>
Its behaviour should be clear. But it seems a bit verbose for such a simple function. Can we do better?
As we [[Haskell/Understanding_monads#Monad_and_Applicative|noted previously]] (and saw [[#Instantiating_the_Monad|above]]), <code>State</code> (and all other monads) are also instances of <code>Functor</code> and <code>Applicative</code>. And in [[Haskell/Prologue:_IO,_an_applicative_functor|the prologue]] we did:
<syntaxhighlight lang="haskell">
...
let mx = readMaybe s :: Maybe Double
case fmap (2*) mx of
...
</syntaxhighlight>
This leveraged the fact that <code>Maybe</code> is a <code>Functor</code>. The <code>fmap (2*) mx</code> converts a <code>Just x</code> to <code>Just (2*x)</code> (or <code>Nothing</code> to <code>Nothing</code>). If we think of <code>x</code> as a value wrapped in a context, we can see that the <code>fmap</code> has kept the same context (it's still a <code>Just</code>, or still <code>Nothing</code>), but applied a conversion to the wrapped value. We can do the same with the <code>State</code> functor:
<syntaxhighlight lang="haskell">
rollDieDoubledS = fmap (*2) rollDieS
</syntaxhighlight>
The meaning of <code>State</code> is different to the meaning of <code>Maybe</code> (it's the output of a state-processing step, not a possibly-existing value), but we've applied the same conversion to the wrapped value. Now, when we unwrap the value from <code>rollDieDoubledS</code> we get double what we would have got had we unwrapped <code>rollDieS</code>.
Suppose we also wanted <code>rollTwoSummedS :: State StdGen Int</code>? In the prologue section did <code>sz <- (++) <$> getLine <*> getLine</code>, and again we can do something similar:
<syntaxhighlight lang="haskell">
rollTwoSummedS :: State StdGen Int
rollTwoSummedS = (+) <$> rollDieS <*> rollDieS
</syntaxhighlight>
This code depends on <code>State</code> being also an <code>Applicative</code>, but not on it being a <code>Monad</code>. It will ensure each of the <code>rollDieS</code> actions is executed in order, and chain the state correctly between them. It will then repackage the combination as a state-processing function wrapped in a <code>State</code> wrapper. The combined function will return the sum of the two successive throws (and also, but quietly, ensure the state is added as an input parameter and an output value).
The <code>Control.Applicative</code> module provides a function <code>liftA2</code>:
<syntaxhighlight lang="haskell">
liftA2 f u v = f <$> u <*> v
</syntaxhighlight>
Using this, it <code>rollTwoSummedS</code> could be defined as:
<syntaxhighlight lang="haskell">
import Control.Applicative --this needs to be at the top of your file
rollTwoSummedS = liftA2 (+) rollDieS rollDieS
</syntaxhighlight>
{{Exercises|1=
#Rewrite <code>rollPairS</code> using <code>(<$>)</code> and <code>(<*>)</code>, or <code>liftA2</code>.
#Implement <code>happyDoubleS :: State StdGen Int</code>, which throws two dice and returns the sum of the first and the second, but doubles the total if the first is a six. Code it using do notation.
#Rewrite <code>happyDoubleS</code> using <code>(<$>)</code> and <code>(<*>)</code>, or <code>liftA2</code>.
#Can you recode <code>luckyDoubleS</code> using just <code>(<$>)</code> and <code>(<*>)</code> (or <code>liftA2</code>)? Why not? Can you use <code>(<$>)</code> (or <code>fmap</code>) to make it a bit shorter?
#Modify <code>tuesdayS</code>, <code>saveCoinS</code> and <code>sequenceUntil</code> from the [[#Monadic_Control_Structures|Monadic Control Structures]] exercises using <code>fmap</code> and/or <code>(<$>)</code>.
#In a [[#Instantiating_the_Monad|previous section]] we defined <code>State</code> instances of <code>Functor</code> and <code>Applicative</code> by deferring to the <code>Monad</code> instance. Now try to write them explicitly based on their behaviour, without using the <code>Monad</code> instance.
}}
More is said later on the [[Haskell/Applicative_functors|relationship between <code>Functor</code>, <code>Applicative</code> and <code>Monad</code>]], and choosing which one to use.
=== Pseudo-random values of different types ===
We saw that <code>randomIO :: Random a => IO a</code> can return a value of a type other than <code>Int</code>. So can its <code>IO</code>-free equivalent <code>random :: (Random a, RandomGen g) => g -> (a, g)</code>.
Because <code>State StdGen</code> is "agnostic" in regard to the type of the pseudo-random value it produces, we can write a similarly "agnostic" function that provides a pseudo-random value of unspecified type (as long as it is an instance of <code>Random</code>):
<syntaxhighlight lang="haskell">
getRandomS :: Random a => State StdGen a
getRandomS = state random
</syntaxhighlight>
Compared to <code>rollDieS</code>, this function does not specify the <code>Int</code> type in its signature and uses <code>random</code> instead of <code>randomR</code>; otherwise, it is just the same. <code>getRandomS</code> can be used for any instance of <code>Random</code>:
<syntaxhighlight lang="haskell">
GHCi> evalState getRandomS (mkStdGen 0) :: Bool
True
GHCi> evalState getRandomS (mkStdGen 0) :: Char
'\64685'
GHCi> evalState getRandomS (mkStdGen 0) :: Double
0.9872770354820595
GHCi> evalState getRandomS (mkStdGen 0) :: Integer
2092838931
</syntaxhighlight>
Indeed, it becomes quite easy to conjure all these at once:
<syntaxhighlight lang="haskell">
someTypes :: State StdGen (Int, Float, Char)
someTypes = liftA3 (,,) getRandomS getRandomS getRandomS
allTypes :: State StdGen (Int, Float, Char, Integer, Double, Bool, Int)
allTypes = (,,,,,,) <$> getRandomS
<*> getRandomS
<*> getRandomS
<*> getRandomS
<*> getRandomS
<*> getRandomS
<*> getRandomS
</syntaxhighlight>
For writing <code>allTypes</code>, there is no <code>liftA7</code>,<ref>Beyond <code>liftA3</code>, the standard libraries only provide the monad-only <code>liftM4</code> and <code>liftM5</code> in <code>Control.Monad</code>.</ref> and so we resort to plain old <code>(<*>)</code> instead. Using it, we can apply the tuple constructor to each of the seven random values in the <code>State StdGen</code> monadic context.
<code>allTypes</code> provides pseudo-random values for all default instances of <code>Random</code>; an additional <code>Int</code> is inserted at the end to prove that the generator is not the same, as the two <code>Int</code>s will be different.
<syntaxhighlight lang="haskell">
GHCi> evalState allTypes (mkStdGen 0)
GHCi>(2092838931,9.953678e-4,'\825586',-868192881,0.4188001483955421,False,316817438)
</syntaxhighlight>
=== (Probably) don't <code>put</code> or <code>get</code> ===
In the [[#Turnstile using State|turnstile example]], we used <code>put</code> to [[#Setting_the_State|set the state]] and <code>get</code> to [[#Accessing_the_State|access it]]. Can we do the same here? Well, yes we can, but there's probably no need.
In that example, we had to code functions (like <code>pushS</code>) that used the current state to determine outputs and new states, or (like <code>testTurnstile</code>) that set required states as part of a processing sequence. With our random number examples, all generation, inspection and update of the <code>StdGen</code> state is done internally within the <code>System.Random</code> module, without us having to know how.
Now, in our [[#Example:_Rolling_Dice|first implementation of <code>rollPair</code>]] we were aware of the <code>StdGen</code> state: we took it as a parameter, threaded it through the successive steps and returned the final state. If we ''really'' wanted to use the value (perhaps we wanted to put it in a debugging message using <code>trace</code>) then we did have the opportunity. And, with our <code>State</code> monad we still do. The following shows one usage:
<syntaxhighlight lang="haskell">
rollDieS :: State StdGen Int
rollDieS = do s0 <- get
let (value, s1) = randomR (1,6) s0
put s1
return value
</syntaxhighlight>
This does spell out all of the steps the <code>State</code> monad takes for us, but would be a rather perverse implementation since the whole point of the monad is so we don't have to spell them out.
{{Exercises|1=
#Write <code>randomElt :: [a] -> State StdGen a</code>, using <code>put</code> and <code>get</code> to access the <code>StdGen</code> state. It can assume the list is non empty, and should return a random element from within it.
#Rewrite <code>randomElt</code> without using <code>put</code> or <code>get</code>.
}}
=== Better Random Numbers ===
Other than our initial use of <code>randomIO</code>, all of the above examples have used <code>mkStdGen</code>, and all with the same seed value 666. This would make for a pretty boring game, where exactly the same dice were rolled each time. (Though this might be useful, e.g. when testing your program.) How can we get better random numbers? Like this:
<syntaxhighlight lang="haskell">
getRandomPair :: IO (Int, Int)
getRandomPair = do
s <- newStdGen
return $ evalState rollPairS s
</syntaxhighlight>
<code>newStdGen</code> is (effectively) defined as <code>newStdGen :: IO StdGen</code>. It is an IO action that spawns a new random state from the same global random state used by <code>randomIO</code>. It also updates that global state, so that further uses of <code>newStdGen</code> give a different value.
So, aren't we back a square one, being dependent on <code>IO</code>? No we're not. We have gained all the power of the <code>State</code> monad to build up chains of dice-rolling steps which we can assemble into bigger and bigger state-transformation functions. We can do all of that without <code>IO</code>. In the turnstile example, we didn't need <code>IO</code> at all (although we probably would if we wanted to put our code into some kind of application), and for some uses of random numbers, having the same numbers each time might be beneficial. We only needed <code>IO</code> to get "really random" numbers, and we may well need <code>newStdGen</code> only once in a program. Chances are that it would be alongside other <code>IO</code> actions, for example:
<syntaxhighlight lang="haskell">
main :: IO ()
main = do
s <- newStdGen
let (r1, r2) = evalState rollPairS s
putStrLn $ "You rolled twice and got " ++ show r1 ++ " and " ++ show r2 ++ "."
</syntaxhighlight>
== Handling Combined States ==
Suppose we wanted to create a random turnstile, where each visitor would be given a random turnstile input: either they insert a coin (but are not allowed through); or they get to push the arm (and go through if it opens, but are otherwise sent away).
Here's one useful bit of code:
<syntaxhighlight lang="haskell">
randomInputS :: State StdGen TurnstileInput
randomInputS = do
b <- getRandomS
return $ if b then Coin else Push
</syntaxhighlight>
This allows us to generate random <code>turnstileInput</code> values<ref>Alternatively, we could make <code>TurnstileInput</code> an instance of <code>Uniform</code>, but this code seems easier.</ref>. However, our random turnstile machine needs to track both the state of a random number generator and the state of the turnstile. We want to write a function like this:
<syntaxhighlight lang="haskell">
randomTurnS :: State (StdGen, TurnstileState) TurnstileOutput
</syntaxhighlight>
And this function needs to call both <code>randomInputS</code> (which is in the <code>State StdGen</code> monad) and <code>turnS</code> (which is in the <code>State TurnstileState</code> monad).
{{Exercises|1=
#Implement <code>randomTurnS</code>, using <code>get</code> and <code>put</code> to access and set the combined state, and <code>runState</code> to invoke <code>randomInputS</code> and <code>turnS</code>.
}}
Much of the code in <code>randomTurnS</code> deals with managing the state: accessing the combined state, unpacking subcomponents, forwarding them to the individual State monads, recombining them and putting the combined state back. The state management code is not too bad in this case, but could easily become cumbersome in a more complex function. And it is something we wanted the <code>State</code> monad to hide from us.
=== State-Processing a Subcomponent ===
Ideally we'd want some utility function(s) that allow us to invoke a <code>State StdGen</code> monad function (or <code>State TurnstileState</code> monad function) from within a <code>State (StdGen, TurnstileState)</code> monad function. These function(s) should take care of the state management for us, ensuring that the right subcomponent of the combined state is updated.
Here's one such a function that works for any combined state represented as a pair, and performs the state update on the first state of the pair:
<syntaxhighlight lang="haskell">
processingFst :: State a o -> State (a,b) o
processingFst m = do
(s1,s2) <- get
let (o,s1') = runState m s1
put (s1',s2)
return o
</syntaxhighlight>
Note the type:
<syntaxhighlight lang="haskell">
GHCi> :t processingFst randomInputS
processingFst randomInputS :: State (StdGen, b) TurnstileInput
</syntaxhighlight>
<code>processingFst</code> "converts" a <code>State</code> monad (in this case with state type <code>StdGen</code>) to another <code>State</code> monad (in this case with state type <code>(StdGen, b)</code>, where <code>b</code> can be any type, even a <code>TurstileState</code>).
{{Exercises|1=
#Implement <code>processingSnd</code>.
#Modify <code>randomTurnS</code> to use <code>processingFst</code> and <code>processingSnd</code>.
}}
Note how <code>randomTurnS</code> is no longer directly involved in the details of the state management, and its business logic is much more apparent.
=== Generic Subcomponent Processing ===
We can see that <code>processingFst</code> and <code>processingSnd</code> are very similar. They both extract a subcomponent of a combined state, <code>runState</code> on that subcomponent, then update the combined state with the new value of the subcomponent.
Let's combine them into a single generic subcomponent processing function. To do this, we could pass two functions in separate parameters, one of type <code>(cmb -> sub)</code> (a function that extracts a subcomponent from a combined state value), and another of type <code>(cmb -> sub -> cmb)</code> (a function that, given a combined value and a new value for a subcomponent, returns the revised combined value with the updated subcomponent). However, it's a bit neater to package these two functions together in a type which we'll call <code>Lens</code>:
<syntaxhighlight lang="haskell">
data Lens cmb sub = Lens
{ view :: cmb -> sub,
set :: cmb -> sub -> cmb
}
</syntaxhighlight>
We can provide specific lenses onto the fst and snd elements in a pair:
<syntaxhighlight lang="haskell">
fstL :: Lens (a,b) a
fstL = Lens fst (\(_,y) x -> (x,y))
sndL :: Lens (a,b) b
sndL = Lens snd (\(x,_) y -> (x,y))
</syntaxhighlight>
So now:
<syntaxhighlight lang="haskell">
GHCi> view fstL ("fred", 5)
"fred"
GHCi> set fstL ("fred", 5) "sue"
("sue",5)
</syntaxhighlight>
{{body note|1=
Lenses that are more sophisticated and powerful are [[Haskell/Lenses_and_functional_references|described later]], but it's also harder to understand how they work. Our simple lenses are sufficient for now, but you might want to update the random turnstile code to use "proper lenses" later on.
}}
We can now replace <code>processingFst</code> and <code>processingSnd</code> with our generic function.
{{Exercises|1=
#Implement <code>processing</code> that takes a <code>Lens cmb sub</code> parameter, and "converts" a <code>State sub</code> to a <code>State cmb</code>.
#Rewrite <code>randomTurnS</code> using the <code>processing</code> function (and <code>fstL</code> and <code>sndL</code>).
}}
Our final random turnstile code is neater, with three separate logical functions segregated:
* state management (now in a single <code>processing</code> utility function, which can be reused elsewhere);
* subcomponent accessing and update (using <code>Lens</code>, which can also be reused elsewhere<ref>We could use <code>Control.Lens</code> for this as described in the later chapter. This module also provides more lenses, automatic creation of lenses for custom data types, easy combining of lenses for deeply-nested subcomponents, etc. Also, <code>Control.Lens.Combinators</code> includes a <code>zoom</code> function that is more generic than <code>processing</code>.</ref>.); and
* the "business logic" of the turnstile, which is now very apparent.
In our first implementation, all three of these were muddled together.
Let's give it a go:
<syntaxhighlight lang="haskell">
GHCi> g <- newStdGen
GHCi> evalState (replicateM 10 randomTurnS) (g, Locked)
[Thank,Open,Tut,Thank,Thank,Open,Tut,Tut,Tut,Thank]
</syntaxhighlight>
I'm not sure we'll sell many of them, though.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Monads}}
{{BookCat}}
gw8563aanqzp5t0woznw7d1kl55iq0c
Haskell/Understanding monads/List
0
209355
4676018
3811768
2026-10-14T11:10:55Z
Luciérnaga de conocimiento
3401314
4676018
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Monads}}
Lists are a fundamental part of Haskell, and we've used them extensively before getting to this chapter. The novel insight is that the list type is a monad too!
As monads, lists are used to model ''nondeterministic'' computations which may return an arbitrary number of results. There is a certain parallel with how <code>Maybe</code> represented computations which could return zero or one value; but with lists, we can return zero, one, or many values (the number of values being reflected in the length of the list).
== The <code>Monad</code> instance of lists ==
The <code>return</code> function for lists simply injects a value into a list:
<syntaxhighlight lang="haskell">
return x = [x]
</syntaxhighlight>
In other words, <code>return</code> here makes a list containing one element, namely the single argument it took. The type of the ''list return'' is <code><nowiki>return :: a -> [a]</nowiki></code>, or, equivalently, <code><nowiki>return :: a -> [] a</nowiki></code>. The latter style of writing it makes it more obvious that we are replacing the generic type constructor in the signature of <code>return</code> (which we had called <code>M</code> in [[Haskell/Understanding monads|Understanding monads]]) with the list type constructor <code>[]</code> (which is distinct from, but easy to confuse with, the empty list!).
The binding operator is less trivial. We will begin by considering its type, which for the case of lists should be:
<syntaxhighlight lang="haskell">
[a] -> (a -> [b]) -> [b]
</syntaxhighlight>
This is just what we'd expect: it pulls out the values from the list to give them to a function that produces a new list.
The actual process here involves first <code>map</code>ping a given function over a given list to get back a list of lists, i.e. type <code><nowiki>[[b]]</nowiki></code> (of course, many functions which you might use in mapping do not return lists; but, as shown in the type signature above, monadic binding for lists only works with functions that return lists). To get back to a regular list, we then concatenate the elements of our list of lists to get a final result of type <code>[b]</code>. Thus, we can define the list version of <code>(>>=)</code>:
<syntaxhighlight lang="haskell">
xs >>= f = concat (map f xs)
</syntaxhighlight>
The bind operator is key to understanding how different monads do their jobs, as its definition specifies the chaining strategy used when working with the monad. In the case of the list monad, the strategy allows us to model non-determinism: an <code>a -> [b]</code> function can be seen as a way of generating, from an input of type <code>a</code>, an unspecified number of ''possible'' outputs of type <code>b</code>, without settling on any one of them in particular. <code>(>>=)</code>, from that perspective, does that for multiple inputs and combines all output possibilities in a single result list.
== Bunny invasion ==
It is easy to incorporate the familiar list processing functions in monadic code. Consider this example: rabbits raise an average of six kits in each litter, half of which will be female. Starting with a single mother, we can model the number of female kits in each successive generation (i.e. the number of new kits after the rabbits grow up and have their own litters):
<pre>
Prelude> let generation = replicate 3
Prelude> ["bunny"] >>= generation
["bunny","bunny","bunny"]
Prelude> ["bunny"] >>= generation >>= generation
["bunny","bunny","bunny","bunny","bunny","bunny","bunny","bunny","bunny"]
</pre>
In this silly example all elements are equal, but the same overall logic could be used to model [http://en.wikipedia.org/wiki/Decay_chain radioactive decay], or chemical reactions, or any phenomenon that produces a series of elements by repeated multiplication.
{{Exercises|1=
#Predict what should be the result of <code>["bunny", "rabbit"] >>= generation</code>.
#Implement <code>themselvesTimes :: [Int] -> [Int]</code>, which takes each number <math>n</math> in the argument list and generates <math>n</math> copies of it in the result list.
}}
== Board game example ==
Suppose we are modeling a turn-based board game and want to find all the possible ways the game could progress. We would need a function to calculate the list of options for the next turn, given a current board state:
<syntaxhighlight lang="haskell">
nextConfigs :: Board -> [Board]
nextConfigs bd = undefined -- details not important
</syntaxhighlight>
To figure out all the possibilities after two turns, we would again apply our function to each of the elements of our new list of board states. Our function takes a single board state and returns a list of possible new states. Thus, we can use monadic binding to map the function over each element from the list:
<syntaxhighlight lang="haskell">
nextConfigs bd >>= nextConfigs
</syntaxhighlight>
In the same fashion, we could bind the result back to the function yet again (ad infinitum) to generate the next turn's possibilities. Depending on the particular game's rules, we may reach board states that have no possible next-turns; in those cases, our function will return the empty list.
On a side note, we could translate several turns into a <code>do</code> block (like we did for the grandparents example in [[Haskell/Understanding monads|Understanding monads]]):
<syntaxhighlight lang="haskell">
threeTurns :: Board -> [Board]
threeTurns bd = do
bd1 <- nextConfigs bd -- bd1 refers to a board configuration after 1 turn
bd2 <- nextConfigs bd1
nextConfigs bd2
</syntaxhighlight>
If the above looks too magical, keep in mind that <code>do</code> notation is syntactic sugar for <code>(>>=)</code> operations. To the right of each left-arrow, there is a function with arguments that evaluate to a list; the variable to the left of the arrow stands for the list elements. After a left-arrow assignment line, there can be later lines that call the assigned variable as an argument for a function. This later function will be performed for ''each'' of the elements from within the list that came from the left-arrow line's function. This per-element process corresponds to the `map` in the definition of <code>(>>=)</code>. A resulting list of lists (one per element of the original list) will be flattened into a single list (the `concat` in the definition of <code>(>>=)</code>).
== List comprehensions ==
The list monad works in a way that has uncanny similarity to list comprehensions. Let's slightly modify the <code>do</code> block we just wrote for <code>threeTurns</code> so that it ends with a <code>return</code>...
<syntaxhighlight lang="haskell">
threeTurns bd = do
bd1 <- nextConfigs bd
bd2 <- nextConfigs bd1
bd3 <- nextConfigs bd2
return bd3
</syntaxhighlight>
This mirrors exactly the following list comprehension:
<syntaxhighlight lang="haskell">
threeTurns bd = [ bd3 | bd1 <- nextConfigs bd, bd2 <- nextConfigs bd1, bd3 <- nextConfigs bd2 ]
</syntaxhighlight>
(In a list comprehension, it is perfectly legal to use the elements drawn from one list to define the following ones, as we did here.)
The resemblance is no coincidence: list comprehensions are, behind the scenes, defined in terms of <code>concatMap</code>, a function available from the Prelude that is defined as <code>concatMap f xs = concat (map f xs)</code>. That's just the list monad binding definition again! To summarize the nature of the list monad: binding for the list monad ''is'' a combination of concatenation and mapping, and so the combined function <code>concatMap</code> ''is'' effectively the same as <code>>>=</code> for lists (except for different syntactic order).
For the correspondence between list monad and list comprehension to be complete, we need a way to reproduce the filtering that list comprehensions can do. We will explain how that can be achieved a little later in the [[Haskell/Alternative and MonadPlus|Alternative and MonadPlus]] chapter.
{{Exercises|1=
As discussed in [[Haskell/Understanding monads|Understanding monads]], all <code>Monad</code>s also have an instance of <code>Applicative</code>. In particular, <code>(<*>)</code> for that instance might be defined as:
:<code>fs <*> xs = concatMap (\f -> map f xs) fs</code>
#Explain briefly what this <code>(<*>)</code> does.
#Write an alternative definition of <code>(<*>)</code> using a list comprehension. Do not use <code>map</code>, <code>concat</code> or <code>concatMap</code> explicitly.
}}
{{Haskell/Navigation|chapter=Monads}}
{{BookCat}}
97kgkospkd8vzvraqylt2bxvpy2g54r
Haskell/do notation
0
209379
4676019
4654884
2026-10-14T11:12:26Z
Luciérnaga de conocimiento
3401314
4676019
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Monads|noexercises=1}}
Using <code>do</code> blocks as an alternative monad syntax was first introduced way back in the [[Haskell/Simple input and output|Simple input and output]] chapter. There, we used <code>do</code> to sequence input/output operations, but we hadn't introduced monads yet. Now, we can see that <code>IO</code> is yet another monad.
Since the following examples all involve <code>IO</code>, we will refer to the computations/monadic values as ''actions'' (as we did in the earlier parts of the book). Of course, <code>do</code> works with any monad; there is nothing specific about <code>IO</code> in how it works.
== Translating the ''then'' operator ==
The <code>(>>)</code> (''then'') operator works almost identically in <code>do</code> notation and in unsugared code. For example, suppose we have a chain of actions like the following one:
<syntaxhighlight lang="haskell">
putStr "Hello" >>
putStr " " >>
putStr "world!" >>
putStr "\n"
</syntaxhighlight>
We can rewrite that in <code>do</code> notation as follows:
<syntaxhighlight lang="haskell">
do { putStr "Hello"
; putStr " "
; putStr "world!"
; putStr "\n" }
</syntaxhighlight>
(using the optional braces and semicolons explicitly, for clarity). This sequence of instructions nearly matches that in any imperative language. In Haskell, we can chain any actions as long as all of them are in the same monad. In the context of the <code>IO</code> monad, the actions include writing to a file, opening a network connection, or asking the user for an input.
Here's the step-by-step translation of <code>do</code> notation to unsugared Haskell code:
<syntaxhighlight lang="haskell">
do { action1 -- by monad laws equivalent to: do { action1
; action2 -- ; do { action2
; action3 } -- ; action3 } }
</syntaxhighlight>
becomes
<syntaxhighlight lang="haskell">
action1 >>
do { action2
; action3 }
</syntaxhighlight>
and so on, until the <code>do</code> block is empty.
== Translating the ''bind'' operator ==
The ''bind'' operator <code>(>>=)</code> is a bit more difficult to translate to and from the <code>do</code> notation. <code>(>>=)</code> passes a value, namely the result of an action or function, downstream in the binding sequence. <code>do</code> notation assigns a variable name to the passed value using the <code><-</code>.
<syntaxhighlight lang="haskell">
do { x1 <- action1
; x2 <- action2
; mk_action3 x1 x2 }
</syntaxhighlight>
The curly braces and the semicolons are optional if every line of code is indented to line up equally (NB: beware the mixing of tabs and spaces in that case; with the explicit curly braces and semicolons indentation plays no part and there's no danger).
<code>x1</code> and <code>x2</code> are the results of <code>action1</code> and <code>action2</code>. If, for instance, <code>action1</code> is an <code>IO Integer</code> then <code>x1</code> will be bound to an <code>Integer</code> value. The two bound values in this example are passed as arguments to <code>mk_action3</code>, which creates a third action. The <code>do</code> block is broadly equivalent to the following vanilla Haskell snippet:
<syntaxhighlight lang="haskell">
action1 >>= (\ x1 -> action2 >>= (\ x2 -> mk_action3 x1 x2 ))
</syntaxhighlight>
The second argument of the first (leftmost) bind operator (<code>>>=</code>) is a function (lambda expression) specifying what to do with the result of the action passed as the bind's first argument. Thus, chains of lambdas pass the results downstream. The parentheses could be omitted, because a lambda expression extends as far as possible. <code>x1</code> is still in scope at the point we call the final action maker <code>mk_action3</code>. We can rewrite the chain of lambdas more legibly by using separate lines and indentation:
<syntaxhighlight lang="haskell">
action1
>>=
(\ x1 -> action2
>>=
(\ x2 -> mk_action3 x1 x2 ))
</syntaxhighlight>
That shows the scope of each lambda function clearly. To group things more like the <code>do</code> notation, we could show it like this:
<syntaxhighlight lang="haskell">
action1 >>= (\ x1 ->
action2 >>= (\ x2 ->
mk_action3 x1 x2 ))
</syntaxhighlight>
These presentation differences are only a matter of assisting readability.<ref>Actually, the indentation isn't needed in this case. This is equally valid:
<syntaxhighlight lang="haskell">
action1 >>= \ x1 ->
action2 >>= \ x2 ->
action3 x1 x2
</syntaxhighlight>
Of course, we could use even more indentation if we wanted. Here's an extreme example:
<syntaxhighlight lang="haskell">
action1
>>=
\
x1
->
action2
>>=
\
x2
->
action3
x1
x2
</syntaxhighlight>
While that indention is certainly overkill, it could be worse:
<syntaxhighlight lang="haskell">
action1
>>= \
x1
-> action2 >>=
\
x2 ->
action3 x1
x2
</syntaxhighlight>
That is valid Haskell but is baffling to read; so please don't ever write like that. Write your code with consistent and meaningful groupings.</ref>
=== The ''fail'' method ===
Above, we said the snippet with lambdas was "broadly equivalent" to the <code>do</code> block. The translation is not exact because the <code>do</code> notation adds special handling of pattern match failures. When placed at the left of either <code><-</code> or <code>-></code>, <code>x1</code> and <code>x2</code> are patterns being matched. Therefore, if <code>action1</code> returned a <code>Maybe Integer</code> we could write a <code>do</code> block like this...
<syntaxhighlight lang="haskell">
do { Just x1 <- action1
; x2 <- action2
; mk_action3 x1 x2 }
</syntaxhighlight>
...and <code>x1</code> be an <code>Integer</code>. In such a case, what happens if <code>action1</code> returns <code>Nothing</code>? Ordinarily, the program would crash with an non-exhaustive patterns error, just like the one we get when calling <code>head</code> on an empty list. With <code>do</code> notation, however, failures are handled with the <code>fail</code> method for the relevant monad. The <code>do</code> block above translates to:
<syntaxhighlight lang="haskell">
action1 >>= f
where f (Just x1) = do { x2 <- action2
; mk_action3 x1 x2 }
f _ = fail "..." -- A compiler-generated message.
</syntaxhighlight>
The <code>fail</code> method is provided by the <code>MonadFail</code> class, which has <code>Monad</code> as its superclass.<ref><code>fail</code> used to be a method of <code>Monad</code> itself, but was permanently removed and moved to the new <code>MonadFail</code> in GHC 8.8. If you are using an older version of GHC, define it under <code>Monad</code> instead.</ref> Without an instance declaration for <code>MonadFail</code>, you will only be able to use pattern matches that are ''unfailable''. Consider the following trivial example:
<syntaxhighlight lang="haskell">
newtype One a = One a
</syntaxhighlight>
Pattern matching using <code>One x <- action</code> would never fail, and you would not need a <code>MonadFail</code> instance to do so.
What <code>fail</code> actually does depends on the <code>MonadFail</code> instance. Though it will often rethrow the pattern matching error, monads that incorporate some sort of error handling may deal with the failure in their own specific ways. For instance, <code>Maybe</code> has {{nowrap|1=<code>fail _ = Nothing</code>}}; analogously, for the list monad {{nowrap|1=<code>fail _ = []</code>}}.<ref>This explains why, as we pointed out in the [[Haskell/Pattern_matching#List_comprehensions|"Pattern matching" chapter]], pattern matching failures in list comprehensions are silently ignored.</ref>
The <code>fail</code> method is an artifact of <code>do</code> notation. Rather than calling <code>fail</code> directly, you should rely on automatic handling of pattern match failures whenever you are sure that <code>fail</code> will do something sensible for the monad you are using.
== Example: user-interactive program ==
{{Body note|We are going to interact with the user, so we will use <code>putStr</code> and <code>getLine</code> alternately. To avoid unexpected results in the output, we must disable output buffering when importing <code>System.IO</code>. To do this, put <code>hSetBuffering stdout NoBuffering</code> at the top of your <code>do</code> block. To handle this otherwise, you would explicitly flush the output buffer before each interaction with the user (namely a <code>getLine</code>) using <code>hFlush stdout</code>. If you are testing this code with ghci, you don't have such problems.}}
Consider this simple program that asks the user for their first and last names:
<syntaxhighlight lang="haskell">
nameDo :: IO ()
nameDo = do putStr "What is your first name? "
first <- getLine
putStr "And your last name? "
last <- getLine
let full = first ++ " " ++ last
putStrLn ("Pleased to meet you, " ++ full ++ "!")
</syntaxhighlight>
A possible translation into vanilla monadic code:
<syntaxhighlight lang="haskell">
nameLambda :: IO ()
nameLambda = putStr "What is your first name? " >>
getLine >>= \ first ->
putStr "And your last name? " >>
getLine >>= \ last ->
let full = first ++ " " ++ last
in putStrLn ("Pleased to meet you, " ++ full ++ "!")
</syntaxhighlight>
In cases like this, where we just want to chain several actions, the imperative style of <code>do</code> notation feels natural and convenient. In comparison, monadic code with explicit binds and lambdas is something of an acquired taste.
Notice that the first example above includes a <code>let</code> statement in the <code>do</code> block. The de-sugared version is simply a regular <code>let</code> expression where the <code>in</code> part is whatever follows from the <code>do</code> syntax.
== Returning values ==
The last statement in <code>do</code> notation is the overall result of the <code>do</code> block. In the previous example, the result was of the type <code>IO ()</code>, i.e. an empty value in the <code>IO</code> monad.
Suppose that we want to rewrite the example but return an <code>IO String</code> with the acquired name. All we need to do is add a <code>return</code>:
<syntaxhighlight lang="haskell">
nameReturn :: IO String
nameReturn = do putStr "What is your first name? "
first <- getLine
putStr "And your last name? "
last <- getLine
let full = first ++ " " ++ last
putStrLn ("Pleased to meet you, " ++ full ++ "!")
return full
</syntaxhighlight>
This example will "return" the full name as a string inside the <code>IO</code> monad, which can then be utilized downstream elsewhere:
<syntaxhighlight lang="haskell">
greetAndSeeYou :: IO ()
greetAndSeeYou = do name <- nameReturn
putStrLn ("See you, " ++ name ++ "!")
</syntaxhighlight>
Here, <code>nameReturn</code> will be run and the returned result (called "full" in the <code>nameReturn</code> function) will be assigned to the variable "name" in our new function. The greeting part of <code>nameReturn</code> will be printed to the screen because that is part of the calculation process. Then, the additional "see you" message will print as well, and the final returned value is back to being <code>IO ()</code>.
If you know imperative languages like C, you might think <code>return</code> in Haskell matches <code>return</code> elsewhere. A small variation on the example will dispel that impression:
<syntaxhighlight lang="haskell">
nameReturnAndCarryOn = do putStr "What is your first name? "
first <- getLine
putStr "And your last name? "
last <- getLine
let full = first++" "++last
putStrLn ("Pleased to meet you, "++full++"!")
return full
putStrLn "I am not finished yet!"
</syntaxhighlight>
The string in the extra line ''will'' be printed out because <code>return</code> is ''not'' a final statement interrupting the flow (as it would be in C and other languages). Indeed, the type of <code>nameReturnAndCarryOn</code> is <code>IO ()</code>, — the type of the final <code>putStrLn</code> action. After the function is called, the <code>IO String</code> created by the <code>return full</code> will disappear without a trace.
== Just sugar ==
As a syntactical convenience, <code>do</code> notation does not add anything essential, but it is often preferable for clarity and style. However, <code>do</code> is not needed for a single action, at all. The Haskell "Hello world" is simply:
<syntaxhighlight lang="haskell">
main = putStrLn "Hello world!"
</syntaxhighlight>
Snippets like this one are totally redundant:
<syntaxhighlight lang="haskell">
fooRedundant = do { x <- bar
; return x }
</syntaxhighlight>
Thanks to the [[Haskell/Monads#Monad_Laws|monad laws]], we can write it simply as
<syntaxhighlight lang="haskell">
foo = do { bar } -- which is, further,
foo = bar
</syntaxhighlight>
A subtle but crucial point relates to function composition: As we already know, the <code>greetAndSeeYou</code> action in the section just above could be rewritten as:
<syntaxhighlight lang="haskell">
greetAndSeeYou :: IO ()
greetAndSeeYou = nameReturn >>= (\ name -> putStrLn ("See you, " ++ name ++ "!"))
</syntaxhighlight>
While you might find the lambda a little unsightly, suppose we had a <code>printSeeYou</code> function defined elsewhere:
<syntaxhighlight lang="haskell">
printSeeYou :: String -> IO ()
printSeeYou name = putStrLn ("See you, " ++ name ++ "!")
</syntaxhighlight>
Now, we can have a clean function definition with neither lambdas or <code>do</code>:
<syntaxhighlight lang="haskell">
greetAndSeeYou :: IO ()
greetAndSeeYou = nameReturn >>= printSeeYou
</syntaxhighlight>
Or, if we have a ''non-monadic'' <code>seeYou</code> function:
<syntaxhighlight lang="haskell">
seeYou :: String -> String
seeYou name = "See you, " ++ name ++ "!"
</syntaxhighlight>
Then we can write:
<syntaxhighlight lang="haskell">
-- Reminder: fmap f m == m >>= (return . f) == liftM f m
greetAndSeeYou :: IO ()
greetAndSeeYou = fmap seeYou nameReturn >>= putStrLn
</syntaxhighlight>
Keep this last example with <code>fmap</code> in mind; we will soon return to using non-monadic functions in monadic code, and <code>fmap</code> will be useful there.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Monads|noexercises=1}}
{{BookCat}}
ehbefcvxnz8mpf4ki49bz0clkmsjyqs
Aros/Developer/Docs/Rexx
0
223927
4675816
4664390
2026-10-13T12:26:19Z
Jeff1138
301139
4675816
wikitext
text/x-wiki
{{ArosNav}}
==Introduction==
Is REXXC = "AREXX". AROS includes REXXMAST where the program register the arexx ports, that can be used from any scripting language that supports it, not just AREXX. AREXX is not compatible integrated, there were improvements in certain areas but it includes regina, that is implementing a relative updated REXX version. But AREXX is not only older but includes extensions and changes not in the original REXX. So yes but not 100%
For example, in SYS:Extras/Rexx/Progs rx <prg>.r runs the script
==Arexx==
A scripting language for processing text and files.
A script is just a plain text file.
rx script.rexx
Copyrighted (William S. Hawes) extension to Rexx from IBM
[http://en.wikipedia.org/wiki/ARexx ARexx] is a scripting language and although you can use it to launch applications, you're better off using a regular DOS script for that, if it's required.
ARexx is far more powerful than DOS, but isn't really intended as a replacement. ARexx's principal strength is that it allows you to write scripts that can talk to "hosts"; that is, any application that has an ARexx port. This allows ARexx to control the application (within the limits of what features it exposes to ARexx). As a single script can communicate with multiple hosts, it can coordinate activity between applications. Any command it doesn't understand, it forwards to the currently selected host. By default, the host is the shell itself.
You invoke CALL searching for a function from a library (according to the documentation in this search order):
1) Internal functions
2) Built-in functions
3) Function libraries and Function Hosts
4) External AREXX programs - forward the Msg to the AREXX process itself and scan for files loaded
There are three different 'modes':
- ARexx command host
- function host
- function library
==Tutorial==
<syntaxhighlight lang="rexx">
/* A simple program */
say 'Hello World'
</syntaxhighlight>
===Looping===
The DO control structure always begins with a DO and ends with an END.
DO UNTIL:
DO UNTIL [condition]
[instructions]
END
DO WHILE:
DO WHILE [condition is true]
[instructions]
END
Stepping through a variable:
DO i = x TO y BY z
[instructions]
END
Looping forever until exiting with LEAVE - BREAK has other possibilities, but you probably want LEAVE:
DO FOREVER
IF [condition] THEN LEAVE
END
Looping a fixed number of times
DO i = x TO y BY z FOR a
[instructions]
END
===Conditionals===
IF [condition] THEN
[instruction]
ELSE
[instruction]
Testing for multiple conditions
SELECT
WHEN [condition] THEN
DO
[instruction]
END
OTHERWISE
DO
[instruction] or NOP
END
NOP indicates no instruction is to be executed.
===Variables===
There is a command that looks if a var is a integer or not... DATATYPE(WHOLE)
=== Command and Function ===
Rexx makes difference between commands and functions. With ADDRESS you indicate a place to send a command to. Commands are always one line. Functions have to be in a library with ARexx support and be added with addlib. You seem to want function syntax but are using command port.
Changes the way that arguments passed on the command line are made available to the called Rexx program. With this switch each parameter on the command line is available as a separate argument, rather then the normal behaviour of only making the combined command line arguments available as one internal argument.
It seems indeed that 'command'-mode is not to receive more than 1 argument (arg[0]).
===PARSE===
The PARSE instruction is particularly powerful; it combines some useful string-handling functions
parse [upper] origin template
where origin specifies the source:
* arg (command line variable)
* linein (keyboard)
* pull (REXX data queue)
* value (a literal or a function) '''with''' required to indicate where the literal ends
* var (a variable)
* version (version/release number)
and template can be:
* list of variables
* column number delimiters
* literal delimiters
upper is optional; it you specify it, data will be converted to upper case.
use 'PARSE PULL var' if you don't want the input to be uppercased. 'PULL var' is the same as 'PARSE UPPER PULL var'
Examples:
Using a list of variables as template
myVar = "John Smith"
parse var MyVar firstName lastName
say "First name is:" firstName
say "Last name is:" lastName
displays the following
First name is: John
Last name is: Smith
Using a delimiter as template:
myVar = "Smith, John"
parse var MyVar LastName "," FirstName
say "First name is:" firstName
say "Last name is:" lastName
also displays the following
First name is: John
Last name is: Smith
Using column number delimiters:
myVar = "(202) 123-1234"
parse var MyVar 2 AreaCode 5 7 SubNumber
say "Area code is:" AreaCode
say "Subscriber number is:" SubNumber
displays the following
Area code is: 202
Subscriber number is: 123-1234
A template can use a combination of variables, literal delimiters, and column number delimiters.
===Advanced Data Structures===
<pre>
array(var, var)
</pre>
<pre>
record.field1
record.field2
</pre>
<pre>
/* check if a library function is available */
SHOW (L, 'rexxsupport.library')
/* if function not available - add library*/
ADDLIB ('rexxsupport.library',0,-30,0)
/* SHOWDIR (directory, {mode), [pad]) */
SHOWDIR ('sys:')
/* if function - remove library*/
REMLIB ('rexxsupport.library')
</pre>
parse arg height, width, depth
PROCEDURE EXPOSE WORD
You can pass a whole stem to a function declared in THE SAME script via the "PROCEDURE EXPOSE" statement, e.g.
<pre>
...
test: procedure expose stem.
say stem.1 stem.a stem.a.ciao
...
</pre>
(take care to put the '.' or just the stem var will be visible to the function 'test', not the all stem.
Any modificiation to 'stem.' will be global. There is no way to pass a stem to an external function
ARexx will also search for the function in a file with the same name as it and as <name>.rexx), both in current dir and REXX:. Don't put .rexx on my files, as ~(*:*) matches functions, *.rexx ordinary scripts, *.ced ...
===File Manipulation===
<pre>
/* Create a file */
if open('file', 'ram:test', 'w') then
call writeln('file' 'data')
call close('file')
else
say 'unable to open'
</pre>
<pre>
/* Read a file */
if open('file', 'ram:test', 'r') then
call readch('file' var) /* read first var characters */
do while ~eof('file')
say line
line=readln('file') /* read next line */
end
call close('file')
</pre>
<pre>
/* Read a file */
if open('file', 'ram:test', 'a') then
say 'it is here'
else
say 'it is not here'
</pre>
position = seek ('file', var, string) /* var is +/- bytes from start and string can be b, c or e */
<pre>
IBM EOL (end of line) = <CR><LF> or (^M^J)
Amiga/UNIX EOL = <LF> or (^J)
Macintosh EOL = <CR> or (^M)
</pre>
<pre>
IBM EOF = <EOL><CTRL-Z> or (^M^J^Z)
Amiga EOF = <NULL> or (), optionally <LF> or (^J)
</pre>
Null, of course, is the absence of any data.
IBM text editors do a <CR><LF> at each <RETURN>. Most Amiga software, AFAIK, only does <LF> and the end of the file is simply indicated when there are no more bytes to be read.
The ARexx EOF() indicates when you've run out of stuff to read from a file. It does not (to my knowledge) look around for whatever the IBM thinks signifies the end of a file on top of simply noticing when the file has reached its end of capacity (say you have a 1024-byte file, after reading 1024 bytes you will have reached the end of the file, or EOF).
<code>
do UNTILEF("FILE")
/* Do some reading here or something */
end
</code>
Change "call readch('rfile',1)" into "say c2d(readch('rfile',1))" to display the "ascii" code. (Note that only charcodes < 127 is ASCII)
===Debugging===
Syntax, loop errors, etc.
Trace
Signal
===Program IPC===
rx "address command Dir"
Talking to DOS,
address "program-name"
You can get the ARexx commands of any MUI program with the HELP command. Here is an example for IBrowse.
<pre>
/* CheckIB.rexx*/
address IBrowse
'HELP vd0:IB.txt'
</pre>
The drive specification after the HELP command is the drive and file name for the output. Of course, the program you are checking must be running so the port is available. The output will show the standard ARexx commands that every MUI program has followed by the commands specific to the particular program being checked.
===Hooks===
Normally you would provide a commandlist with your application and those command would 'automatically' be processed by the hooks installed.
It's when you use commands that does not get 'processed automatically' (because they are not in the commandlist) you need to make use of the functionality you presented (like MUIA_Application_RexxHook).
Since those attributes does not seem to be in place, you would need to fallback to the ordinairy way of doing things, meaning you would somehow 'invent' how to 'sync' your normal commands with the arexx commands
==References==
*[http://web.archive.org/web/20020405121853/http://www.halcyon.com/robin/www/arexxguide/main.html ARexx guide] (last updated jun-1995)
*[http://web.archive.org/web/20060114052122/http://members.cox.net/midian/tutorials/arexx1.htm Beginning ARexx]
*[http://web.archive.org/web/20060114050816/http://members.cox.net/midian/tutorials/arexx2.htm Loops and Conditionals]
*[http://aminet.net/util/rexx Aminet Guides]
*[http://aminet.net/search?query=reference+arexx Arexx references (in AmigaGuide)]
Regina 3.00
===Instructions===
<pre>
CALL {symbol | string} [expression] [,expression,...]
DO [var=exp] [To exp] [BY exp]] [FOR exp] [FOREVER] [WHILE exp | UNTIL exp]
DROP variable [variable...]
ELSE [;] [conditional statement]
END [variable]
EXIT [expression]
IF expression [THEN] [;] [conditional statement]
INTERPRET expression
ITERATE [variable]
LEAVE [variable]
NOP
NUMERIC {DIGITS | FUZZ} expression or: NUMERIC FORM {SCIENTIFIC | ENGINEERING}
OPTIONS [FAILAT expression] or: OPTIONS [PROMPT expression] or: OPTIONS [RESULTS]
OTHERWISE [;] [conditional statement]
PARSE [UPPER] inputsorce [template] [,template...]
PROCEDURE [EXPOSE variable [variable...]]
PULL [template] [,template...]
PUSH [expression]
QUEUE [expression]
RETURN
SAY [expression]
SELECT
SHELL [symbol | string] [expression]
SIGNAL {ON |OFF} condition or: SIGNAL [VALUE] expression
THEN[;] [conditional statement]
TRACE [symbol|string|[[VALUE] expression]]
UPPER variable [variable...]
WHEN expression [THEN [;] [conditional statement]]
</pre>
===Functions===
<pre>
ABBREV
ABS
ADDLIB
ADDRESS [Symbol|string|VALUE] [expression]]
ALLOCATED
ARG [template] [,template...]
B2C
B2X
BEEP
BITAND
BITCHG
BITCLR
BITCOMP
BITOR
BITSET
BITTST
BITXOR
BUFTYPE
C2B
C2D
C2X
CD
CENTER
CENTRE
CHANGESTR
CHARIN
CHAROUT
CHARS
CHDIR
CLOSE
COMPARE
COMPRESS
CONDITION
COPIES
COUNTSTR
CRYPT
D2C
D2X
DATATYPE
DATE
DELSTR
DELWORD
DESBUF
DIGITS
DIRECTORY
DROPBUF
DUMPFILES
DUMPTREE
DUMPVARS
EOF
ERRORTEXT
EXISTS
EXPORT
FREELISTS
FREESPACE
FUZZ
GETCLIP
GETENV
GETPATH
GETPID
GETSPACE
GETTID
HASH
IMPORT
INDEX
INSERT
JUSTIFY
LASTPOS
LEFT
LENGTH
LINEIN
LINEOUT
LINES
LISTLEAKED
MAKEBUF
MAX
MEMORYSTATS
MIN
OPEN
OVERLAY
POPEN
POS
PRAGMA
QUALIFY
QUEUED
RANDOM
RANDU
READCH
READLN
REMLIB
REVERSE
RIGHT
RXFUNCADD
RXFUNCDROP
RXFUNCERRMSG
RXFUNCQUERY
RXQUEUE
SEEK
SETCLIP
SHOW
SIGN
SLEEP
SOURCELINE
SPACE
STATE
STREAM
STRIP
STORAGE
SUBSTR
SUBWORD
SYMBOL
TIME
TRACE
TRIM
TRACEBACK
TRANSLATE
TRUNC
UNAME
UNIXERROR
UPPER
USERID
VALUE
VERIFY
WORD
WORDINDEX
WORDLENGTH
WORDPOS
WORDS
WRITECH
WRITELN
X2B
X2C
X2D
XRANGE
</pre>
===Operators===
<pre>
OPERATOR PRIORITY OPERATOR DEFINITION
~ 8 Logical NOT
+ 8 Prefix Conversion
- 8 Prefix Negation
** 7 Exponentiation
* 6 Multiplication
/ 6 Division
% 6 Integer Division
// 6 Remainder
+ 5 Addition
- 5 Subtraction
|| 4 Concatenation
(blank) 4 Blank Concatenation
== 3 Exact Equality
~== 3 Exact Inequality
= 3 Equality
~= 3 Inequality
> 3 Greater Than
>=,~< 3 Greater Than or Equal To
< 3 Less Than
<=,~> 3 Less Than or Equal To
& 2 Logical AND
| 1 Logical Inclusive OR
^,&& 1 Logical Exclusive OR
</pre>
===RexxSupport===
<pre>
LONG rxsupp_allocmem(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_baddr(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_closeport(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_delay(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_delete(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_forbid(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_freemem(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_getarg(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_getpkt(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_makedir(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_next(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_null(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_offset(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_openport(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_permit(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_rename(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_reply(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_showdir(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_showlist(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_statef(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_typepkt(struct Library *, struct RexxMsg *, UBYTE **);
LONG rxsupp_waitpkt(struct Library *, struct RexxMsg *, UBYTE **);
</pre>
===RexxSyslib===
<pre>
UBYTE *CreateArgstring(UBYTE *string, ULONG length) (A0, D0)
void DeleteArgstring(UBYTE *argstring) (A0)
ULONG LengthArgstring(UBYTE *argstring) (A0)
struct RexxMsg *CreateRexxMsg(struct MsgPort *port, UBYTE *extension, UBYTE *host) (A0, A1, D0)
void DeleteRexxMsg(struct RexxMsg *packet) (A0)
void ClearRexxMsg(struct RexxMsg *msgptr, ULONG count) (A0, D0)
BOOL FillRexxMsg(struct RexxMsg *msgptr, ULONG count, ULONG mask) (A0, D0, D1)
BOOL IsRexxMsg(struct RexxMsg *msgptr) (A0)
void LockRexxBase(ULONG resource) (D0)
void UnlockRexxBase(ULONG resource) (D0)
</pre>
==Adding Regina/Rexx to Programs==
http://aminet.net/search?query=Minrexx
http://www.pcguru.plus.com/tutorial/introduction.html
It's really easy to set up your own Rexx port. It's just a standard MsgPort. If you are just going to exit on any message and not parse commands sent to the port then you don't even need to open rexxsyslib.library...
<pre>
struct MsgPort *CreatePubPort (UBYTE *name, LONG pri)
/* create a port if port name is not already used */
{
struct MsgPort *pubport;
port = NULL;
Forbid ();
if (FindPort (name) == NULL)
pubport = CreateMsgPort (name, pri);
Permit ();
return (pubport);
}
</pre>
Now that the port is created we just need to wait for a message.
<pre>
static void PubPortWait (struct MsgPort *pubport)
/* wait for a message or signal on our pubport */
{
ULONG port_mask, signals;
struct RexxMsg *msg;
port_mask = (1L << RexxPort->mp_SigBit);
while (1)
{
signals = Wait (port_mask | SIGBREAKF_CTRL_C);
if (signals & SIGBREAKF_CTRL_C)
Quit("Aborting");
if (signals & port_mask)
{
while ((msg = (struct RexxMsg *) GetMsg (pubport)) != NULL)
{
ProcessRexxMsg (msg); /* routine parses the REXX message */
ReplyMsg ((struct Message *) msg);
}
}
}
}
</pre>
ProcessRexxMsg() can print your message and exit but remember to ReplyMsg(). If you want to parse the Arexx commands, it's not much more work. The above is pulled from a longer printed code example and uses some REXX includes from "arexx.h" and "arexxsyslib.h" but it should NOT be necessary to open rexxsyslib.library if you will exit on any message received at your port.
http://utilitybase.com/forum/index.php?action=vthread&forum=15&topic=1915
<pre>/*
#include <proto/exec.h>
#include <proto/alib.h>
#include <proto/rexxsyslib.h>
#include <exec/ports.h>
#include <rexx/errors.h>
#include <rexx/storage.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
struct MsgPort *port;
struct RexxMsg *msg;
struct Library *RexxSysBase;
char *value;
RexxSysBase = OpenLibrary("rexxsyslib.library", 0);
if (RexxSysBase == NULL)
{
puts("Error opening rexxsyslib.library");
return 20;
}
port = CreatePort("VARTEST", 1);
if (port == NULL)
{
puts("Error creating port");
CloseLibrary(RexxSysBase);
return 20;
}
printf("Port created %x, waiting for message\n", port);
WaitPort(port);
msg = (struct RexxMsg *)GetMsg(port);
puts("Got a message");
if (!IsRexxMsg(msg))
{
puts("Message is not a rexxmsg");
ReplyMsg((struct Message *)msg);
DeletePort(port);
CloseLibrary(RexxSysBase);
return 20;
}
puts("Is a rexx message");
if (!CheckRexxMsg(msg))
{
puts("Message is not from rexx interpreter");
msg->rm_Result1 = RC_ERROR;
ReplyMsg((struct Message *)msg);
DeletePort(port);
CloseLibrary(RexxSysBase);
return 20;
}
puts("Message is from the rexx interpreter");
if (!GetRexxVar(msg, "A", &value))
{
puts("Error during retrieval of value");
return 20;
}
printf("Length string: %d\n", strlen(value));
printf("Value of A: %s\n", value);
SetRexxVar(msg, "A", "2", 1);
msg->rm_Result1 = RC_OK;
msg->rm_Result2 = NULL;
ReplyMsg((struct Message *)msg);
DeletePort(port);
CloseLibrary(RexxSysBase);
return 0;
}
</pre>
You can now send a message to this little program with the following script:
<pre>
/* Testing the variable interface */
a = 1
say 'a before call' a
ADDRESS 'VARTEST' test
say 'a after call' a
</pre>
Save it as (example) 'vartest.rexx' and run it with:
<pre>
rx vartest.rexx
</pre>
==Example script==
[http://aminet.net/util/rexx For More Examples]
<pre>
/* Calculate some squares and cubes */
do i = 1 to 10 /* 10 interations */
say i i**2 i**3 /* calculations */
end
say ' all done '
</pre>
<pre>
/* Even or odd? */
do i = 1 to 10
if i//2 = 0 then type = 'even'
else type = 'odd'
say i 'is' type
end
</pre>
<pre>
/* Defining and calling a function */
do i = 1 to 5
say i square(i) /* call square */
end
exit /* all done */
square: /* function name */
arg x /* get the "argument" */
return x**2 /* square it and return*/
</pre>
<pre>
/* Demonstrate "results" tracing */
trace results
sum=0;sumsq=0;
do i = 1 to 5
sum = sum + i
sumsq = sumsq + i**2
end
say 'sum=' sum 'sumsq=' sumsq
</pre>
<pre>
/* Calculate age in days */
say 'Please enter your age'
pull age
say 'You are about' age*365 'days old'
</pre>
<pre>
DO .... ; you have the code already
line = READLN(textfile)
IF line = marker line THEN DO
target = READLN(textfile)
END
END
</pre>
<pre>
/* File to read */
IF ~OPEN("in", "Path:yourTextFile", "READ") THEN DO
SAY "Can't open 'Path:yourTextFile' for reading."
CALL CLOSE('in')
EXIT
END
/* File to write */
IF ~OPEN("out", "Ram:filename", "WRITE") THEN DO
SAY "Can't open 'Ram:filename' for writing."
CALL CLOSE('out')
EXIT
END
/* Write lines that start with "(" to Ram:filename */
DO UNTIL EOF('in')
line = READLN('in')
temp = STRIP(line, 'L')
IF LEFT(temp, 1) = '(' THEN CALL WRITELN('out', line)
END
</pre>
<pre>
/* */
options results
arg sourcefile
if open(input, sourcefile, R) then do
if ~open(output, "ram:output", W) then call error
Do until eof(input)
line=readln(input)
if pos('(',line)=1 then writeln(output,line) /* line begins with '(' at POS 1 */
end
close(input)
close(output)
end
EXIT
/* function */
ERROR:
SAY "ERROR"
EXIT
</pre>
<pre>
/*Bin2AHex*/
/* Convert a binary file to a ASCII representation of Hex.*/
if ~open('bufbin', 'RAM:buffer.bin', 'READ') then do
say "Can't open 'RAM:buffer.bin' for reading."
exit
end
if ~open('buftxt', 'RAM:buffer.txt','WRITE') then do
say "Can't open 'RAM:buffer.txt' for writing."
exit
end
/* 500 seems do be the max for c2x() */
max = 500
in = readch('bufbin', max)
DO until eof('bufbin')
call writech('buftxt',c2x(in))
in = readch('bufbin', max)
END
call close('bufbin')
call close('buftxt')
/* That's All Folks! */
</pre>
<pre>
/* Here's a more visible way to enter the control codes */
CSI='9b'x /* control sequence introducer */
boldOn=CSI'1m'
boldOff=CSI'22m'
</pre>
<pre>
IF OPEN("Env", "Env:File", "R") THEN DO
filename = READLN("Env")
CALL CLOSE("Env")
END
</pre>
<pre>
/* OPEN alone will pop up a filerequester */
OPEN NAME <filename>
</pre>
<pre>
/* Displays the data in the source string */
parse source source /* type results called resolved extension host */
words=words(source)
shell command 'RequestChoice >Nil: Source',
'"Invocation type:' word(source,1)'*n',
||'Result requested:' word(source,2)'*n',
||'Called name:' word(source,3)'*n',
||'Resolved name:' DelWord(trim(DelWord(source,words-1)),1,3)'*n',
||'Search extension:' word(source,words-1)'*n',
||'Initial command host:' word(source,words)'"',
'OK'
</pre>
<pre>
/* Grabs the Users Hz thus the tick rate per second of the persons machine
(either 50 or 60 generally) amd pouts it into variable 'f' */
PARSE UPPER VERSION f
f=SUBSTR(WORD(f,6),1,2)
DO UNTIL <expression is valid> | i=<value ya want>
/* Call a delay and do nothing for value times(*) variable 'f' */
Call Delay(1*f)
i=i+1
End
</pre>
You can do it so it makes a value true or tries indefinitely. otherwise you can make it leave the loop using a 'Leave' command at any stage of the DO UNTIL part.
So the below loading libs works well...
<pre>
libs = "rexxreqtools.library rexxdossupport.library rexxkuang11.library
rexxsupport.library rexxtricks.library"
DO UNTIL libs='';PARSE VAR libs lib libs
IF EXISTS('libs:'lib)|EXISTS('Libs/'lib)|EXISTS(lib) THEN DO
IF ~show('L',lib) THEN call addlib(lib,0,-30,0);END;ELSE DO
/* error output line whether say or echo or defined */
cECHO('Cannot load 'lib);END;END
</pre>
find what number every key has, this can be in ARexx...
<pre>
rx <RAW: "
do while 1;
z=readch(stdin,1);
c=c2d(z);
if c2d(bitand('7f'x,z)) < 33 then
z='<'c'>';
call writech(stdout,z);
end
</pre>
(All on one line)
CTRL-C will stop this thing. Note here that the above and RAW-KEY Intui-messages (OpenWindow()/intuition,
IDCMP flags) are about the only easy and *system legal* way to obtain information about keys pressed.
This will extract the filename extension (such as .lha or .8svx) along with its length. It can be useful, when renaming files. Used it in a conversion script, that can convert different file- types, so archive.lha gets archive.lzx and pic.gif gets pic.png.
<pre>
STRING = ExtPart(filename)
PARSE VAR string extlen ext
</pre>
<pre>
/* ExtPart(filename)
** Returns filename extension and length of extension
** freely usable, freely distributable, intellectual property:
** Andreas Mixich <humpty@...>
*/
PARSE ARG filename
posi = LastPos('.',filename)
ext = SubStr(filename,(posi+1))
extlen = Length(SubStr(filename,posi))-1
extpartinfo = extlen||' '||ext
RETURN(extpartinfo)
</pre>
This one makes a valid path, which is better to use. No more RAM:Envfilename mistake, but RAM:Env/filename
Additional it makes RAM: out of Ram Disk:
Nothing special, though, you can achieve the same result (except for RAM:<-Ram Disk:) by using rexxdossupport.library/AddPart(pathname,"") - Do not forget the "".
<pre>
STRING = ValPath("sys:Tools")
</pre>
<pre>
/* ValPath()
** make a vaild path out of path (in case it lacks '/')
** Concentrates "Ram Disk:" to "Ram:", so we get rid of this annoying space
** Freely usabel, freely distributable, intellectual property of
** Andreas Mixich <humpty@...>
*/
valpath:
PARSE ARG path
IF (LastPos('/',path) ~= Length(path) & Pos('/',path) ~= 0) THEN
path = path||'/'
ELSE
IF (LastPos(':',path) ~= Length(path) & Pos('/',path) = 0) THEN
path = path||'/'
IF Left(path,9) = "Ram Disk:" THEN
path = Insert("Ram",DelStr(path,1,8))
RETURN(path)
</pre>
this little sub-routine used in all my ARexx scripts, that need external ports to be available. (WaitForPort)
Since not liking to write the same lines in any script, just select this routine from a GoldED list requester and it is appended to my source. The function is simple:
<pre>
BOOL = IfPort(portname, prog, mode)
</pre>
portname is the ARexx-port name of the application,
prog is the full path to the application, in case it needs to be launched mode can be either empty or WB. If WB is used it will be started with WBRun. Sometimes this is quite useful.
The function results in a BOOL (either TRUE or FALSE) so it is easy to handle flow control.
In this routine you will find another function I use:
myERR()
You can replace it by anything you want or just take it away. Use such general routines, because they are more powerful, so could have some logging in myERR() or WB requesters or whatever.
<pre>
/*///------------------------------ "IfPort(portname,prog,mode)" ------------------------------ */
/*
** IfPort(portname, prog, mode)
** Shows if portname is available, attempts to launch program if not
** Freely usable, freely distributable, intellectual properties:
** Andreas Mixich <humpty@...>
*/
ifport:
PARSE ARG portname, prog, mode
IF ~Show(P,portname) THEN
DO
IF mode = WB THEN
ADDRESS COMMAND wbrun||' >NIL: '||prog
ELSE
ADDRESS COMMAND 'run >NIL: '||prog
ADDRESS COMMAND 'WaitForPort '||portname
IF RC ~= 0 THEN
DO
Call myERR('Error: Could not start '||prog)
RETURN(FALSE)
END
ELSE
RETURN(TRUE)
END
RETURN(TRUE)
/*\\\*/
</pre>
Here ya go, the fastest SQRT function in Rexx I have seen yet, found in c.l.rexx
<pre>
/* */
parse arg N
if N <= 0 then exit
s = time('e')
call MethodB(N)
say time('e') - s
exit
</pre>
<pre>
MethodB:
x1 = 1
x0 = N
if N ~= 0 then
do until x1 = x0
x0 = x1
x1 = ((x0 * x0) + N) / (2 * x0)
end
else x1 = 0
say x1
return
</pre>
a very simple one, seldomly used, but given as some example of the Translate() function to newbies and to make the function set a bit more complete. (Since there is an Upper() why shouldn't be there also a Lower())
<pre>
/*
** Lower()
** Like Upper(), but this one makes a string lowercase.
** Considers german unmlauts and some accents.
** TODO: Add more national characters. Do you know of any missing
** (and where to find them on the keyboard) ?
*/
Lower: PROCEDURE
PARSE ARG string
res =
Translate(string,'abcdefghijklmnopqrstuvwxyzäöüáéíóú','ABCDEFGHIJKLMNOPQRSTUVWXY\
ZÄÖÜÁÉÍÓÚ')
RETURN(res)
</pre>
<pre>
/* convert a file into sentences */
arg fileid .
input=''
do until LINES(fileid)=0
in=LINEIN(fileid)
input=input in
end
t=LINEOUT("sentence.txt","--- "fileid" ---")
out=''
do i=1 to LENGTH(input)
char=SUBSTR(input,i,1)
out=out||char
if char="." then do
out=STRIP(SPACE(out))
t=LINEOUT("sentence.txt",out)
out=''
end
end
out=STRIP(SPACE(out))
t=LINEOUT("sentence.txt",out)
exit
</pre>
Suggest that when you open files you do something more like this to check that it was opened successfully:
<pre>
if open(tempfile,'t:ms_scenes',w) then do
call writeln(tempfile,'SCENE1')
/* blah, blah... */
call close(file)
end
else do
say 'Unable to open temp file!'
exit
end
</pre>
Get the file size
<pre>
/* */
parse arg file
if file="" then do
say "no file given"
exit
end
s=statef(file)
if s="" then do
say "can't find file '"file"'"
exit
end
parse var s type size d d d d d comment
if type~="FILE" then do
say "'"file"' is not a valid file name"
exit
end
say "file '"file"':" size
</pre>
{{Subjects|Scripting languages}}
bab89r3l06lz9fh1pzhet9m7qjy2yii
Radiation Oncology/Rectum/Guidelines
0
224015
4675993
2023932
2026-10-14T09:19:31Z
Jcb
90773
4675993
wikitext
text/x-wiki
{{:Radiation_Oncology:TOC}}
<big>'''Rectal Cancer Official Guidelines'''</big>
'''''Screening'''''
*'''ACS:''' Colorectal Cancer: Early Detection
**[http://www.cancer.org/docroot/CRI/content/CRI_2_6X_Colorectal_Cancer_Early_Detection_10.asp?sitearea=&level= Guideline link]
*'''Joint Consensus Guideline:''' Screening and Surveillance for the Early Detection of Colorectal Cancer and Adenomatous Polyps
**From ACS, ACR, and US Multi-Society Task Force
**'''2008''' [http://www.gastrojournal.org/article/S0016-5085%2808%2900232-1/fulltext#sec4.1.2 Guideline link] {{PMID|18384785}}
'''''Tumor Markers'''''
*'''ASCO:''' Use of Tumor Markers in GI Malignancies
**'''2006''' [http://jco.ascopubs.org/cgi/reprint/24/33/5313 Guideline link] {{PMID|17060676}} -- "ASCO 2006 update of recommendations for the use of tumor markers in gastrointestinal cancer." (Locker GY, J Clin Oncol. 2006 Nov 20;24(33):5313-27.)
'''''Treatment'''''
*'''ACR:''' Local Excision in Early Stage Rectal Cancer
**[http://www.acr.org/SecondaryMainMenuCategories/quality_safety/app_criteria/pdf/ExpertPanelonRadiationOncologyRectalAnalWorkGroup/LocallyUnresectableRectalCancerUpdateinProgressDoc2.aspx Guideline link]
*'''ACR:''' Rectal Cancer—Metastatic Disease at Presentation
**[http://www.acr.org/SecondaryMainMenuCategories/quality_safety/app_criteria/pdf/ExpertPanelonRadiationOncologyRectalAnalWorkGroup/RectalCancerMetastaticandLocallyAdvancedDiseaseUpdateinProgressDoc3.aspx Guideline link]
*'''ACR:''' Recurrent Rectal Cancer
**[http://www.acr.org/SecondaryMainMenuCategories/quality_safety/app_criteria/pdf/ExpertPanelonRadiationOncologyRectalAnalWorkGroup/RecurrentRectalCancerUpdateinProgress.aspx Guideline link]
*'''ACR:''' Resectable Rectal Cancer
**[http://www.acr.org/SecondaryMainMenuCategories/quality_safety/app_criteria/pdf/ExpertPanelonRadiationOncologyRectalAnalWorkGroup/ResectableRectalCancerUpdateinProgressDoc4.aspx Guideline link]
'''''Contouring Guidelines'''''
*'''RTOG Atlas'''
**[http://www.rtog.org/pdf_file2.html?pdf_document=AnorectalContouringGuidelines.pdf RTOG Anorectal Contouring Guidelines]
**'''2009''' {{PMID|19117696}} -- "Elective clinical target volumes for conformal therapy in anorectal cancer: a radiation therapy oncology group consensus panel contouring atlas." (Myerson RJ, Int J Radiat Oncol Biol Phys. 2009 Jul 1;74(3):824-30. Epub 2008 Dec 29.)
**'''2011''' {{PMID|20400244}} -- "Prospective randomized double-blind pilot study of site-specific consensus atlas implementation for rectal cancer target volume delineation in the cooperative group setting." (Fuller CD, Int J Radiat Oncol Biol Phys. 2011 Feb 1;79(2):481-9. Epub 2010 Apr 18.)
***Randomized. 1 rectal case, 14 physicians and one reference expert countouring. Arm 1) consensus guideline vs Arm 2) no consensus guideline. Two contours, pre- and post.
***Outcome: Greater agreement for GTV (0.75) than for CTVs (0.46 - 0.65). For consensus guideline group, only improvement after reviewing atlas was for CTVA, no impact on GTV and CTVB contours
***Conclusion: Visual atlas inclusion should be considered in clinical trials
gunoo4aam7ho1qsej8xxk0peg6fv2xy
Template:In use/doc
10
224892
4675988
4674645
2026-10-14T06:14:05Z
Gshfgh
3628029
4675988
wikitext
text/x-wiki
{{delete|merged into template}}{{Documentation subpage}}
<!-- EDIT TEMPLATE DOCUMENTATION BELOW THIS LINE -->
=== Usage ===
This template is for pages actively undergoing a major edit. If the page instead is actively undergoing construction, please use {{tl|under construction}}.
The '''In use''' template message is placed at the top of a page you are actively editing for a short period of time. The tag is intended to inform people that someone is currently working on the article, thereby reducing edit conflicts. Please do not leave it in place for more than the few hours at most that should be necessary, as doing so may unnecessarily discourage others from contributing to the page. If it has been up for more than two hours since the last edit, it should be removed. Specifying periods of several days or longer for this template goes against the spirit of simply avoiding edit conflicts; please only use it for sessions where you are actively editing the page.
If you wish to indicate that a page is being rebuilt over a longer period of time consider the {{Tl|under construction}} template. That template encourages others to edit the page while indicating that it is a work in progress.
To use, just add <code><nowiki>{{in use|time=~~~~~}}</nowiki></code> at the top of the page you want to work on. If you want to reserve it for a specific length of time and optionally, a message, use <code><nowiki>{{in use|time (message)}}</nowiki></code>. Alternatively, if only one section of the page is being edited, you may place this template at the top of that section using <code><nowiki>{{in use|section}}</nowiki></code>. '''Please remember to remove the ''in use'' note''' as soon as you're finished editing.
=== Examples ===
<code><nowiki>{{In use}}</nowiki></code>
{{In use}}
<code><nowiki>{{In use|section}}</nowiki></code>
{{In use|section}}
<code><nowiki>{{In use|5 minutes}}</nowiki></code>
{{In use|5 minutes}}
<code><nowiki>{{In use|30 minutes to fix the information in the History section|time=20:49, 27 February 2009 (UTC)}}</nowiki></code>
{{In use|30 minutes to fix the information in the History section|time=20:49, 27 February 2009 (UTC)}}
== See also ==
* {{tl|under construction}} for books actively undergoing construction
* {{tl|new book}} for newly created books still under construction
<includeonly>
<!-- ADD CATEGORIES BELOW THIS LINE -->
[[ka:თარგი:მუშავდება]]
[[Category:Under-construction templates|{{PAGENAME}}]]
</includeonly>
ip5m9qkgihyw4y1z4v3t8jvvcozejo6
Haskell/Other data structures
0
226798
4676012
4666188
2026-10-14T11:03:38Z
Luciérnaga de conocimiento
3401314
4676012
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Intermediate Haskell|noexercises=1}}
In this chapter, we will work through examples of how the techniques we have studied thus far can be used to deal with more complex data types. In particular, we will see examples of ''recursive data structures'', which are data types that can contain values of the same type. Recursive data structures play a vital role in many programming techniques, and so even if you are not going to need defining a new one often (as opposed to using the ones available from the libraries) it is important to be aware of what they are and how they can be manipulated. Besides that, following closely the implementations in this chapter is a good exercise for your budding Haskell abilities.
{{body note|The Haskell library ecosystem provides a wealth of data structures (recursive and otherwise), covering a wide range of practical needs. Beyond lists, there are maps, sets, finite sequences and arrays, among many others. A good place to begin learning about the main ones is the [[Haskell/Libraries/Data structures primer|Data structures primer]] in the Haskell in Practice track. We recommend you to at least skim it once you finish the next few Intermediate Haskell chapters.}}
==Trees==
One of the most important types of recursive data structures is ''trees''. There are several different kinds of trees, so we will arbitrarily choose a simple one to use as an example. Here is its definition:
<syntaxhighlight lang="haskell">
data Tree a = Leaf a | Branch (Tree a) (Tree a)
</syntaxhighlight>
As you can see, it's parameterized; i.e. we can have trees of <code>Int</code>s, trees of <code>String</code>s, trees of <code>Maybe Int</code>s, trees of <code>(Int, String)</code> pairs and so forth. What makes this data type special is that <code>Tree</code> appears in the definition of itself. A <code>Tree a</code> is either a ''leaf'', containing a value of type <code>a</code> or a ''branch'', from which hang two other trees of type <code>Tree a</code>.
===Lists as Trees===
As we have seen in [[Haskell/Lists II|Lists II]] and [[Haskell/Lists III|Lists III]], we break lists down into two cases: An empty list (denoted by <code>[]</code>), and an element of the specified type plus another list (denoted by <code>(x:xs)</code>). That means the definition of the list data type might look like this:
<syntaxhighlight lang="haskell">
-- Pseudo-Haskell, will not actually work (because lists have special syntax).
data [a] = [] | (a:[a])
</syntaxhighlight>
An equivalent definition you can actually play with is:
<syntaxhighlight lang="haskell">
data List a = Nil | Cons a (List a)
</syntaxhighlight>
Like trees, lists are also recursive. For lists, the constructor functions are <code>[]</code> and <code>(:)</code>. They correspond to <code>Leaf</code> and <code>Branch</code> in the <code>Tree</code> definition above. That implies we can use <code>Leaf</code> and <code>Branch</code> for pattern matching just as we did with the empty list and the <code>(x:xs)</code>.
===Maps and Folds===
We already know about maps and folds for lists. Now, we can write map and fold functions for our new <code>Tree</code> type. To recap:
<syntaxhighlight lang="haskell">
data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving (Show)
data [a] = [] | (:) a [a]
-- (:) a [a] is the same as (a:[a]) with prefix instead of infix notation.
</syntaxhighlight>
{{body note|Deriving is explained later on in the section [[Haskell/Classes and types|Classes and types]]. For now, understand it as telling Haskell (and by extension your interpreter) how to display a Tree instance.}}
====Map====
Let's take a look at the definition of <code>map</code> for lists:
<syntaxhighlight lang="haskell">
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
</syntaxhighlight>
If we were to write <code>treeMap</code>, what would its type be? Defining the function is easier if you have an idea of what its type should be.
We want <code>treeMap</code> to work on a <code>Tree</code> of some type and return another <code>Tree</code> of some type by applying a function on each element of the tree.
<syntaxhighlight lang="haskell">
treeMap :: (a -> b) -> Tree a -> Tree b
</syntaxhighlight>
This is just like the list example.
Now, when talking about a <code>Tree</code>, each <code>Leaf</code> only contains a single value, so all we have to do is apply the given function to that value and then return a <code>Leaf</code> with the altered value:
<syntaxhighlight lang="haskell">
treeMap :: (a -> b) -> Tree a -> Tree b
treeMap f (Leaf x) = Leaf (f x)
</syntaxhighlight>
This looks a lot like the empty list case with <code>map</code>. Now, if we have a <code>Branch</code>, it will include two subtrees; what do we do with those? The list-<code>map</code> uses a call to itself on the tail of the list (recursion), so we also shall do that with the two subtrees. The complete definition of <code>treeMap</code> is as follows:
<syntaxhighlight lang="haskell">
treeMap :: (a -> b) -> Tree a -> Tree b
treeMap f (Leaf x) = Leaf (f x)
treeMap f (Branch left right) = Branch (treeMap f left) (treeMap f right)
</syntaxhighlight>
We can make this a bit more readable by noting that <code>treeMap f</code> is itself a function with type {{nowrap|<code>Tree a -> Tree b</code>}}. This gives us the following revised definition:
<syntaxhighlight lang="haskell">
treeMap :: (a -> b) -> Tree a -> Tree b
treeMap f = g where
g (Leaf x) = Leaf (f x)
g (Branch left right) = Branch (g left) (g right)
</syntaxhighlight>
If you didn't follow that immediately, try re-reading it. This use of pattern matching may seem weird at first, but it is essential to the use of datatypes. Remember that pattern matching happens on constructor functions.
When you're ready, read on for folds over Trees.
====Fold====
As with map, let's first review the definition of <code>foldr</code> for lists:
<syntaxhighlight lang="haskell">
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f acc [] = acc
foldr f acc (x:xs) = f x (foldr f acc xs)
</syntaxhighlight>
Recall that lists have two constructors:
<syntaxhighlight lang="haskell">
(:) :: a -> [a] -> [a] -- takes an element and combines it with the rest of the list
[] :: [a] -- the empty list takes zero arguments
</syntaxhighlight>
Thus <code>foldr</code> takes two arguments corresponding to the two constructors:
<syntaxhighlight lang="haskell">
f :: a -> b -> b -- a function takes two elements and operates on them to return a single result
acc :: b -- the accumulator defines what happens with the empty list
</syntaxhighlight>
Let's take a moment to make this clear. If the initial <code>foldr</code> is given an empty list, then the default accumulator is returned. With a non-empty list, the first element is combined (with <code>f</code>) with the result of folding the tail of the list, and so the fold proceeds until we get to the empty list.
Like <code>foldr</code> for lists, we want <code>treeFold</code> to transform a tree of some type into a value of some other type; so in place of {{nowrap|<code>[a] -> b</code>}} we will have {{nowrap|<code>Tree a -> b</code>}}. How do we specify the transformation? First note that {{nowrap|<code>Tree a</code>}} has two constructors (just like lists have two constructors):
<syntaxhighlight lang="haskell">
Branch :: Tree a -> Tree a -> Tree a
Leaf :: a -> Tree a
</syntaxhighlight>
So <code>treeFold</code> will have two arguments corresponding to the two constructors:
<syntaxhighlight lang="haskell">
fbranch :: b -> b -> b
fleaf :: a -> b
</syntaxhighlight>
Putting it all together we get the following type definition:
<syntaxhighlight lang="haskell">
treeFold :: (b -> b -> b) -> (a -> b) -> Tree a -> b
</syntaxhighlight>
That is, the first argument, of type {{nowrap|<code>(b -> b -> b)</code>}}, is a function specifying how to combine subtrees into a single result; the second argument, of type {{nowrap|<code>a -> b</code>}}, is a function specifying what to do with leaves (which are the end of recursion, just like empty-list for lists); and the third argument, of type <code>Tree a</code>, is the whole tree we want to fold.
As with <code>treeMap</code>, we'll avoid repeating the arguments <code>fbranch</code> and <code>fleaf</code> by introducing a local function <code>g</code>:
<syntaxhighlight lang="haskell">
treeFold :: (b -> b -> b) -> (a -> b) -> Tree a -> b
treeFold fbranch fleaf = g where
-- definition of g goes here
</syntaxhighlight>
The argument <code>fleaf</code> tells us what to do with <code>Leaf</code> subtrees:
<syntaxhighlight lang="haskell">
g (Leaf x) = fleaf x
</syntaxhighlight>
The argument <code>fbranch</code> tells us how to combine the results of "folding" two subtrees:
<syntaxhighlight lang="haskell">
g (Branch left right) = fbranch (g left) (g right)
</syntaxhighlight>
Our full definition becomes:
<syntaxhighlight lang="haskell">
treeFold :: (b -> b -> b) -> (a -> b) -> Tree a -> b
treeFold fbranch fleaf = g where
g (Leaf x) = fleaf x
g (Branch left right) = fbranch (g left) (g right)
</syntaxhighlight>
For examples of how these work, copy the <code>Tree</code> data definition and the <code>treeMap</code> and <code>treeFold</code> functions to a Haskell file, along with the following example Tree and example functions to fold over.
<syntaxhighlight lang="haskell">
tree1 :: Tree Integer
tree1 =
Branch
(Branch
(Branch
(Leaf 1)
(Branch (Leaf 2) (Leaf 3)))
(Branch
(Leaf 4)
(Branch (Leaf 5) (Leaf 6))))
(Branch
(Branch (Leaf 7) (Leaf 8))
(Leaf 9))
doubleTree = treeMap (*2) -- doubles each value in tree
sumTree = treeFold (+) id -- sum of the leaf values in tree
fringeTree = treeFold (++) (: []) -- list of the leaves of tree
</syntaxhighlight>
Then load it into GHCi and evaluate:
<pre>
doubleTree tree1
sumTree tree1
</pre>
==Other datatypes==
Map and fold functions can be defined for any kind of data type. In order to generalize the strategy applied for lists and trees, in this final section we will work out a map and a fold for a very strange, contrived datatype:
<syntaxhighlight lang="haskell">
data Weird a b = First a
| Second b
| Third [(a,b)]
| Fourth (Weird a b)
</syntaxhighlight>
It can be a useful exercise to write the functions as you follow the examples, trying to keep the coding one step ahead of your reading.
===General Map===
The first important difference in working with this <code>Weird</code> type is that it has ''two'' type parameters. For that reason, we will want the map function to take two functions as arguments, one to be applied on the elements of type <code>a</code> and another for the elements of type <code>b</code>. With that accounted for, we can write the type signature of <code>weirdMap</code>:
<syntaxhighlight lang="haskell">
weirdMap :: (a -> c) -> (b -> d) -> Weird a b -> Weird c d
</syntaxhighlight>
Next step is defining <code>weirdMap</code>. The key point is that maps preserve the ''structure'' of a datatype, so the function must evaluate to a <code>Weird</code> which uses the same constructor as the one used for the original <code>Weird</code>. For that reason, we need one definition to handle each constructor, and these constructors are used as patterns for writing them. As before, to avoid repeating the <code>weirdMap</code> argument list over and over again a '''where''' clause comes in handy. A sketch of the function is below:
<syntaxhighlight lang="haskell">
weirdMap :: (a -> c) -> (b -> d) -> Weird a b -> Weird c d
weirdMap fa fb = g
where
g (First x) = --More to follow
g (Second y) = --More to follow
g (Third z) = --More to follow
g (Fourth w) = --More to follow
</syntaxhighlight>
The first two cases are fairly straightforward, as there is just a single element of <code>a</code> or <code>b</code> type inside the <code>Weird</code>.
<syntaxhighlight lang="haskell">
weirdMap :: (a -> c) -> (b -> d) -> Weird a b -> Weird c d
weirdMap fa fb = g
where
g (First x) = First (fa x)
g (Second y) = Second (fb y)
g (Third z) = --More to follow
g (Fourth w) = --More to follow
</syntaxhighlight>
<code>Third</code> is trickier because it contains a list whose elements are themselves data structures (the tuples). So we need to navigate the nested data structures, apply <code>fa</code> and <code>fb</code> on all elements of type <code>a</code> and <code>b</code> and eventually (as a map must preserve structure) produce a list of tuples – <code>[(c,d)]</code> – to be used with the constructor. The simplest approach might seem to be just breaking down the list inside the <code>Weird</code> and playing with the patterns:
<syntaxhighlight lang="haskell">
g (Third []) = Third []
g (Third ((x,y):zs)) = Third ( (fa x, fb y) : ( (\(Third z) -> z) (g (Third zs)) ) )
</syntaxhighlight>
This appears to be written as a typical recursive function for lists. We start by applying the functions of interest to the first element in order to obtain the head of the new list, {{nowrap|<code>(fa x, fb y)</code>}}. But what will we cons it to? As <code>g</code> requires a <code>Weird</code> argument, we need to make a <code>Weird</code> using the list tail in order to make the recursive call. But then <code>g</code> will give a <code>Weird</code> and not a list, so we have to retrieve the modified list from that – that's the role of the lambda function. Finally, there is also the empty list base case to be defined as well.
After all of that, we are left with a messy function. Every recursive call of <code>g</code> requires wrapping <code>zs</code> into a <code>Weird</code>, while what we really wanted to do was to build a list with {{nowrap|<code>(fa x, fb y)</code>}} and the modified <code>xs</code>. The problem with this solution is that <code>g</code> can (thanks to pattern matching) act directly on the list head but (due to its type signature) can't be called directly on the list tail. For that reason, it would be better to apply <code>fa</code> and <code>fb</code> without breaking down the list with pattern matching (as far as <code>g</code> is directly concerned, at least). But there ''was'' a way to directly modify a list element-by-element...
<syntaxhighlight lang="haskell">
g (Third z) = Third ( map (\(x, y) -> (fa x, fb y) ) z)
</syntaxhighlight>
...our good old <code>map</code> function, which modifies all tuples in the list <code>z</code> using a lambda function. In fact, the first attempt at writing the definition looked just like an application of the list map except for the spurious <code>Weird</code> packing and unpacking. We got rid of these by having the pattern splitting of <code>z</code> done by <code>map</code>, which works directly with regular lists. You could find it useful to expand the map definition inside <code>g</code> to see the difference more clearly. Finally, you may prefer to write this new version in an alternative and clean way using list comprehension syntax:
<syntaxhighlight lang="haskell">
g (Third z) = Third [ (fa x, fb y) | (x,y) <- z ]
</syntaxhighlight>
Adding the <code>Third</code> function, we only have the <code>Fourth</code> left to define:
<syntaxhighlight lang="haskell">
weirdMap :: (a -> c) -> (b -> d) -> Weird a b -> Weird c d
weirdMap fa fb = g
where
g (First x) = First (fa x)
g (Second y) = Second (fb y)
g (Third z) = Third ( map (\(x, y) -> (fa x, fb y) ) z)
g (Fourth w) = --More to follow
</syntaxhighlight>
All we need to do is apply <code>g</code> recursively:
<syntaxhighlight lang="haskell">
weirdMap :: (a -> c) -> (b -> d) -> Weird a b -> Weird c d
weirdMap fa fb = g
where
g (First x) = First (fa x)
g (Second y) = Second (fb y)
g (Third z) = Third ( map (\(x, y) -> (fa x, fb y) ) z)
g (Fourth w) = Fourth (g w)
</syntaxhighlight>
===General Fold===
While we were able to define a map by specifying as arguments a function for every separate type, this isn't enough for a fold. For a fold, we'll need a function for every constructor function. With lists, the constructors are <code>[]</code> and <code>(:)</code>. The <code>acc</code> argument in the <code>foldr</code> function corresponds to the <code>[]</code> constructor. The <code>f</code> argument in the <code>foldr</code> function corresponds to the <code>(:)</code> constructor. The <code>Weird</code> datatype has four constructors, so we need four functions – one for handling the internal structure of the datatype specified by each constructor. Next, we have an argument of the <code>Weird a b</code> type, and finally we want the whole fold function to evaluate to a value of some other, arbitrary, type. Additionally, each individual function we pass to <code>weirdFold</code> must evaluate to the same type <code>weirdFold</code> does. That allows us to make a mock type signature and sketch the definition:
<syntaxhighlight lang="haskell">
weirdFold :: (something1 -> c) -> (something2 -> c) -> (something3 -> c) -> (something4 -> c) -> Weird a b -> c
weirdFold f1 f2 f3 f4 = g
where
g (First x) = --Something of type c here
g (Second y) = --Something of type c here
g (Third z) = --Something of type c here
g (Fourth w) = --Something of type c here
</syntaxhighlight>
Now, we need to figure out which types <code>something1</code>, <code>something2</code>, <code>something3</code> and <code>something4</code> correspond to. That is done by analyzing the constructors, since the functions must take as arguments the elements of the datatype (whose types are specified by the constructor type signature). Again, the types and definitions of the first two functions are easy enough. The third one isn't too difficult either because, for the purposes of folding the list of <code>(a,b)</code>, tuples are no different from a simple type (unlike in the map example, the ''internal'' structure does not concern us now). The fourth constructor, however, is recursive, and we have to be careful. As with <code>weirdMap</code>, we also need to recursively call the <code>g</code> function. This brings us to the final definition:
<syntaxhighlight lang="haskell">
weirdFold :: (a -> c) -> (b -> c) -> ([(a,b)] -> c) -> (c -> c) -> Weird a b -> c
weirdFold f1 f2 f3 f4 = g
where
g (First x) = f1 x
g (Second y) = f2 y
g (Third z) = f3 z
g (Fourth w) = f4 (g w)
</syntaxhighlight>
{{body note|1=
If you were expecting very complex expressions in the <code>weirdFold</code> above and are surprised by the immediacy of the solution, it might be helpful to have a look on what the common <code>foldr</code> would look like if we wrote it in this style and didn't have the special square-bracket syntax of lists to distract us:
<syntaxhighlight lang="haskell">
-- List a is [a], Cons is (:) and Nil is []
data List a = Cons a (List a) | Nil
listFoldr :: (a -> b -> b) -> (b) -> List a -> b
listFoldr fCons fNil = g
where
g (Cons x xs) = fCons x (g xs)
g Nil = fNil
</syntaxhighlight>
Now it is easier to see the parallels. The extra complications are that <code>Cons</code> (that is, <code>(:)</code>) takes two arguments (and, for that reason, so does <code>fCons</code>) and is recursive, requiring a call to <code>g</code>. Also, <code>fNil</code> is of course not really a function, as it takes no arguments.
}}
====Folds on recursive datatypes====
As far as folds are concerned, <code>Weird</code> was a fairly nice datatype to deal with. Just one recursive constructor, which isn't even nested inside other structures. What would happen if we added a truly complicated fifth constructor?
<syntaxhighlight lang="haskell">
Fifth [Weird a b] a (Weird a a, Maybe (Weird a b))
</syntaxhighlight>
This is a valid and yet tricky question. In general, the following rules apply:
* A function to be supplied to a fold has the same number of arguments as the corresponding constructor.
* The type of the arguments of such a function match the types of the constructor arguments, ''except'' if the constructor is recursive (that is, takes an argument of its own type).
* If a constructor is recursive, any recursive argument of the constructor will correspond to an argument of the type the fold evaluates to.<ref>This sort of recursiveness, in which the function used for folding can take the result of another fold as an argument, is what confers the folds of data structures such as lists and trees their "accumulating" functionality.</ref>
* If a constructor is recursive, the complete fold function should be (recursively) applied to the recursive constructor arguments.
* If a recursive element appears inside another data structure, the appropriate map function for that data structure should be used to apply the fold function to it.
So <code>f5</code> would have the type:
<syntaxhighlight lang="haskell">
f5 :: [c] -> a -> (Weird a a, Maybe c) -> c
</syntaxhighlight>
as the type of <code>Fifth</code> is:
<syntaxhighlight lang="haskell">
Fifth :: [Weird a b] -> a -> (Weird a a, Maybe (Weird a b)) -> Weird a b
</syntaxhighlight>
The definition of <code>g</code> for the <code>Fifth</code> constructor will be:
<syntaxhighlight lang="haskell">
g (Fifth list x (waa, mc)) = f5 (map g list) x (waa, maybeMap g mc)
where
maybeMap f Nothing = Nothing
maybeMap f (Just w) = Just (f w)
</syntaxhighlight>
Note that nothing strange happens with the <code>Weird a a</code> part. No <code>g</code> gets called. What's up? This is recursion, right? Well, not really. <code>Weird a a</code> and <code>Weird a b</code> are different types, so it isn't a real recursion. It isn't guaranteed that, for example, <code>f2</code> will work with something of type 'a', where it expects a type 'b'. It can be true for some cases but is not reliable for every case.
Also look at the definition of <code>maybeMap</code>. Verify that it is indeed a map function as:
* It preserves structure.
* Only types are changed.
==== A nice sounding word ====
The folds we have defined here are examples of ''catamorphisms''. A catamorphism is a general way to collapse a data structure into a single value. There is deep theory associated with catamorphisms and related recursion schemes; however, we won't go through any of it now, as our main goal here was exercising the mechanics of data structure manipulation in Haskell with believable examples.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Intermediate Haskell|noexercises=1}}
{{BookCat}}
infaqpc9326pnqlubuhsdc9najuczfe
OpenSCAD User Manual/Using OpenSCAD in a command line environment
0
227473
4675860
4675812
2026-10-13T15:35:45Z
~2026-54954-64
3628319
/* Automation */ Add command to set script directory as current directory
4675860
wikitext
text/x-wiki
__TOC__
=== Command line usage ===
OpenSCAD can not only be used as a GUI, but also handles command line arguments.
OpenSCAD (DEV/nightly) 2025.08.17 has these options
<pre>
Usage: openscad.exe [options] file.scad
Allowed options:
--export-format arg overrides format of exported scad file when
using option '-o', arg can be any of its
supported file extensions. For ascii stl
export, specify 'asciistl', and for binary
stl export, specify 'binstl'. Ascii export
is the current stl default, but binary stl
is planned as the future default so
asciistl should be explicitly specified in
scripts when needed.
-o [ --o ] arg output specified file instead of running
the GUI. The file extension specifies the
type: stl, off, wrl, amf, 3mf, csg, dxf,
svg, pdf, png, echo, ast, term, nef3,
nefdbg, param, pov. May be used multiple
times for different exports. Use '-' for
stdout.
-O [ --O ] arg pass settings value to the file export
using the format section/key=value, e.g
export-pdf/paper-size=a3. Use --help-export
to list all available settings.
-D [ --D ] arg var=val -pre-define variables
-p [ --p ] arg customizer parameter file
-P [ --P ] arg customizer parameter set
--enable arg enable experimental features (specify 'all'
for enabling all available features): roof
| input-driver-dbus | lazy-union |
vertex-object-renderers-indexing |
textmetrics | import-function |
predictible-output
-h [ --help ] print this help message and exit
--help-export print list of export parameters and values
that can be set via -O
-v [ --version ] print the version
--info print information about the build process
--camera arg camera parameters when exporting png:
=translate_x,y,z,rot_x,y,z,dist or
=eye_x,y,z,center_x,y,z
--autocenter adjust camera to look at object's center
--viewall adjust camera to fit object
--backend arg 3D rendering backend to use: 'CGAL'
(old/slow) [default] or 'Manifold'
(new/fast)
--imgsize arg =width,height of exported png
--render arg for full geometry evaluation when exporting
png
--preview arg [=throwntogether] -for ThrownTogether
preview png
--animate arg export N animated frames
--animate_sharding arg Parameter <shard>/<num_shards> - Divide
work into <num_shards> and only output
frames for <shard>. E.g. 2/5 only outputs
the second 1/5 of frames. Use to
parallelize work on multiple cores or
machines.
--view arg =view options: axes | crosshairs | edges |
scales
--projection arg =(o)rtho or (p)erspective when exporting
png
--csglimit arg =n -stop rendering at n CSG elements when
exporting png
--summary arg enable additional render summary and
statistics: all | cache | time | camera |
geometry | bounding-box | area
--summary-file arg output summary information in JSON format
to the given file, using '-' outputs to
stdout
--colorscheme arg =colorscheme: *Cornfield | Metallic |
Sunset | Starnight | BeforeDawn | Nature |
Daylight Gem | Nocturnal Gem | DeepOcean |
Solarized | Tomorrow | Tomorrow Night |
ClearSky | Monotone
-d [ --d ] arg deps_file -generate a dependency file for
make
-m [ --m ] arg make_cmd -runs make_cmd file if file is
missing
-q [ --quiet ] quiet mode (don't print anything *except*
errors)
--hardwarnings Stop on the first warning
--trace-depth arg =n, maximum number of trace messages
--trace-usermodule-parameters arg =true/false, configure the output of user
module parameters in a trace
--check-parameters arg =true/false, configure the parameter check
for user modules and functions
--check-parameter-ranges arg =true/false, configure the parameter range
check for builtin modules
--debug arg special debug info - specify 'all' or a set
of source file names
-s [ --s ] arg stl_file deprecated, use -o
-x [ --x ] arg dxf_file deprecated, use -o
</pre>
Export help
<pre>
OpenSCAD version 2025.08.17
List of settings that can be given using the -O option using the
format '<section>/<key>=value', e.g.:
openscad -O export-pdf/paper-size=a6 -O export-pdf/show-grid=false
Section 'export-pdf':
- paper-size (enum): [a6,a5,<a4>,a3,letter,legal,tabloid]
- orientation (enum): [<portrait>,landscape,auto]
- show-filename (bool): <true>/false
- show-scale (bool): <true>/false
- show-scale-message (bool): <true>/false
- show-grid (bool): <true>/false
- grid-size (double): 1.000000 : <10.000000> : 100.000000
- add-meta-data (bool): <true>/false
- meta-data-title (string): ""
- meta-data-author (string): ""
- meta-data-subject (string): ""
- meta-data-keywords (string): ""
Section 'export-3mf':
- color-mode (enum): [<model>,none,selected-only]
- unit (enum): [micron,<millimeter>,centimeter,meter,inch,foot]
- color (string): "#f9d72c"
- material-type (enum): [color,<basematerial>]
- decimal-precision (int): 1 : <6> : 16
- add-meta-data (bool): <true>/false
- meta-data-title (string): ""
- meta-data-designer (string): ""
- meta-data-description (string): ""
- meta-data-copyright (string): ""
- meta-data-license-terms (string): ""
- meta-data-rating (string): ""
</pre>
OpenSCAD 2021.01 has these options:
Usage: openscad [options] file.scad
Allowed options:
--export-format arg overrides format of exported scad file when
using option '-o', arg can be any of its
supported file extensions. For ascii stl
export, specify 'asciistl', and for binary stl
export, specify 'binstl'. Ascii export is the
current stl default, but binary stl is planned
as the future default so asciistl should be
explicitly specified in scripts when needed.
-o [ --o ] arg output specified file instead of running the
GUI, the file extension specifies the type: stl,
off, wrl, amf, 3mf, csg, dxf, svg, pdf, png,
echo, ast, term, nef3, nefdbg (May be used
multiple time for different exports). Use '-'
for stdout
-D [ --D ] arg var=val -pre-define variables
-p [ --p ] arg customizer parameter file
-P [ --P ] arg customizer parameter set
--enable arg enable experimental features (specify 'all' for
enabling all available features): roof |
input-driver-dbus | lazy-union |
vertex-object-renderers |
vertex-object-renderers-indexing |
vertex-object-renderers-direct |
vertex-object-renderers-prealloc | textmetrics
-h [ --help ] print this help message and exit
-v [ --version ] print the version
--info print information about the build process
--camera arg camera parameters when exporting png:
=translate_x,y,z,rot_x,y,z,dist or
=eye_x,y,z,center_x,y,z
--autocenter adjust camera to look at object's center
--viewall adjust camera to fit object
--imgsize arg =width,height of exported png
--render for full geometry evaluation when exporting png
--preview arg [=throwntogether] -for ThrownTogether preview
png
--animate arg export N animated frames
--view arg =view options: axes | crosshairs | edges |
scales | wireframe
--projection arg =(o)rtho or (p)erspective when exporting png
--csglimit arg =n -stop rendering at n CSG elements when
exporting png
--summary arg enable additional render summary and statistics:
all | cache | time | camera | geometry |
bounding-box | area
--summary-file arg output summary information in JSON format to the
given file, using '-' outputs to stdout
--colorscheme arg =colorscheme: *Cornfield | Metallic | Sunset |
Starnight | BeforeDawn | Nature | DeepOcean |
Solarized | Tomorrow | Tomorrow Night | Monotone
-d [ --d ] arg deps_file -generate a dependency file for make
-m [ --m ] arg make_cmd -runs make_cmd file if file is missing
-q [ --quiet ] quiet mode (don't print anything *except*
errors)
--hardwarnings Stop on the first warning
--check-parameters arg =true/false, configure the parameter check for
user modules and functions
--check-parameter-ranges arg =true/false, configure the parameter range check
for builtin modules
--debug arg special debug info - specify 'all' or a set of
source file names
=== Export options ===
When called with the <code>-o</code> option, OpenSCAD does not start the GUI, but executes the given file and exports to the <i>output_file</i> in a format depending on the extension (<code>.stl</code> / <code>.off</code> / <code>.dxf</code>, <code>.csg</code>).
Some versions use -s/-d/-o to determine the output file format instead; check with "openscad --help".
If the option <code>-d</code> is given in addition to an export command, all files accessed while building the mesh are written in the argument of <code>-d</code> in the syntax of a Makefile.
For at least 2015.03-2+, specifying the extension <code>.echo</code> causes openscad to produce a text file containing error messages and the output of all <code>echo()</code> calls in <code>filename</code> as they would appear in the console window visible in the GUI. Multiple output files are not supported, so using this option you cannot also obtain the model that would have normally been generated.
Note: When exporting to STL, the GUI defaults to binary STL (smaller, faster) and the CLI defaults to ASCII STL (larger, slower). Post-processing pipelines may prefer ASCII STL; they should explicitly say `--export-format asciistl` in preparation for the default eventually changing to binary STL.
==== Camera and image output ====
For 2013.05+, the option to output a <code>.png</code> image was added. There are two types of cameras available for the generation of images.
The first camera type is a 'gimbal' camera that uses Euler angles, translation, and a camera distance, like OpenSCAD's GUI viewport display at the bottom of the OpenSCAD window.
The second camera type is a 'vector' camera, with an 'eye' camera location vector and a 'lookat' center vector.
--imgsize x,y chooses the .png dimensions and --projection chooses orthogonal or perspective, as in the GUI.
By default, cmdline .png output uses Preview mode (f5) with OpenCSG. For some situations it may be desirable to output the full render, with CGAL. This is done by adding '--render' as an option.
=== Constants ===
In order to pre-define variables, use the <code>-D</code> option. It can be given repeatedly. Each occurrence of <code>-D</code> must be followed by an assignment. Unlike normal OpenSCAD assignments, these assignments don't define variables, but constants, which cannot be changed inside the program, and can thus be used to overwrite values defined in the program at export time.
If you want to assign the -D variable to another variable, the -D variable MUST be initialized in the main .scad program
param1=17; // must be initialized
val=param1; // param1 passed via -D on cmd-line
echo(val,param1); // outputs 17,17
without the first line, val would be undefined.
The right hand sides can be arbitrary OpenSCAD expressions, including mathematical operations and strings.
Be aware that your shell (bash, cmd, etc.) parses the arguments before passing them to <code>openscad</code>, therefore you need to properly quote or escape arguments with special characters like spaces or quotation marks. For example to assign a string <code>production</code> to a <code>quality</code> parameter one has to ensure the <code>"</code> characters OpenSCAD expects aren't stripped by the shell. In bash one could write:
openscad -o my_model_production.stl -D 'quality="production"' my_model.scad
or from the Windows prompt:
openscad.com -o my_model_production.stl -D "quality=""production""" my_model.scad
or you may need to escape the inner quotes instead:
openscad -o my_model_production.stl -D "quality=\"production\"" my_model.scad
Note that this sort of double-escaping isn't necessary when executing OpenSCAD from another process that isn't using a shell, because each argument is passed separately. For example a Java application might start a process like so:
pb = new ProcessBuilder("/usr/bin/openscad",
"-o", "my_model_production.stl",
"-D", "quality=\"production\"",
"my_model.scad");
// 12-Pole Fuse Box with Cover (EV Application)
// ================= PARAMETERS =================
length = 100;
width = 40;
height = 35;
wall = 2.5;
fuse_w = 4.2;
fuse_l = 12;
fuse_h = 12;
x_pitch = 8.5;
y_pitch = 14;
cover_height = 5;
// ================= MAIN HOUSING =================
difference() {
cube([length, width, height]);
// Hollow inside
translate([wall, wall, wall])
cube([length-2*wall, width-2*wall, height]);
// Fuse slots (2 rows x 6 columns)
for (row = [0:1]) {
for (col = [0:5]) {
x = 10 + col * x_pitch;
y = 10 + row * y_pitch;
translate([x, y, 5])
cube([fuse_w, fuse_l, fuse_h]);
}
}
}
// ================= COVER =================
translate([0, 0, height])
cube([length, width, cover_height]);
// ================= MOUNTING HOLES =================
for (x = [10, length-10]) {
translate([x, width/2, 0])
cylinder(h=height, d=5, center=false);
}
=== Processing all .scad files in a folder ===
Example to convert all the .scad in a folder into .stl:
In a folder with .scad files, make a .bat file with text:
FOR %%f in (*.scad) DO openscad -o "%%~nf.stl" "%%f"
If it closes without processing, check to set the PATH by adding openscad directory to:
Start - Settings - Control Panel - System - Advanced tab - Environment Variables - System Variables, select Path, then click Edit.
Add the openscad directory to the list
=== Makefile example ===
The <code>-d</code> and <code>-m</code> options only make sense together. (<code>-m</code> without <code>-d</code> would not consider modified dependencies when building exports, <code>-d</code> without <code>-m</code> would require the files to be already built for the first run that generates the dependencies.)
Here is an example of a basic Makefile that creates an .stl file from an .scad file of the same name:
# explicit wildcard expansion suppresses errors when no files are found
include $(wildcard *.deps)
%.stl: %.scad
openscad -m make -o $@ -d $@.deps $<
When <code>make my_example.stl</code> is run for the first time, it finds no .deps files, and must depend on <code>my_example.scad</code>. Because <code>my_example.stl</code> is not yet present, it gets created unconditionally. If OpenSCAD finds missing files, it calls <code>make</code> to build them, and it lists all used files in <code>my_example.stl.deps</code>.
When <code>make my_example.stl</code> is called subsequently, it finds and includes <code>my_example.stl.deps</code> and check if any of the files listed there, including <code>my_example.scad</code>, changed since <code>my_example.stl</code> was built, based on their time stamps. Only if that is the case, it builds <code>my_example.stl</code> again.
==== Automatic targets ====
When building similar .stl files from a single .scad file, there is a way to automate that too:
# match "module foobar() { // `make` me"
TARGETS=$(shell sed '/^module [a-z0-9_-]*().*make..\?me.*$$/!d;s/module //;s/().*/.stl/' base.scad)
all: ${TARGETS}
# auto-generated .scad files with .deps make make re-build always. keeping the
# scad files solves this problem. ([[Talk:OpenSCAD User Manual/Using OpenSCAD in a command line environment|explanations are welcome]].)
.SECONDARY: $(shell echo "${TARGETS}" | sed 's/\.stl/.scad/g')
# explicit wildcard expansion suppresses errors when no files are found
include $(wildcard *.deps)
%.scad:
echo -ne 'use <base.scad>\n$*();' > $@
%.stl: %.scad
openscad -m make -o $@ -d $@.deps $<
All objects that are supposed to be exported automatically have to be defined in <code>base.scad</code> in an own module with their future file name (without the ".stl"), and have a comment like "<code>// make me</code>" in the line of the module definition. The "<code>TARGETS=</code>" line picks these out of the base file and creates the file names. These are built when <code>make all</code> (or <code>make</code>, for short) is called.
As the convention from the last example is to create the .stl files from .scad files of the same base name, for each of these files, an .scad file must be generated. This is done in the "<code>%.scad:</code>" paragraph; <code>my_example.scad</code> is a simple OpenSCAD file:
use <base.scad>
my_example();
The "<code>.SECONDARY</code>" line is there to keep <code>make</code> from deleting the generated .scad files. Its presence helps determine which files no longer need to be rebuilt; please post ideas about what exactly goes wrong there (or how to fix it better) on the [[Talk:OpenSCAD User Manual/Using OpenSCAD in a command line environment|talk]] page!
=== Windows notes ===
On Windows, openscad.com should be called from the command line as a wrapper for openscad.exe. This is because Openscad uses the 'devenv' solution to the Command-Line/GUI output issue. Typing 'openscad' at the cmd.exe prompt calls the .com program wrapper by default.
=== MacOS notes ===
On MacOS the binary is normally hidden inside the App folder. If OpenSCAD is installed in the global Applications folder, it can be called from command line like in the following example that just shows the OpenSCAD version:
macbook:/$ /Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD -v
OpenSCAD version 2013.06
Alternatively, you may create a symbolic link to the binary to make calls from the command line easier:
macbook:/$ sudo ln -sf /Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD /usr/local/bin/openscad
Now you can call <code>openscad</code> directly without having to type in the full path.
macbook:/$ openscad -v
OpenSCAD version 2015.03-3
On some versions of MacOS, you might get the following error when attempting to run openscad via that link:
This application failed to start because it could not find or load the Qt platform plugin "cocoa".
Reinstalling the application may fix this problem.
Abort trap: 6
You can fix this by creating a wrapper script to invoke the executable directly:
sudo rm -f /usr/local/bin/openscad
echo '#!/bin/sh' > test
echo '/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD "$@"' >> test
chmod +x test ; sudo mv test /usr/local/bin/openscad
=== Automation ===
There are many solutions to automate Openscad operation, the following examples use Microsoft Powershell which is available either on Windows, on Linux (in deb and snap packages) or on MacOS.
Such script file shall be written on a text editor, much preferably a code editor with syntax coloring for powershell (e.g. VS code, Sublime text).
Note that while powershell script may be started directly from file browser in Linux, for debugging you may want to start script from a terminal window in order to see messages from script or OpenScad.
First you shall define the program call for your system and set it in a variable, adjust according your system
On Windows this may depends from your system disk, could be simpler if your environment variable are well set:
<pre>$scad = "c:`"/Program Files/OpenSCAD/openscad.exe`""</pre>
On Linux simply:
<pre>$scad = "openscad" </pre>
On MacOS this may be:
<pre>$scad = "/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD"</pre>
If you want to be capable to use a variation of openscad, say the nightly version, set the openscad version you want.
<pre>$scad = "openscad-nightly"</pre>
==== Outputting different parts of a model ====
The first automation that you may want is to output automatically many parts from the same scad file.
You can use a variable ‘part’ to select the part to output.
code of 'mymodel.scad' might be:
<pre>
part = 0; // [0:Ensemble, 1:Part 1, 2:Part 2, 3:Part 3]
...
if (part==1) {
...
}
else if (part==2) {
...
}
else if (part==3) {
...
}
</pre>
and the automation file ‘mybatch.ps1’ will be:
<pre>
#!/usr/bin/env pwsh
# Above 'shebang' line required on Linux for automatic execution of powershell from a direct launch on file browser. 'mybatch.ps1' file attributes shall be made executable first.
$scad = "openscad" #Adapt according to your OS
#Powershell part batch generator
$arglist = "-o mymodelpart1.stl -D part=1 mymodel.scad"
Start-Process $scad -ArgumentList $arglist -Wait -NoNewWindow
$arglist = "-o mymodelpart2.stl -D part=2 mymodel.scad"
Start-Process $scad -ArgumentList $arglist -Wait -NoNewWindow
$arglist = "-o mymodelpart2.stl -D part=3 mymodel.scad"
Start-Process $scad -ArgumentList $arglist -Wait -NoNewWindow
</pre>
-Wait parameter impose the task to be finished before continuing the script
-NoNewWindow will execute the script in the existing window without starting a new one
Note there is no space around the '=' sign for parameters
You may want to change any other parameter than 'part' at will, including or not a part number, in this case the argument list might be:
<pre>
$arglist = "-o somepart.stl -D myvar1=value1 -D myvar2=value2 mymodel.scad"
</pre>
Note that if the value is a string, double quotes shall be escaped by a bactick ` : -D myvals=`"myparam`" for them not to be interpreted as the $arglist string end or start.
You may also define a string by setting it between simple quotes but that prevent you to use variables which will be interpreted when running command.
So the execution line became:
<pre>
Start-Process $scad -ArgumentList $arglist -Wait -NoNewWindow
</pre>
==== BOM or datasheet exportation ====
Another frequent request is to export a BOM or a specification
This could be done by adapting your program to echo the stuff you want, by example:
<pre>
echoout = 0; //0 is normal screen echo, 1 will be BOM, 2 will be data Specification
if (echoout==0) {
echo("Normal echo");
}
...
if (echoout==1) {
echo("Part 1 : description1");
echo("Part 2 : description2");
echo("Part 3 : description3 dimensions:", part3dim1,"x",part3dim2);
}
...
if (echoout==2) {
echo(str("First parameter =", var1));
echo(str("Second parameter =", var2));
echo(str("Third parameter =", var3));
}
</pre>
Writing your own echo module may help.
then to obtain an output, your argument list may became:
<pre>$arglist = "-o mymodel_BOM.txt -D echoout=1 --export-format echo mymodel.scad"</pre>
and
<pre>$arglist = "-o mymodel_data.txt -D echoout=2 --export-format echo mymodel.scad"</pre>
However, the outputted text will have 'ECHO:' written at the beginning of each line and text will be set between ", that you want to remove with following commands:
<pre>
#IMPORTANT! Before manipulating files, you shall know where you are in the directory tree
cd $PSScriptRoot #Set script directory as current directory, allow to work with relative path
$fc = Get-Content .\mymodel_BOM.txt #get whole file in $fc variable
if($fc) { #check if the file have any content
$fc = $fc -replace 'ECHO: ', '' #remove 'ECHO: ' text
$fc = $fc -replace '"' , '' #remove '"' char - this is optional
$fc > .\mymodel_BOM.txt #send variable content to the file which will be overwritten
}
</pre>
==== Image exportation ====
You can export an image simply by defining the png extension. By default the image is the preview adapted to object size and viewed in 3D. Your argument list then became:
<pre>$arglist = "-o mymodel.png --imgsize 1024,1024 mymodel.scad"</pre>
If you want the viewed image as rendered add '--render' parameter before the size definition:
<pre>$arglist = "-o mymodel.png --render --imgsize 1024,1024 mymodel.scad"</pre>
==== Using datasets ====
An interesting option is to use Customizer datasets, however Customizer datasets variable values supersedes any values than you try to define in the command line:
The solution is to rename the parameter you need to modify and copy it to a variable that the command line will then be capable to change.
In your scad you may find:
<pre>
cpart = 0; // [0:ensemble, 1:Part 1, 2:Part 2, 3:Part 3] //This variable will be recorded in the dataset, so not modifiable
part=cpart; // 'part' variable can be manipulated by the command line
//Argument list for all your runs could then be:
$arglist = "-o mymodeldataset1part1.stl -D part=1 -p mymodel.json -P dataset1 mymodel.scad"
$arglist = "-o mymodeldataset1part2.stl -D part=2 -p mymodel.json -P dataset1 mymodel.scad"
$arglist = "-o mymodeldataset2part1.stl -D part=1 -p mymodel.json -P dataset2 mymodel.scad"
$arglist = "-o mymodeldataset2part2.stl -D part=2 -p mymodel.json -P dataset2 mymodel.scad"
</pre>
Do the same for any parameter that you want to manipulate in the command Line when using datasets:
<pre>
//This is parameter1
cvar1 = value1;
var1 = cvar1;
//This is parameter 2
cvar2 = value2;
var2 = cvar2;
</pre>
==== Browsing datasets ====
A step further might be to automate the dataset browsing. You shall read the json file which contains all datasets:
A regular expression can then filter dataset names:
<pre>
$regex='\"(?!parameterSets)([^\"]+)\"\:\s\{' # This regex extract anything between "" followed by ': {' excluding 'parameterSets'
$jfile = "./mymodel.json #directory localisation required by powershell
foreach($line in Get-Content $jfile) { # read json file Line by Line
if($line -match $regex) { # We found a dataset name
$dataset = $Matches.1 # dataset is the part captured by the regex parenthesis, will also be used in the part name
Write-Output "Dataset: $dataset" #Output to console debugging info
$datasetname = $dataset -replace ' ' , '_' #replace space by underscore
#Dataset name containing often space character shall be set between double quotes
#We may use simple quotes to define strings containing double quotes around dataset name
$arglist = "-o + mymodel" + $datasetname + '.stl -p mymodel.json -P "' + $dataset + '" mymodel.scad'
Write-Output "Argument list: $arglist" #Output to console debugging info
Start-Process $scad -ArgumentList $arglist -Wait -NoNewWindow
}
}
</pre>
{{BookCat}}
63h6ixhmr7v4mamv9uupy9olmyax3zz
Haskell/Truth values
0
227830
4675913
4439827
2026-10-13T22:23:13Z
~2026-55011-96
3628367
4675913
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Haskell Basics|noexercises=1}}
== Equality and other comparisons ==
In the last chapter, we used the equals sign to define variables and functions in Haskell as in the following code:
<syntaxhighlight lang = "haskell">
r = 5
</syntaxhighlight>
That means that the evaluation of the program replaces all occurrences of <code>r</code> with <code>5</code> (within the scope of the definition). Similarly, evaluating the code
<syntaxhighlight lang = "haskell">
f x = x + 3
</syntaxhighlight>
replaces all occurrences of <code>f</code> followed by a number (<code>f</code>'s argument) with that number plus three.
Mathematics also uses the equals sign in an important and subtly different way. For instance, consider this simple problem:
{{Haskell/Example|Solve the following equation:|<math>x+3=5</math>}}
Our interest here isn't about representing the value <math>5</math> as <math>x+3</math>, or vice-versa. Instead, we read the <math>x+3=5</math> equation as a ''proposition'' that some number <math>x</math> gives 5 as result when added to 3. Solving the equation means finding which, if any, values of <math>x</math> make that proposition true. In this example, elementary algebra tells us that <math>x=2</math> (i.e. 2 is the number that will make the equation true, giving <math>2+3=5</math>).
Comparing values to see if they are equal is also useful in programming. In Haskell, such tests look just like an equation. Since the equals sign is already used for defining things, Haskell uses a ''double'' equals sign, <code>==</code> instead. Enter our proposition above in GHCi:
{{Haskell/GHCi|1=
Prelude> 2 + 3 == 5
True
}}
GHCi returns "True" because <math>2 + 3</math> is equal to 5. What if we use an equation that is not true?
{{Haskell/GHCi|1=
Prelude> 7 + 3 == 5
False
}}
Nice and coherent. Next, we will use our own functions in these tests. Let's try the function <code>f</code> we mentioned at the start of the chapter:
{{Haskell/GHCi|1=
Prelude> let f x = x + 3
Prelude> f 2 == 5
True
}}
This works as expected because <code>f 2</code> evaluates to <code>2 + 3</code>.
We can also compare two numerical values to see which one is larger. Haskell provides a number of tests including: <code><</code> (less than), <code>></code> (greater than), <code><=</code> (less than or equal to) and <code>>=</code> (greater than or equal to). These tests work comparably to <code>==</code> (equal to). For example, we could use <code><</code> alongside the <code>area</code> function from the previous module to see whether a circle of a certain radius would have an area smaller than some value.
{{Haskell/GHCi|1=
Prelude> let area r = pi * r ^ 2
Prelude> area 5 < 50
False
}}
== Boolean values ==
What is actually going on when GHCi determines whether these arithmetical propositions are true or false? Consider a different but related issue. If we enter an arithmetical expression in GHCi the expression gets ''evaluated'', and the resulting numerical value is displayed on the screen:
{{Haskell/GHCi|1=
Prelude> 2 + 2
4
}}
If we replace the arithmetical expression with an equality comparison, something similar seems to happen:
{{Haskell/GHCi|1=
Prelude> 2 == 2
True
}}
Whereas the "4" returned earlier is a number which represents some kind of count, quantity, etc., "True" is a ''value'' that stands for the truth of a proposition. Such values are called '''truth values''', or '''boolean values'''.<ref>The term is a tribute to the mathematician and philosopher [[w:George Boole|George Boole]].</ref> Naturally, only two possible boolean values exist: <code>True</code> and <code>False</code>.
=== Introduction to types ===
<code>True</code> and <code>False</code> are real values, not just an analogy. Boolean values have the same status as numerical values in Haskell, and you can manipulate them in similar ways. One trivial example:
{{Haskell/GHCi|1=
Prelude> True == True
True
Prelude> True == False
False
}}
<code>True</code> is indeed equal to <code>True</code>, and <code>True</code> is not equal to <code>False</code>. Now: can you answer whether <code>2</code> is equal to <code>True</code>?
{{Haskell/GHCi|1=
Prelude> 2 == True
<interactive>:1:0:
No instance for (Num Bool)
arising from the literal ‘2’ at <interactive>:1:0
Possible fix: add an instance declaration for (Num Bool)
In the first argument of ‘(==)’, namely ‘2’
In the expression: 2 == True
In an equation for ‘it’: it = 2 == True
}}
Error! The question just does not make sense. We cannot compare a number with a non-number or a boolean with a non-boolean. Haskell incorporates that notion, and the ugly error message complains about this. Ignoring much of the clutter, the message says that there was a number (<code>Num</code>) on the left side of the <code>==</code>, and so some kind of number was expected on the right side; however, a boolean value (<code>Bool</code>) is not a number, and so the equality test failed.
So, values have '''types''', and these types define limits to what we can or cannot do with the values. <code>True</code> and <code>False</code> are values of type <code>Bool</code>. The <code>2</code> is complicated because there are many different types of numbers, so we will defer that explanation until later. Overall, types provide great power because they regulate the behavior of values with rules that ''make sense'', making it easier to write programs that work correctly. We will come back to the topic of types many times as they are very important to Haskell.
== Infix operators ==
An equality test like <code>2 == 2</code> is an expression just like <code>2 + 2</code>; it evaluates to a value in pretty much the same way. The ugly error message we got on the previous example even says so:
{{Haskell/GHCi|1=
In the expression: 2 == True
}}
When we type <code>2 == 2</code> in the prompt and GHCi "answers" <code>True</code>, it is simply evaluating an expression. In fact, <code>==</code> is itself a function which takes two arguments (which are the left side and the right side of the equality test), but the syntax is notable: Haskell allows two-argument functions to be written as ''infix operators'' placed ''between'' their arguments. When the function name uses only non-alphanumeric characters, this infix approach is the common use case. If you wish to use such a function in the "standard" way (writing the function name before the arguments, as a ''prefix operator'') the function name must be enclosed in parentheses. So the following expressions are completely equivalent:
{{Haskell/GHCi|1=
Prelude> 4 + 9 == 13
True
Prelude> (==) (4 + 9) 13
True
}}
Thus, we see how <code>(==)</code> works as a function similarly to <code>areaRect</code> from the previous module. The same considerations apply to the other ''relational operators'' we mentioned (<code><</code>, <code>></code>, <code><=</code>, <code>>=</code>) and to the arithmetical operators (<code>+</code>, <code>*</code>, etc.) – all are functions that take two arguments and are normally written as infix operators.
In general, we can say that tangible things in Haskell are either values or functions.
== Boolean operations ==
Haskell provides three basic functions for further manipulation of truth values as in logic propositions:
* <code>(&&)</code> performs the ''and'' operation. Given two boolean values, it evaluates to <code>True</code> if both the first and the second are <code>True</code>, and to <code>False</code> otherwise.
{{Haskell/GHCi|1=
Prelude> (3 < 8) && (False == False)
True
Prelude> (&&) (6 <= 5) (1 == 1)
False
}}
* <code>(||)</code> performs the ''or'' operation. Given two boolean values, it evaluates to <code>True</code> if at least one of them is <code>True</code> and to <code>False</code> otherwise.
{{Haskell/GHCi|1=
Prelude> (2 + 2 == 5) {{!!}} (2 > 0)
True
Prelude> ({{!!}}) (18 == 17) (9 >= 11)
False
}}
* <code>not</code> performs the negation of a boolean value; that is, it converts <code>True</code> to <code>False</code> and vice-versa.
{{Haskell/GHCi|1=
Prelude> not (5 * 2 == 10)
False
}}
Haskell libraries already include the relational operator function <code>(/=)</code> for ''not equal to'', but we could easily implement it ourselves as:
<syntaxhighlight lang = "haskell">
x /= y = not (x == y)
</syntaxhighlight>
Note that we can write operators infix even when defining them. Completely new operators can also be created out of ASCII symbols (which means mostly the common symbols used on a keyboard).
== Guards ==
Haskell programs often use boolean operators in convenient and abbreviated syntax. When the same logic is written in alternative styles, we call this ''syntactic sugar'' because it sweetens the code from the human perspective. We'll start with ''guards'', a feature that relies on boolean values and allows us to write simple but powerful functions.
Let's implement the absolute value function. The absolute value of a real number is the number with its sign discarded; so if the number is negative (that is, smaller than zero) the sign is inverted; otherwise it remains unchanged. We could write the definition as:
<math>|x| = \begin{cases} x, & \mbox{if } x \ge 0 \\ -x, & \mbox{if } x < 0. \end{cases} </math>
Here, the actual expression to be used for calculating <math>|x|</math> depends on a set of propositions made about <math>x</math>. If <math>x \ge 0</math> is true, then we use the first expression, but if <math>x < 0</math> is the case, then we use the second expression instead. To express this decision process in Haskell using guards, the implementation could look like this:<ref>This function is already provided by Haskell with the name <code>abs</code>, so in a real-world situation you don't need to provide an implementation yourself.</ref>
{{Haskell/Example|1=The absolute value function.|2=<syntaxhighlight lang="haskell">
absolute x
| x < 0 = -x
| otherwise = x
</syntaxhighlight>}}
Remarkably, the above code is about as readable as the corresponding mathematical definition. Let us dissect the components of the definition:
* We start just like a normal function definition, providing a name for the function, <code>absolute</code>, and saying it will take a single argument, which we will name <code>x</code>.
* Instead of just following with the <code>=</code> and the right-hand side of the definition, we enter the two alternatives placed below on separate lines.<ref>We ''could'' have joined the lines and written everything in a single line, but it would be less readable.</ref> These alternatives are the ''guards'' proper. Note that the whitespace (the indentation of the second and third lines) is not just for aesthetic reasons; it is necessary for the code to be parsed correctly.
* Each of the guards begins with a pipe character, <code>|</code>. After the pipe, we put an expression which evaluates to a boolean (also called a boolean condition or a ''predicate''), which is followed by the rest of the definition. The function only uses the equals sign and the right-hand side from a line if the predicate evaluates to <code>True</code>.
* The <code>otherwise</code> case is used when none of the preceding predicates evaluate to <code>True</code>. In this case, if <code>x</code> is not smaller than zero, it must be greater than or equal to zero, so the final predicate could have just as easily been <code>x >= 0</code>; but <code>otherwise</code> works just as well.
{{body note |There is no syntactical magic behind <code>otherwise</code>. It is defined alongside the default variables and functions of Haskell as simply
<syntaxhighlight lang = "haskell">otherwise = True</syntaxhighlight>
This definition makes ''otherwise'' a catch-all guard. As evaluation of the guard predicates is sequential, the <code>otherwise</code> predicate will only be reached if none of the previous cases evaluate to <code>True</code> (so make sure you always place ''otherwise'' as the last guard!). In general, it is a good idea to always provide an <code>otherwise</code> guard, because a rather ugly runtime error will be produced if none of the predicates is true for some input.
}}
{{body note |In the first guard
<syntaxhighlight lang = "haskell"> | x < 0 = -x </syntaxhighlight>
we used the minus sign to negate <code>x</code>. It is worth noting that this way of expressing sign inversion is a special case of sorts, in that the <code>-</code> is ''not'' a function that takes one argument and evaluates to <code>0 - x</code>, but merely a syntactical abbreviation. While very handy, this abbreviation occasionally conflicts with the usage of <code>(-)</code> as an actual function (the subtraction operator), which is a potential source of annoyance (for example, try writing three minus negative-four without using any parentheses for grouping).
That being so, when testing <code>absolute</code> with negative numbers you should call it like this:
{{Haskell/GHCi|1=
Prelude> absolute (-10)
10
}}
}}
=== <code>where</code> and Guards ===
<code>where</code> clauses work well along with guards. For instance, consider a function which computes the number of unique (real) solutions for a [[w:Quadratic equation|quadratic equation]], <math>ax^2 + bx + c = 0</math>: <!-- I don't like this example, but still couldn't think of anything more meaningful with only bare numbers. Suggestions are welcome... -->
<syntaxhighlight lang = "haskell">
numOfRealSolutions a b c
| disc > 0 = 2
| disc == 0 = 1
| otherwise = 0
where
disc = b^2 - 4*a*c
</syntaxhighlight>
The <code>where</code> definition is within the scope of all of the guards, sparing us from repeating the expression for <code>disc</code>.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Haskell Basics|noexercises=1}}
hynfm4fiegezn64lst77hd8rac5cz4x
Haskell/Type basics II
0
228915
4675920
4415983
2026-10-13T22:53:34Z
Luciérnaga de conocimiento
3401314
4675920
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Haskell Basics|noexercises=1}}
In this chapter, we will show how numerical types are handled in Haskell and introduce some important features of the type system. Before diving into the text, though, pause for a moment and consider the following question: what should be the type of the function <code>(+)</code>?<ref>If you followed our recommendations in "Type basics", chances are you have already seen the rather exotic answer by testing with <code>:t</code>... if that is the case, consider the following analysis as a path to understanding the meaning of that signature.</ref>
== The <code>Num</code> class ==
Mathematics puts few restrictions on the kinds of numbers we can add together. Consider, for instance, <math>2 + 3</math> (two natural numbers), <math>(-7) + 5.12</math> (a negative integer and a rational number), or <math>\frac{1}{7} + \pi</math> (a rational and an irrational). All of these are valid. In fact, any two real numbers can be added together. In order to capture such generality in the simplest way possible we need a general <code>Number</code> type in Haskell, so that the signature of <code>(+)</code> would be simply
<syntaxhighlight lang = "haskell">
(+) :: Number -> Number -> Number
</syntaxhighlight>
However, that design fits poorly with the way computers perform arithmetic. While computers can handle integers as a sequence of binary digits in memory, that approach does not work for real numbers,<ref>Among other issues, between any two real numbers there are uncountably many real numbers – and that fact can't be directly mapped into a representation in memory no matter what we do.</ref> thus making a more complicated encoding necessary for dealing with them: [[w:Floating point|floating point numbers]]. While floating point provides a reasonable way to deal with real numbers in general, it has some inconveniences (most notably, loss of precision) which makes using the simpler encoding worthwhile for integer values. So, we have at least two different ways of storing numbers: one for integers and another for general real numbers. Each approach should correspond to different Haskell types. Furthermore, computers are only able to perform operations like <code>(+)</code> on a pair of numbers if they are in the same format.
So much for having a universal <code>Number</code> type – it seems that we can't even have <code>(+)</code> mix integers and floating-point numbers. However, Haskell ''can'' at least use the same <code>(+)</code> function with either integers or floating point numbers. Check this yourself in GHCi:
{{Haskell/GHCi|1=
Prelude> 3 + 4
7
Prelude> 4.34 + 3.12
7.46
}}
When discussing lists and tuples, we saw that functions can accept arguments of different types if they are made ''polymorphic''. In that spirit, here's a possible type signature for <code>(+)</code> that would account for the facts above:
<syntaxhighlight lang = "haskell">
(+) :: a -> a -> a
</syntaxhighlight>
With that type signature, <code>(+)</code> would take two arguments of the same type <code>a</code> (which could be integers or floating-point numbers) and evaluate to a result of type <code>a</code> (as long as both arguments are the same type). But this type signature indicates ''any'' type at all, and we know that we can't use <code>(+)</code> with two <code>Bool</code> values, or two <code>Char</code> values. What would adding two letters or two truth-values mean? So, the ''actual'' type signature of <code>(+)</code> uses a language feature that allows us to express the semantic restriction that <code>a</code> can be any type ''as long as it is a number type'':
<syntaxhighlight lang = "haskell">
(+) :: (Num a) => a -> a -> a
</syntaxhighlight>
<code>Num</code> is a '''typeclass''' — a group of types — which includes all types which are regarded as numbers.<ref>This is a loose definition, but will suffice until we discuss typeclasses in more detail.</ref> The <code>(Num a) =></code> part of the signature restricts <code>a</code> to number types – or, in Haskell terminology, ''instances'' of <code>Num</code>.
== Numeric types ==
So, which are the ''actual'' number types (that is, the instances of <code>Num</code> that the <code>a</code> in the signature may stand for)? The most important numeric types are
<code>Int</code>, <code>Integer</code> and <code>Double</code>:
* <code>Int</code> corresponds to the plain integer type found in most languages. It has fixed maximum and minimum values that depend on a computer's processor. (In 32-bit machines the range goes from -2147483648 to 2147483647).
* <code>Integer</code> also is used for integer numbers, but it supports arbitrarily large values – at the cost of some efficiency.
* <code>Double</code> is the double-precision floating point type, a good choice for real numbers in the vast majority of cases. (Haskell also has <code>Float</code>, the single-precision counterpart of <code>Double</code>, which is usually less attractive due to further loss of precision.)
Several other number types are available, but these cover most in everyday tasks.
=== Polymorphic guesswork ===
If you've read carefully thus far, you know that we don't need to specify types always because the compiler can ''infer'' types. You also know that we cannot mix types when functions require matched types. Combine this with our new understanding of numbers to understand how Haskell handles basic arithmetic like this:
{{Haskell/GHCi|1=
Prelude> (-7) + 5.12
-1.88
}}
This may seem to add two numbers of different types – an integer and a non-integer. Let's see what the types of the numbers we entered actually are:
{{Haskell/GHCi|1=
Prelude> :t (-7)
(-7) :: (Num a) => a
}}
So, <code>(-7)</code> is neither <code>Int</code> nor <code>Integer</code>! Rather, it is a ''polymorphic'' value, which can "morph" into any number type. Now, let's look at the other number:
{{Haskell/GHCi|1=
Prelude> :t 5.12
5.12 :: (Fractional t) => t
}}
<code>5.12</code> is also a polymorphic value, but one of the <code>Fractional</code> class, which is a subset of <code>Num</code> (every <code>Fractional</code> is a <code>Num</code>, but not every <code>Num</code> is a <code>Fractional</code>; for instance, <code>Int</code>s and <code>Integer</code>s are not <code>Fractional</code>).
When a Haskell program evaluates <code>(-7) + 5.12</code>, it must settle for an actual matching type for the numbers. The type inference accounts for the class specifications: <code>(-7)</code> can be any <code>Num</code>, but there are extra restrictions for <code>5.12</code>, so that's the limiting factor. With no other restrictions, <code>5.12</code> will assume the default <code>Fractional</code> type of <code>Double</code>, so <code>(-7)</code> will become a <code>Double</code> as well. Addition then proceeds normally and returns a <code>Double</code>.<ref>''For seasoned programmers:'' This appears to have the same effect that programs in C (and many other languages) manage with an ''implicit cast'' (where an integer literal is silently converted to a double). In C, however, the conversion is done behind your back, while in Haskell it only occurs if the variable/literal is a polymorphic value. This distinction will become clearer shortly, when we show a counter-example.</ref>
The following test will give you a better feel of this process. In a source file, define
<syntaxhighlight lang = "haskell">
x = 2
</syntaxhighlight>
Then load the file in GHCi and check the type of <code>x</code>. Then, change the file to add a <code>y</code> variable,
<syntaxhighlight lang = "haskell">
x = 2
y = x + 3
</syntaxhighlight>
reload it and check the types of <code>x</code> and <code>y</code>. Finally, modify <code>y</code> to
<syntaxhighlight lang = "haskell">
x = 2
y = x + 3.1
</syntaxhighlight>
and see what happens with the types of both variables.
=== Monomorphic trouble ===
The sophistication of the numerical types and classes occasionally leads to some complications. Consider, for instance, the common division operator <code>(/)</code>. It has the following type signature:
<syntaxhighlight lang = "haskell">
(/) :: (Fractional a) => a -> a -> a
</syntaxhighlight>
Restricting <code>a</code> to fractional types is a must because the division of two integer numbers will often result in a non-integer. Nevertheless, we can still write something like
{{Haskell/GHCi|1=
Prelude> 4 / 3
1.3333333333333333
}}
because the literals <code>4</code> and <code>3</code> are polymorphic values and therefore assume the type <code>Double</code> at the behest of <code>(/)</code>. Suppose, however, we want to divide a number by the number of elements in a list.<ref>A reasonable scenario – think of computing an average of the values in a list.</ref> The obvious thing to do would be using the <code>length</code> function, which takes a list and gives the number of elements in it:
{{Haskell/GHCi|1=
Prelude> length [1,2,3]
3
Prelude> 4 / length [1,2,3]
}}
Unfortunately, that blows up:
{{Haskell/GHCi|1=
<interactive>:1:0:
No instance for (Fractional Int)
arising from a use of `/' at <interactive>:1:0-17
Possible fix: add an instance declaration for (Fractional Int)
In the expression: 4 / length [1, 2, 3]
In the definition of `it': it = 4 / length [1, 2, 3]
}}
As usual, the problem can be understood by looking at the type signature of <code>length</code>:
<syntaxhighlight lang = "haskell">
length :: (Foldable t) => t a -> Int
</syntaxhighlight>
For now, let's focus on the type of the result of <code>length</code>. It is <code>Int</code>; the result is not polymorphic. As an <code>Int</code> is not a <code>Fractional</code>, Haskell won't let us use it with <code>(/)</code>.
To escape this problem, we have a special function. Before following on with the text, try to guess what this does only from the name and signature:
<syntaxhighlight lang = "haskell">
fromIntegral :: (Integral a, Num b) => a -> b
</syntaxhighlight>
<code>fromIntegral</code> takes an argument of some <code>Integral</code> type (like <code>Int</code> or <code>Integer</code>) and makes it a polymorphic value. By combining it with <code>length</code>, we can make the length of the list fit into the signature of <code>(/)</code>:
{{Haskell/GHCi|1=
Prelude> 4 / fromIntegral (length [1,2,3])
1.3333333333333333
}}
In some ways, this issue is annoying and tedious, but it is an inevitable side-effect of having a rigorous approach to manipulating numbers. In Haskell, if you define a function with an <code>Int</code> argument, it will never be converted to an <code>Integer</code> or <code>Double</code>, unless you explicitly use a function like <code>fromIntegral</code>. As a direct consequence of its refined type system, Haskell has a surprising diversity of classes and functions dealing with numbers.
== Classes beyond numbers ==
Haskell has typeclasses beyond arithmetic. For example, the type signature of <code>(==)</code> is:
<syntaxhighlight lang = "haskell">
(==) :: (Eq a) => a -> a -> Bool
</syntaxhighlight>
Like <code>(+)</code> or <code>(/)</code>, <code>(==)</code> is a polymorphic function. It compares two values of the same type, which must belong to the class <code>Eq</code> and returns a <code>Bool</code>. <code>Eq</code> is simply the class for types of values which can be compared for equality, and it includes all of the basic non-functional types.<ref>Comparing two functions for equality is considered intractable</ref>
A quite different example of a typeclass that we have glossed over has appeared in the type of <code>length</code>. Given that <code>length</code> takes a list and gives back an <code>Int</code>, we might have expected its type to be:
<syntaxhighlight lang = "haskell">
length :: [a] -> Int
</syntaxhighlight>
The actual type, however, is a little trickier:
<syntaxhighlight lang = "haskell">
length :: (Foldable t) => t a -> Int
</syntaxhighlight>
Beyond lists, there are other kinds of structures that can be used to group values in different ways. Many of these structures (together with lists themselves) belong to a typeclass called <code>Foldable</code>. The type signature of <code>length</code> tells us that it works not only with lists, but also with all those other <code>Foldable</code> structures. Later in the book, we will see examples of such structures, and discuss <code>Foldable</code> in detail. Until then, whenever you see something like <code>Foldable t => t a</code> in a type signature, feel free to mentally replace that with <code>[a]</code>.
Typeclasses add a lot to the power of the type system. We will return to this topic later to see how to use them in custom ways.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Haskell Basics|noexercises=1}}
{{BookCat}}
mpwvp73etwh8q59uumg0jp3qwo2urlo
Relational Database Design/Normalization
0
230433
4676007
4667112
2026-10-14T10:29:36Z
Xieve7
3628394
/* 4NF and 5NF deal with 1-to-many and many-to-many relationships , or multivalued dependencies */ Add link to new multivalued dependency page
4676007
wikitext
text/x-wiki
Database practitioners talk about normalization a lot, but it's often poorly understood. Some people see it as an academic detail that is impractical in the real world. Many practitioners are convinced that normalization is always too costly in terms of performance. In fact there are important practical benefits to normalization. Even though there may be legitimate reasons to eschew normalization in some circumstances, it is always best to make this decision from a standpoint of understanding the costs and benefits than dismissing it out of ignorance.
Normalization provides a set of rules and patterns that can be applied to any database to avoid common logical inconsistencies. Normalizing a database design will typically improve:
* '''Consistency''', since errors that could be made with the database would be structurally impossible
* '''Extensibility''', since changes to the database structure will only affect parts of the database they are logically dependent on
* '''Efficiency''', since redundant information will not need to be stored
The database community has identified several distinct levels of normalization, each more stringent than the last. These are referred to as normal forms and are numbered from one (the lowest form of normalization, referred to as first normal form or 1NF) through five (fifth normal form or 5NF). It's quite common in practice to speak of one database design as being more or less normalized than another, as defined by these levels.
In practical applications, you'll often see 1NF, 2NF, and 3NF along with the occasional 4NF. Fifth normal form is very rarely seen but is briefly discussed in this article. Fifth normal form means that the SQL selecting newbies won't produce misleading results by doing a join with artificial, spurious rows occurring due to a many-to-many dependency, or something equal to or more than a 3-way relationship, which are rare in comparison to the most of the many-to-one that will be detected by the earlier forms.
=== Why perform normalization ? ===
A database is a set of facts about the world. Database administrators would like their database to contain only true facts about the world, and no false facts. Normalization allows the RDBMS to prevent some classes of false fact from occurring in the database, and therefore helps consistency. Obviously much of the information in the database can't be verified by the computer; the only types of error that can be prevented are errors that are inconsistent and entail some logical contradiction. Generally speaking, with each additional level of normalization one or more classes of logical error are made impossible by virtue of the structure of the tables.
An ''anomaly'' occurs in a database if the database starts in a consistent state and an apparently valid action causes the database to become inconsistent. This can be further specified as an ''update'', ''insertion'' or ''deletion anomaly'' depending on whether the action that causes the error is a row update, insertion or deletion respectively.
[[File:Update anomaly.png|500px]]
The example above shows an update anomaly. A database user has attempted to update an employee's address. However, since the address occurs more than once in the table and only one copy has been updated, there is now inconsistent data in the table: the employee cannot have two addresses at once.
[[File:Insertion anomaly.svg|500px]]
This example shows an insertion anomaly. A new faculty member has been hired, but this information cannot be inserted into the database until he has been assigned to teach at least one course.
==== What's an FD ? ====
A Functional Dependency, or FD, looks like
<math>a\rightarrow b</math>
Which means that b is functionally dependent on a. Another way to read this is to say, "a determines b."
The idea here is just that if you know a value for one field (a) then you also know the value for the other field (b). For example, if you know someone's Social Security Number (in the U.S.) then you can find that person's last name, first name, etc. Knowing one piece of data is enough for you to ''determine'' the others.
Another example might be that if you know the serial number on a car, you can also find (determine) the car's manufacturer and model.
<math>\text{serial number} \rightarrow (\text{manufacturer}, \text{model})</math>
Thus manufacturer and model ''depend'' on serial number. This is a functional dependency.
Notice that this relationship often does not work in reverse. If you know a car has a given manufacturer, that is not enough information to find out what its serial number is (since there are many individual cars, with different serial numbers, all made by the same manufacturer).
==== What's the point of knowing Functional Dependencies ? ====
If you don't know your functional dependencies, then forever will you be condemned to reincarnate your update, insertion and deletion anomalies. Contemplate your Functional Dependencies, and you may be able to achieve BCNF (Boyce-Codd normal form) across your whole database, and if not, at least there are two levels in normalization. You could do 3NF, and break the hold of inefficient database design, which your ER modeling did not account for. The point of Functional Dependencies is that they're like used car warranties, and preserving FDs avoids update anomaly costly repairs.
What Boyce-Codd Normal Form does is to connect the dots between the concept of FDs and the concept of relational table key attributes, remembering that any candidate key of a table can be a primary key. In BCNF, all FDs left-hand-sided attributes', are candidate keys.
Consider the negative case, that when one or more FDs are not candidate keys, then the schema is not in BCNF, and
the schema is prone to a lossy join or a functional dependency integrity constraint is not preserved.
=== The normal forms ===
Before we begin our discussion of the normal forms, it's important to point out that they are guidelines and guidelines only. Occasionally, it becomes necessary to stray from them to meet practical business requirements. However, when variations take place, it's extremely important to evaluate any possible ramifications they could have on your system and account for possible inconsistencies. That said, let's explore the normal forms.
Normal forms are as fun as watching legal dramas:
"I swear to tell the truth, the whole truth, and nothing but the truth, so help me god".
"All non-key attributes will tell a fact about the key, the whole key, and nothing but the key, so help me Codd." (about 2NF, 3NF, and BCNF).
Some terms used to understand each of the normal forms:
1NF - atomic values
2NF, 3NF, BCNF - a <u>key</u> is a set of attributes of a relation which can be used to identify a row in a relation. A <u>superkey</u> is a superset of a <u>candidate key</u>, a minimal set of attributes which can be used to identify a row. Hence, all the attributes of a relation can be a superkey.
2NF - non-key attributes are dependent on other non-key attributes, whole candidate keys, but not dependent on a part of a composite key. <br>
3NF - non-key attributes are directly dependent on whole candidate keys, or are a part of a candidate key. <br>
BCNF - non-key attributes are directly dependent on whole candidate keys and are not part of keys.<br>
The above summary seems good enough, but it isn't, because the definition of superkey is that all the attributes of a relation can be a key, and therefore, there are no "non-key" attributes. So it is better to express the normal forms in terms of functional dependency, X -> A "X determines A", or "A depends on X".
2NF then becomes "X cannot be a part of a candidate key, but can be a candidate key, or an attribute of a superkey that is not in the minimal key set of the superkey."
3NF becomes "X is a whole superkey, or A is part of a candidate key".
BCNF becomes "X is a whole superkey"
==== Why have a NF ? ====
1NF - makes it easier to write a query. The example is a Clients table where the Client has three separate phone numbers (perhaps to allow office, home and cellphone numbers to be entered). Your DB is not even 1NF if you have a client / customer table with multiple telephone number fields.
[[File:Relational_DB_example_Clients_table_not_1NF.svg]]
Not being in first normal form makes queries complex and inefficient if you want to look up a client from a given phone number. Since you don't know which of the fields the phone number will appear in, you have to do something like the following:
<syntaxhighlight lang="sql">
SELECT Id
FROM Clients
WHERE FirstPhoneNumber = '555-123-4567'
OR SecondPhoneNumber = '555-123-4567'
OR ThirdPhoneNumber = '555-123-4567';
</syntaxhighlight>
2NF - one textbook says it isn't relevant given 3NF, and BCNF, and is probably being posh about why one splits a table into a parent and child relations linked by a foreign key. An example, like having a client table, is a contractor table, where contractors have more than one skill, and having the contractor-skill table own
a contractor's address field means owning a non-prime attribute that is partially dependent on the whole key contractor-skill, i.e. address determined by contractor only. If a contractor has more than one skill, then there will be redundant rows containing the same contractor name and address. 2NF would mandate splitting the table according to the FDs, N -> A , and the multivalue dependency, N ->-> S, or (<u>Name </u>, Address), and (<u>Name, Skill </u>); as well as being 2NF, this is 3NF, BCNF, and also 4NF.
Why ?
3NF - is like a restrictive form of BCNF, so maybe easier to look at BCNF first to see if it doable, before doing 3NF.
BCNF - the mapping is easier because for every FD X->A, X must be a superkey. This makes it easy to show when breaking a non-normalized 1NF or 2NF relation into
a BC normal form can't be done without losing a conflicting FD, and therefore the decomposition is not <u>dependency preserving</u> , and the normalization should then
revert to 3NF , which can always accommodate for conflicting FDs during attempted BCNF.
3NF - the only additional relaxation is that if a FD X-> A applies, then A can be part of a candidate key. To see a decomposition which is not BCNF because an FD is not preserved, but is 3NF, an example would be helpful, and this author is not cognitive enough to think of one, so some internet and book derived examples will be given,
with the proviso that they may be withdrawn for unrelated socially backward reason (usually legal). The examples are : enrol ( student, class, assistant), with FDs student class -> assistant , assistant -> class ( only allowed to assist one class) , and part_supply, (contract, supplier, department, project, part, quantity, value), with the FDs
1) project part -> contract
2) supplier department -> part
3) project -> supplier , and
4) contract -> the rest of the original relation.
For the original part_supply relation, the second and thirds FDs have determinants X which don't fit the statement "X is a superkey".
The transitive axiom of Armstrong's Axioms suggests that the first FD, 1) Project part -> contract , doesn't make the original relation violate BCNF, because Project,Part is a superkey or alternate key , as it transitively maps to the original singly attributed key, contract.
==== Steps for attempting BCNF decomposition ====
The recommended decomposition step is to use a violating FD which has a single dependent A in X -> A, possible because of another Armstrong Axiom stating X-> A B C , can always be decomposed to X -> A , X->B, X -> C, singly attributed dependent FDs .
(The decomposition axiom is another way of stating the Reflexivity Axiom combined with the Transitivity Axiom, i.e. that if X is a superset of Y then X -> Y, and since, in this instance, A B C is a superset of A, and X -> A B C , so X transitively -> A because A B C -> A. )
Going back to the statement 2 paragraphs back, to use a FD X -> A where
a) A is a single attribute of R , and
b) X must be a subset of R .
c) the FD X -> A is a member of a ''minimal cover set of FDs'' , which implies the original set of FDs have all been transformed into FDs with single dependents, and
no lesser set of FDs can be created with Armstrong's Axioms , that can regenerate the original set of FDs using Armstrong's axioms.
if a) and b), then decompose a relation R into R - A, and X A e.g.
R = ( contract, supllier, department, project, part, quantity, value) , X = supplier department, A = part
So R -A = ( contract, supplier, department, project, quantity, value) , and XA = ( supplier, department, part ).
Because X -> A, X can be a key of XA and X can be joined naturally with R - A , because the attributes of R is a superset of X.
Then step 2 is to check the resulting decomposition relations for BCNF e.g.
in this example, R-A is not BCNF because project -> supplier FD exists, and project is not a superkey of (contract supplier dept project, quantity, value).
Recurse if BCNF is violated, so now R = contract, supplier, dept, project, quantity, value,
the next singly attributed dependent FD is project -> supplier, so remove A (supplier) to form X-A as before, to give( contract , department, project, quantity , value ).
The decomposition is now ,
(supplier, department, part)
(project, supplier)
(contract, department, project, quantity, value)
However, the only remaining violating FD is project, part -> contract , but here X ( project, part) is not a subset of R ( contract, department, project, quantity, value).
Therefore BCNF decomposition cannot continue. At this point, attempting to achieve BCNF is abandoned, and achieving 3NF is the next goal.
==== 3NF decomposition follows on with the products of a failed BCNF decomposition, and achieves a lossless joining , FD preserving decomposition in all cases ====
The technique for decomposition into 3NF is to start with a lossless decomposition of the original relation, and the set of violating FDs. The former is created by the
attempt to decompose into BCNF as above , and the latter is the remaining FDs when the BCNF decomposition cannot proceed any further.
''This is the rationale for starting with BCNF as a goal, because the abandoned results of failure to achieve BCNF can be used to achieve 3NF.''
To achieve 3NF, for every violating FD X -> A, simply add a relation XA . In this example, the last FD , project, part -> contract, can form a relation
so a successful 3NF decomposition is now:
(supplier, department, part)
(project, supplier)
(contract, department, project, quantity, value)
(project, part, contract).
'''To summarize without the example''',
Step 1: Attempt to decompose into BCNF.
Step 2: Attempt to decompose into 3NF.
To do step 1,
a. remember '''Armstrong's axioms''' :
''Reflexivity'', if X is a subset of Y, then Y -> X,
''Transitivity'', if X -> Y and Y -> Z, then X -> Z,
''Augmentation'', if XB -> YB, then X-> Y
Reflexitivy and Transitivity implies ''Decomposition'': ABC -> A , X -> ABC, then X -> A, ( and X->B, and X-> C)
''Union'' is also implied, X -> Y, X -> Z, then X -> YZ
b) convert the original set of FDs , into a minimal covering set of FDs using Armstrong's axioms.
b1. Use Decomposition to make all FDs singly attributed on the right hand side ( singly attributed dependent).
b2. Use Armstrong's axioms to remove redundant determinant attributes , and then
b3. remove equivalent transformed FDs.
c) Use one FD from the remaining set of minimal covering set of FDs.
d) for this FD, X -> A (single), X and A must be respectively a subset and a member of R 's attributes. i.e. R is a superset of X union A .
e) remove from A from R , to get R - A as one decomposition product, and another relation X A as another decomposition product (i.e. attributes making X and A ).
f) remove the used FD from the covering set of FDs, and go back to c). , using the set of relations - R, union with each decomposition product R -A, and X A as the source set of relations to be decomposed , and continue until t all the minimal covering set of FDs has been exhausted (emptied),
or the remaining singly attributed FDs cannot be used to decompose any of the growing set of decomposed relations.
If there are remaining FDs, then BCNF cannot be achieved whilst preserving all FDs.
Switch to 3NF covering relation generation by constructing:
Get each FD that is part of a residual minimal set of FDs i.e. each FD is of the form X-> A where A is a singly attributed dependent, with Armstrong's axioms applied to remove any redundancy on the determinant side (X), and then removing any remaining essentially equivalent FDs , until no more FDs can be removed without losing the ability to reconstruct the original set of FDs.
With this FD, construct a relation XA and remove the FD from the remaining set of FDs; continue until all FDs are processed.
==== The sales pitch for normalization ====
The resulting set of relations , either from successful BCNF conversion, or from BCNF/3NF conversion, can be recomposed by joins into the original relation without loss or generation of spurious rows, and preserves all the original functional dependencies. Update, insertion and deletion anomalies should not occur when using these normalized relations.
==== 4NF and 5NF deal with 1-to-many and many-to-many relationships , or multivalued dependencies ====
Achieving BCNF may achieve 4NF if the resulting decomposed relations have single attributed keys. A [[Relational Database Design/Multivalued dependency|multivalued dependency]] is expressed as X ->-> A,
which means for every instance of X, there is a fixed set of A values, which are ''independent'' of any other attributes except X. In fact, a FD X -> A where each X value implies a single A value, is a special case of MVD.
For instance, <code>stereotype_expertise</code> is a multivalued relation, with stereotype values / multivalued dependency expertise instances:
<pre>
medical_graduate ->-> physiology, anatomy , pharmacology ;
computer_science_graduate ->-> concrete mathematics, database design, programming ;
idiot ->-> pharmacology, database design.
</pre>
In 4NF, a multivalue dependency will always hold if the determinant and the multivalued dependents of this single MVD are the only attributes of the relation,
or if the determinant is a superkey and there are other attributes apart from X, Y in the MVD X->-> Y. This last criteria doesn't make sense, because if X is a superkey, then there is only one row for each X.
The rationale for 4NF is illustrated by the example of a relation which has 2 ''independent'' multivalue dependencies, e.g. Person Skill Language.
A person has a set of skills, and a set of languages. An example of a design problem is when a person adds a language, there is a design choice :
have null values for skill in the row with the new person language detail, to having always a cross product of skills and language for every person,
so for each row of cross product skill and language , have person, so this facilitates a search for someone with a certain skill and language.
In this kind of table, person cannot be a candidate key, due to multiple skill + language mappings, and actually all 3 attributes form the key.
So by 4NF, this relation needs to be decomposed until all MVDs X->->Y have either only X Y as attributes , or X is a superkey ( which really doesn't make
sense since there are multiple Y for a X ). [[What is the 4NF decomposition of Person Skill Language ?]]
[http://www.bkent.net/Doc/simple5.htm#label4
William Kent, "A Simple Guide to Five Normal Forms in Relational Database Theory", Communications of the ACM 26(2), Feb. 1983, 120-125]
==== 5NF ====
This author's good but slightly inconsistent textbook states that
<blockquote>
a 3NF decomposition relation is in 5NF if there is no candidate key in the relation which is composite.
</blockquote>
Presumably, a composite key can be projected with only one of its two or more attributes, into a smaller decomposition, which when re-joined, with the rest of the relation , will result in spurious rows. 5NF is like a declarative version of the procedural decomposition of BCNF by its functional dependencies, and the patching with additional single FD relations of 3NF, except it is being applied to MVDs as well, in that the lossless join condition is incorporated into the definition of join dependency, which is that a 5NF relation can be decomposed into any set of smaller relations, and all of these can be rejoined without spurious rows.
=== Normal Forms, without the logic fetish ===
==== 1NF ====
First normal form (1NF) sets the very basic rules for an organized database:
Eliminate duplicate columns from the same table.
Create separate tables for each group of related data and identify each row with a unique column or set of columns (the primary key).
==== 2NF ====
Second normal form (2NF) further addresses the concept of removing duplicate data:
Meet all the requirements of the first normal form.
Remove subsets of data that apply to multiple rows of a table and place them in separate tables.
Create relationships between these new tables and their predecessors through the use of foreign keys.
==== 3NF ====
Third normal form (3NF) goes one large step further:
Meet all the requirements of the second normal form.
Remove columns that are not dependent upon the primary key.
If a remaining column ( attribute) plays a part in a functional dependency, all the attributes of the functional dependency
are in the table, and the determinants of the attribute form a key, or all the dependent attributes are keying attributes.
The latter means that another table which has the determinant attributes as a key, maps these determinant attributes against the dependent
attributes , and these form a foreign key into this table.
==== Boyce-Codd NF ====
If an attribute of a table plays a part as a determinant attribute in a functional dependency, then it and all the other determinant attributes of the functional dependency
are in the table and all of them together form a superset of or are equal to a key of the table. All the dependent attributes of the functional dependency are also in the table.
==== 4NF ====
Fourth normal form (4NF) has one additional requirement:
Meet all the requirements of the third normal form.
A relation is in 4NF if it is in BCNF and it has a single column key,
or the table only has attributes of one multivalued dependency, or the determinant of
the multivalued dependency is a superset of or equal to a the key.
==== 5th Normal Form (5NF) ====
The purpose of 5NF is to achieve a lossless join decomposition with respect to all the candidate keys of a relation.
5NF is defined in terms of not breaking join dependencies that hold over a relation. A Join dependency is a statement that
a particular decomposition will result in a lossless recomposition. A multivalued dependency, is a special case of a join dependency,
expressed as a subrelation consisting of the MVDs determinant and dependent attributes, and a subrelation consisting of all the other attributes
in the original relation and the MVDs determinant attributes, and hence the join occurs on the determinant attributes.
A paper showed that if a 3NF relation has all candidate keys as single attributes, then all join dependencies will hold (there will be
no decomposition involving candidate keys which will lead to a lossy recomposition).
==== Domain-Key NF ====
''Domain-Key Normal Form'' eliminates insertion and deletion anomalies while relying only on domain constraints and key constraints (no arbitrary <code>CHECK</code> constraints are needed). Unfortunately there is no general method for transforming a database into DKNF, so it is usually the hardest normal form to achieve.
=== Denormalization ===
After reading about Normalization above and how things should be broken up, you may be thinking:
<code>Well, now I have all these tables all over the place, and I have to join a buncha them just to get simple sets of data out of the system! How is that gonna affect the performance?</code>
Well, you may be right. In some cases where performance is an issue, it may be necessary to ''denormalize'' parts of your database/schema and have wider tables that may contain duplicated/redundant data.
However, such decisions are best left in the hands of an experienced DBA, because there may be other ways to improve performance such as physical design, indexes, query optimization, etc. that DBA's specialize in. Database Denormalization, just like Normalization, is best left in the hands of the experienced.
But if you were cocky enough to want to be good at Database Denormalization, then reading a chapter out of a good database textbook about database tuning would help;
the one I read, simply reiterated the previous lessons about Boyce-Codd Normalization and 3NF Normalization, and the choice between the two, so that there is already a
denormalization step from BCNF to 3NF when attempting to achieve the normalization goals of no lossy joins and functional dependency preservation. This book also goes on
to talk briefly about using update, insert, and delete, SQL triggers to enforce functional dependencies, that aren't being enforced because of denormalization, and then
to compare the query plan and execution costs of these triggers, vs the query plan and execution costs of preserving normalization , and hence the costs of mandatory joins for some queries, the latter often requiring the creation of indexes to lower the cost of joins where only a small proportion of rows are needed in the query.
{{BookCat}}
ila2wv7h44zh81zmtl0adilwjeyox7a
Template:Haskell/GHCiExample
10
234152
4675883
3292322
2026-10-13T17:59:23Z
Luciérnaga de conocimiento
3401314
4675883
wikitext
text/x-wiki
{{HaskellExample|1={{{1}}}|2=
{{HaskellGHCi|1={{{2}}}}}
}}<noinclude><!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentation|content=This template is used for Haskell GHCi transcript examples in Haskell books.
The content is automatically colored following [[Template:Haskell/GHCi]].
If you want to display Haskell code examples use [[Template:Haskell/Example]].
Example:
<pre><nowiki>
{{HaskellGHCi/Example|1=Source example|2=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
</nowiki></pre>
Is rendered as:
{{HaskellGHCi/Example|1=Source example|2=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
The <code>{{!}}1=</code> and <code>{{!}}2=</code> are necessary as the text may contain equal signs. Otherwise just <code>{{{1}}}</code> would get displayed.
}}{{BookCat}}</noinclude>
eq4gymsvw9au8t4nuh0q22wkbnop9z1
4675884
4675883
2026-10-13T17:59:53Z
Luciérnaga de conocimiento
3401314
4675884
wikitext
text/x-wiki
{{HaskellExample|1={{{1}}}|2=
{{HaskellGHCi|1={{{2}}}}}
}}<noinclude><!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentation|content=This template is used for Haskell GHCi transcript examples in Haskell books.
The content is automatically colored following [[Template:Haskell/GHCi]].
If you want to display Haskell code examples use [[Template:Haskell/Example]].
Example:
<pre><nowiki>
{{HaskellGHCi/Example|1=Source example|2=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
</nowiki></pre>
Is rendered as:
{{Haskell/GHCiExample|1=Source example|2=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
The <code>{{!}}1=</code> and <code>{{!}}2=</code> are necessary as the text may contain equal signs. Otherwise just <code>{{{1}}}</code> would get displayed.
}}{{BookCat}}</noinclude>
5vnq7kz1t7jbp9dqwwdli42auxuuybn
4675885
4675884
2026-10-13T18:00:19Z
Luciérnaga de conocimiento
3401314
4675885
wikitext
text/x-wiki
{{Haskell/Example|1={{{1}}}|2=
{{HaskellGHCi|1={{{2}}}}}
}}<noinclude><!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentation|content=This template is used for Haskell GHCi transcript examples in Haskell books.
The content is automatically colored following [[Template:Haskell/GHCi]].
If you want to display Haskell code examples use [[Template:Haskell/Example]].
Example:
<pre><nowiki>
{{HaskellGHCi/Example|1=Source example|2=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
</nowiki></pre>
Is rendered as:
{{Haskell/GHCiExample|1=Source example|2=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
The <code>{{!}}1=</code> and <code>{{!}}2=</code> are necessary as the text may contain equal signs. Otherwise just <code>{{{1}}}</code> would get displayed.
}}{{BookCat}}</noinclude>
g1xggvlgui9n89mg4vt522e27vd4jc3
4675886
4675885
2026-10-13T18:00:27Z
Luciérnaga de conocimiento
3401314
4675886
wikitext
text/x-wiki
{{Haskell/Example|1={{{1}}}|2=
{{Haskell/GHCi|1={{{2}}}}}
}}<noinclude><!-- It is important that there is no linebreak before the noinclude or it causes an empty line after the template when it's used. -->
{{Documentation|content=This template is used for Haskell GHCi transcript examples in Haskell books.
The content is automatically colored following [[Template:Haskell/GHCi]].
If you want to display Haskell code examples use [[Template:Haskell/Example]].
Example:
<pre><nowiki>
{{HaskellGHCi/Example|1=Source example|2=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
</nowiki></pre>
Is rendered as:
{{Haskell/GHCiExample|1=Source example|2=
Prelude> let f a b = a * b
Prelude> f 3 5
15
Prelude>
}}
The <code>{{!}}1=</code> and <code>{{!}}2=</code> are necessary as the text may contain equal signs. Otherwise just <code>{{{1}}}</code> would get displayed.
}}{{BookCat}}</noinclude>
6m9c9134lpmg5t2klwbv3dklcipm4j8
Talk:Radiation Oncology/Breast/Post mastectomy
1
240256
4675974
1934549
2026-10-14T05:58:27Z
Jcb
90773
4675974
wikitext
text/x-wiki
To Add:
*{{PMID|19811918}}
sbbpnfna4wuw6gfgiyhr9zyh9vctrzo
Structural Biochemistry/Proteins/Protein Folding Problem
0
242427
4675968
3259786
2026-10-14T05:27:34Z
Jcb
90773
4675968
wikitext
text/x-wiki
[[File:SPX.png|thumb|SPX]]
[[File:Heading.png|thumb|Heading]]
The “protein folding problem” consists of three closely related puzzles:
#What is the folding code?
#What is the folding mechanism?
#Can we predict the native structure of a protein from its amino acid sequence?
== Protein Folding Problem ==
The Protein Folding Problem is the obstacle that scientists confront when they try to predict 3D structure of proteins based on their amino acid sequence. Although it is known that a given sequence of amino acids almost always folds into a 3D structure with certain functions, it is impossible to predict, with high precision, the exact folding pattern. Understanding the speed of proteins folding, which occurs extremely quickly, has also become a challenge to scientists. To be able to understand any type of biochemical reaction requires isolation and structure determination of reactants, intermediates and products. In protein folding, the isolation of reactants, intermediates and products is complicated because most interactions in proteins are non-covalent and weak interactions which lead to rapid rates of interconversion between each reaction state. Therefore, the isolation of intermediates is not easily achieved and therefore inaccessible for X-ray crystallography. In addition, several advances in protein folding research have been made in characterizing reactants and intermediates. Based on the complexity of protein folding, there are 3 major problems of protein folding: The folding code, structure prediction and the folding speed and mechanism.
== The Three Folding Problems ==
=== The Folding Code ===
In the late 1980s, scientists discovered that there is a sequence of amino acid code that folds proteins in a particular way. The starting point of protein folding is indeed the primary structure (the sequence of amino acids), also known as denatured state of the protein. Even the smallest amount of the denatured state can activate nucleation and proliferation carried out through protein folding pathways. Characterization of these denatured states of proteins at physiological conditions is very difficult because it is necessary to unfold the proteins to their denatured states without the presence of denaturants [2, Travagilini-Allocatelli et al.].
Recent research has allowed the study of denatured states to reach new heights using the single-molecule approach. Researchers used single-molecule experiments to examine coil to globule transition of proteins and have demonstrated that the denatured state showed steady expansion as the concentration of denaturant was increased. Similarly, at low denaturant concentrations, the peptide chain of the protein collapsed in a sequence dependent manner [2, Travagilini-Allocatelli et al.].
Also there have been advancements to study intermediates in protein folding. For example, the denatured state of the engrailed homeodomian (En-HD) was engineered to be denatured in physiological conditions and Nuclear Magnetic Resonance (NMR) has shown that it resembles a folding intermediate. An additional study discovered that the specific section of the En-HD called the helix-turn-helix motif (HTH) behaves as an independent folding domain. When examining the full protein, the HTH motif represents a folding intermediate in the En-HD folding pathway [2, Travagilini-Allocatelli et al.].
Although the folding of protein is still an enigma, scientists have taken the advantage of these protein information to design new materials, such as medicine, reagents and inhibitors, to benefit the society.
=== Structure Prediction ===
Nowadays, researchers predict the structure of a protein by inputting the amino acid sequence into a computer. The advanced technology and modeling software allow scientists and researchers to form a predicted structure. However, the structure is not accurate, as there is always a small degree of errors present. Nevertheless, this can speed up discovery of new medications since the digital structure can be manipulated.
'''Secondary structure prediction'''
Secondary structure prediction is a set of techniques that aim to predict the secondary structures of proteins and RNA sequences based only on their primary structure which is amino acid or nucleotide sequence. For example, proteins, a prediction consists of assigning regions of the amino acid sequence as alpha helices, beta strands, or turns. The success of a prediction is determined by comparing it to the results of the DSSP (the DSSP algorithm is the standard method for assigning secondary structure to the amino acids of a protein, given the atomic-resolution coordinates of the protein) algorithm applied to the crystal structure of the protein; for nucleic acids, it may be determined from the hydrogen bonding pattern. Specialized algorithms have been developed for the detection of specific well defined patterns such as transmembrane helices and coiled coils in proteins, or microRNA structures in RNA.
'''Tertiary structure prediction'''
Experimental methods such as NMR spectroscopy or x-ray diffraction analysis are widely used in order to determine tertiary protein structures. But the rate at which protein structures can be determined by experimental techniques is much lower than the rate at which new genes are identified by the various genome projects.
'''''Ab initio protein modelling''''' methods have been used to build 3-D protein models. For example, based on physical principles rather than on previously solved structures. There are many possible procedures that either attempt to mimic protein folding or apply some stochastic method to search possible solutions (like, global optimization of a suitable energy function). These procedures require massive computational resources, and have thus only been carried out for tiny proteins. To predict protein structure for larger proteins will require better algorithms and larger computational resources like those afforded by either powerful supercomputers. Although these computational barriers are massive, the potential benefits of structural prediction make ab initio an active research topic.
'''''Side-chain geometry prediction''''' describes a computational approach that can make predictions for a series of coiled-coil dimers. This method comprises a dual strategy that augments extensive conformational sampling with molecular mechanics minimization.
'''Quaternary structure'''
In the case of complexes of two or more proteins, where the structures of the proteins are known or can be predicted with high accuracy, protein–protein docking methods can be used to predict the structure of the complex.
[[File:Annexin II.png|thumb|Annexin II]]
=== Folding Speed and Mechanism ===
In 1968, Cyrus Levinthal pointed out that protein folding, with precision, happens in microseconds, which seems unrealistic and impossible. This is also known as the Levinthal's paradox. Nowadays, we have advanced methods such as mutational methods, which give us the value of phi and psi during folding, and hydrogen exchange methods, which allow us to see structural folding events. However, the dynamics and mechanism of protein folding still require additional research and understanding.
The dynamics and kinetics of unfolded polypeptide chain have been addressed by recent studies of loop formation by Keifhaber and coworkers. They used different model systems each representing different types of loops: end to end, end to interior, or interior to interior. Their experiments showed that end to interior and interior to interior loop formation formed slower than end to end loops. This discovery suggests that chain motion of one part of the unfolded polypeptide chain is coupled to other parts of the chain. These kinetics experiments also revealed that protein folding processes take place on different time scales and thus there is a hierarchy in loop formation[2, Travagilini-Allocatelli et al.].
Although additional research is necessary to understand mechanisms in protein folding, there are two different classical mechanisms that have been used to describe folding of single domain proteins. The first of the mechanisms is called the '''Diffusion-Collision Model'''. Proteins that follow this mechanism fold in a stepwise manner that involves growing secondary structure elements. These elements then collide, combine and strengthen. For example, there is evidence that the En-HD mentioned above follows the diffusion-collision model. The second mechanism is known as the '''Nucleation-Condensation Model'''. Proteins following this method have been seen to fold from an unstructured denatured state with simultaneous formation of secondary and tertiary structure. For example, a homologous protein of En-HD called hTRF1 has been shown to follow this model. However, there are many proteins that exhibit characteristic pathways of both diffusion-collision and nucleation-condensation models [2, Travagilini-Allocatelli et al.].
The starting point of protein folding: the denatured state
In the denatured state, the structure can trigger nucleation and propagation, which may carry through the folding pathway. Characterization of denatured states of proteins at physical conditions represents a hard task as needed to disfavor the population of native states without adding denaturants. Chemically denatured states may act like random-coil polymer at high denaturant concentrations.
Sherman and Haran used single-molecule experiments to analyze the coil to globule transition of protein L and showed that the denatured state of the protein increases as the denaturant concentration increases. Also Eaton and co-workers compared the size and dynamics of the denatured states of those two proteins, displaying a similar length of 64 and 66 amino acids.
Mechanisms of protein folding
There were two different mechanism used to describe the folding of single-domain proteins. Some proteins such as barnase, has been described to fold in a stepwise manner with rapid formation of distinct nuclei and also with their collision and consolidation. There are also other proteins, with chymotrypsin inhibitor 2 as an example of the nucleation-condensation model.
The folding pathway of the small alpha beta protein domain has been shown to be distinct from the pure nucleation-condensation and diffusion-collision, but still displaying the characteristics of both models.
Folding stability and function
The inherent stability of individual protein segment is a key factor in determining the folding mechanism of a given protein. Many times, cell’s life relies on the ability of its constituent proteins to fold into 3D structures that are crucial for their function. The amount of folded functional protein in a cell depends on several factors such as, rate of protein biosynthesis and degradation.
There was a question about whether the stability and folding of fully folded proteins can be related to their activity. Allostery can be the bridge where protein folding meets function. Allosteric effects involve communication between ligand binding sites which is critical to many physiological processes.
As allostery is a thermodynamic process, it should not only be considered by changes in conformation but also by changes in the dynamics of the mean conformation.
Therefore more research is necessary to fully comprehend the mechanism of protein folding and find a solution to the protein folding problem.
== Reference ==
# Ken A Dill, S Banu Ozkan, Thomas R Weikl, John D Chodera and Vincent A Voelz. ''The protein folding problem: when will it be solved?''Current Opinion in Structural Biology 2007.
#Carlo Travaglini-Allocatelli, Yiva Ivarsson, Per Jemth and Stefano Gianni. ''Folding and stability of globula proteins and implications for function'' Current Opinion in Structural Biology 2009, 19:3-7.
#Mount DM (2004). Bioinformatics: Sequence and Genome Analysis. 2. Cold Spring Harbor Laboratory Press. {{ISBN|0879697121}}
#Zhang Y (2008). "Progress and challenges in protein structure prediction". Curr Opin Struct Biol 18 (3): 342–8. doi:10.1016/j.sbi.2008.02.004. PMC 2680823. {{PMID|18436442}}
{{BookCat}}
8sl71k8t29tb3hvhckswfbutf3wcc5l
Haskell/Using GHCi effectively
0
245553
4675955
4666175
2026-10-14T00:45:14Z
~2026-54868-50
3628373
4675955
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Elementary Haskell|noexercises=1}}
GHCi assists in several ways toward more efficient work. Here, we will discuss some of the best practices for using GHCi.
==User interface==
===Tab completion===
As in many other terminal programs, you can enter some starting text in GHCi and then hit the Tab key to be presented with a list of all possibilities that start with what you've written so far. When there is only one possibility, using Tab will auto-complete the string. For example <code>fol</code><code><Tab></code> will append letter "d" (since nothing exists with "fol" other than items that start with "fold"). A second <code>Tab</code> will list the four functions included in Prelude: <code>foldl</code>, <code>foldl1</code>, <code>foldr</code>, and <code>foldr1</code>. More options may show if you have already imported additional modules.
Tab completion works also when you are loading a file with your program into GHCi. For example, after typing <code>:l fi</code><code><Tab></code>, you will be presented with all files that start with "fi" that are present in the current directory (the one you were in when you launched GHCi).
The same also applies when you are importing modules, after typing <code>:m +Da</code><code><Tab></code> or <code>import Da</code><code><Tab></code>, you will be presented with all modules that start with "Da" present in installed packages.
===": commands"===
On GHCi command line, commands for the interpreter start with the character ":" (colon).
* <code>:help</code> or <code>:h</code> -- prints a list of all available commands.
* <code>:load</code> or <code>:l</code> -- loads a given file into GHCi (you must include the filename with the command).
* <code>:reload</code> or <code>:r</code> -- reloads whatever file had been loaded most recently (useful after changes to the file).
* <code>:type</code> or <code>:t</code> -- prints the type of a given expression included with the command
* <code>:module</code> or <code>:m</code> -- loads a given module (include the module name with the command). You can also ''un''load a module by adding a <code>-</code> symbol before the module name.
* <code>:browse</code> -- gives the type signatures for all functions available from a given module.
Here again, you can use <code>Tab</code> to see the list of commands, type :<code>Tab</code> to see all possible commands.
===Timing Functions in GHCi===
GHCi provides a basic way to measure how much time a function takes to run, which can be useful for to find out which version of a function runs fastest (such as when there are multiple ways to define something to get the same effective result).
# Type <code>:set +s</code> into the ghci command line.
# run the function(s) you are testing. The time the function took to run will be displayed after GHCi outputs the results of the function.
===Multi-line Input===
If you are trying to define a function that takes up multiple lines, or if you want to type a do block into ghci (without writing a file that you then import), there is an easy way to do this:
# Begin a new line with <code>:{</code>
# Type in your code. Press enter when you need a new line.
# Type <code>:}</code> to end the multi-line input.
For example:
*Main> :{
*Main| let askname = do
*Main| putStrLn "What is your name?"
*Main| name <- getLine
*Main| putStrLn $ "Hello " ++ name
*Main| :}
*Main>
The same can be accomplished by using <code>:set +m</code> command (allow multi-line commands). In this case, an empty line will end the block.
In addition, line breaks in ghci commands can be separated by <code>;</code>, like this:
*Main> let askname1 = do ; putStrLn "what is your name?" ; name <- getLine ; putStrLn $ "Hello " ++ name
{{Haskell navigation|chapter=Elementary Haskell|noexercises=1}}
{{BookCat}}
fed7u6t9or5zothq2ooset5w3aicmy1
4675956
4675955
2026-10-14T00:45:35Z
~2026-54868-50
3628373
4675956
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Elementary Haskell|noexercises=1}}
GHCi assists in several ways toward more efficient work. Here, we will discuss some of the best practices for using GHCi.
==User interface==
===Tab completion===
As in many other terminal programs, you can enter some starting text in GHCi and then hit the Tab key to be presented with a list of all possibilities that start with what you've written so far. When there is only one possibility, using Tab will auto-complete the string. For example <code>fol</code><code><Tab></code> will append letter "d" (since nothing exists with "fol" other than items that start with "fold"). A second <code>Tab</code> will list the four functions included in Prelude: <code>foldl</code>, <code>foldl1</code>, <code>foldr</code>, and <code>foldr1</code>. More options may show if you have already imported additional modules.
Tab completion works also when you are loading a file with your program into GHCi. For example, after typing <code>:l fi</code><code><Tab></code>, you will be presented with all files that start with "fi" that are present in the current directory (the one you were in when you launched GHCi).
The same also applies when you are importing modules, after typing <code>:m +Da</code><code><Tab></code> or <code>import Da</code><code><Tab></code>, you will be presented with all modules that start with "Da" present in installed packages.
===": commands"===
On GHCi command line, commands for the interpreter start with the character ":" (colon).
* <code>:help</code> or <code>:h</code> -- prints a list of all available commands.
* <code>:load</code> or <code>:l</code> -- loads a given file into GHCi (you must include the filename with the command).
* <code>:reload</code> or <code>:r</code> -- reloads whatever file had been loaded most recently (useful after changes to the file).
* <code>:type</code> or <code>:t</code> -- prints the type of a given expression included with the command
* <code>:module</code> or <code>:m</code> -- loads a given module (include the module name with the command). You can also ''un''load a module by adding a <code>-</code> symbol before the module name.
* <code>:browse</code> -- gives the type signatures for all functions available from a given module.
Here again, you can use <code>Tab</code> to see the list of commands, type :<code>Tab</code> to see all possible commands.
===Timing Functions in GHCi===
GHCi provides a basic way to measure how much time a function takes to run, which can be useful for to find out which version of a function runs fastest (such as when there are multiple ways to define something to get the same effective result).
# Type <code>:set +s</code> into the ghci command line.
# run the function(s) you are testing. The time the function took to run will be displayed after GHCi outputs the results of the function.
===Multi-line Input===
If you are trying to define a function that takes up multiple lines, or if you want to type a do block into ghci (without writing a file that you then import), there is an easy way to do this:
# Begin a new line with <code>:{</code>
# Type in your code. Press enter when you need a new line.
# Type <code>:}</code> to end the multi-line input.
For example:
*Main> :{
*Main| let askname = do
*Main| putStrLn "What is your name?"
*Main| name <- getLine
*Main| putStrLn $ "Hello " ++ name
*Main| :}
*Main>
The same can be accomplished by using <code>:set +m</code> command (allow multi-line commands). In this case, an empty line will end the block.
In addition, line breaks in ghci commands can be separated by <code>;</code>, like this:
*Main> let askname1 = do ; putStrLn "what is your name?" ; name <- getLine ; putStrLn $ "Hello " ++ name
{{Haskell/Navigation|chapter=Elementary Haskell|noexercises=1}}
{{BookCat}}
ia90e19sh7snj15vyfwo1rifsupgaju
OpenSSH
0
248395
4675847
4663124
2026-10-13T14:19:41Z
Larsnooden
430753
New Shodan search
4675847
wikitext
text/x-wiki
{{Featured book}}
OpenSSH was first released in late 1999, and has been actively developed ever since. It is the latest step in a very long and useful history of networked computing, remote access, and telecommuting.
The OpenSSH suite provides secure remote access and file transfer.<ref name="OpenSSH_homepage">{{cite web | url=http://www.openssh.com/ | title=OpenSSH | publisher=www.openssh.com}}</ref> Since its initial release, it has grown to become the most widely used implementation of the SSH protocol. During the first ten years of its existence, it had largely replaced older corresponding unencrypted tools and protocols.
The OpenSSH client is included by default in most operating system distributions, including MacOS, AIX, Linux, BSD, and Solaris. Any day you use the Internet, you are using and relying on hundreds if not thousands of machines operated and maintained using OpenSSH. A survey in 2008 showed that of the SSH servers found running, just over 80% were OpenSSH. <ref name="OpenSSH_marketshare_2008">{{cite web |url=http://www.openssh.com/usage/ssh-stats.html
|title=Statistics from the current scan results |publisher=OpenSSH.com |year=2008}}</ref> Even with the advent of the Internet of Things and the increased use of IPv6, a cursory search of Shodan <ref name="OpenSSH_marketshare_shodan">{{cite web |url=https://www.shodan.io/search/facet?query=ssh-2.0&facet=product | title=SSH-2.0 Search Results |publisher=shodan.io|accessdate=2026-10-13}}</ref> for SSH 2.0 services, on any port, in October 2026 showed 92% of responding addresses running OpenSSH. <ref>On October 13, 2026, OpenSSH's 92% was 36,841,871 out of 39,640,574 systems. Dropbear made up just over 1% at 469,091 systems and then a long tail filled in the rest. </ref>
This book is for fellow users of OpenSSH to help save effort and time through using OpenSSH, and especially SFTP, where it makes sense to use it.
__NOTOC__
<noinclude>{{OpenSSH/TOC|mini}}
</noinclude>
<noinclude>
{{print version}}
{{PDF version|OpenSSH}}
{{Collection|OpenSSH}}
{{Statistics}}
</noinclude>
<noinclude>
===Introduction===
*[[/Overview/]]
*[[/Why Use Encryption/]]
*[[/SSH Protocols/]]
*[[/Other SSH Implementations/]]
===Client-Server===
*[[/Client Applications/]]
*[[/Client Configuration Files/]]
*[[/Server/|OpenSSH Server]]
*[[/Pattern Matching in OpenSSH Configuration/]]
===Utilities===
*[[/Utilities/]]
*[[/Third_Party_Utilities/|Third Party Utilities]]
===Logging, Troubleshooting, and Development===
*[[/Logging_and_Troubleshooting|Logging and Troubleshooting]]
*[[/Development/]]
===Cookbook===
*[[/Cookbook/Remote_Processes/|Remote Processes]]
*[[/Cookbook/Tunnels|Tunnels]]
*[[/Cookbook/Automated_Backup|Automated Backup]]
*[[/Cookbook/File_Transfer_with_SFTP| File Transfer with SFTP]]
*[[/Cookbook/Public Key Authentication|Public Key Authentication]]
*[[/Cookbook/Certificate-based_Authentication/|Certificate-based Authentication]]
*[[/Cookbook/Host-based_Authentication/|Host-based Authentication]]
*[[/Cookbook/Load_balancing/|Load Balancing]]
*[[/Cookbook/Multiplexing/|Multiplexing]]
*[[/Cookbook/Proxies_and_Jump_Hosts|Proxies and Jump Hosts]]
== References ==
</noinclude>
{{reflist}}
{{Shelves|Internet|Open source software|Computing|System administration}}
<noinclude>
{{alphabetical|O}}
</noinclude>
{{status|100%}}
avgkm88tcx50ksnjnup31xvd3obcj1j
4675852
4675847
2026-10-13T14:26:57Z
Larsnooden
430753
Put some old market share data from 2022 back
4675852
wikitext
text/x-wiki
{{Featured book}}
OpenSSH was first released in late 1999, and has been actively developed ever since. It is the latest step in a very long and useful history of networked computing, remote access, and telecommuting.
The OpenSSH suite provides secure remote access and file transfer.<ref name="OpenSSH_homepage">{{cite web | url=http://www.openssh.com/ | title=OpenSSH | publisher=www.openssh.com}}</ref> Since its initial release, it has grown to become the most widely used implementation of the SSH protocol. During the first ten years of its existence, it had largely replaced older corresponding unencrypted tools and protocols.
The OpenSSH client is included by default in most operating system distributions, including MacOS, AIX, Linux, BSD, and Solaris. Any day you use the Internet, you are using and relying on hundreds if not thousands of machines operated and maintained using OpenSSH. A survey in 2008 showed that of the SSH servers found running, just over 80% were OpenSSH. <ref name="OpenSSH_marketshare_2008">{{cite web |url=http://www.openssh.com/usage/ssh-stats.html
|title=Statistics from the current scan results |publisher=OpenSSH.com |year=2008}}</ref> Even with the advent of the Internet of Things and the increased use of IPv6, a cursory search of Shodan <ref name="OpenSSH_marketshare_shodan">{{cite web |url=https://www.shodan.io/search/facet?query=ssh-2.0&facet=product | title=SSH-2.0 Search Results |publisher=shodan.io|accessdate=2026-10-13}}</ref> for SSH 2.0 services, on any port, in October 2026 showed 92% of responding addresses running OpenSSH. Previously, in November 2022, around 87% of the responding addresses were running OpenSSH. Previously, in November 2022, around 87% of the responding addresses were running OpenSSH. <ref>On October 13, 2026, OpenSSH's 92% was 36,841,871 out of 39,640,574 systems. Dropbear made up just over 1% at 469,091 systems and then a long tail filled in the rest. </ref>
This book is for fellow users of OpenSSH to help save effort and time through using OpenSSH, and especially SFTP, where it makes sense to use it.
__NOTOC__
<noinclude>{{OpenSSH/TOC|mini}}
</noinclude>
<noinclude>
{{print version}}
{{PDF version|OpenSSH}}
{{Collection|OpenSSH}}
{{Statistics}}
</noinclude>
<noinclude>
===Introduction===
*[[/Overview/]]
*[[/Why Use Encryption/]]
*[[/SSH Protocols/]]
*[[/Other SSH Implementations/]]
===Client-Server===
*[[/Client Applications/]]
*[[/Client Configuration Files/]]
*[[/Server/|OpenSSH Server]]
*[[/Pattern Matching in OpenSSH Configuration/]]
===Utilities===
*[[/Utilities/]]
*[[/Third_Party_Utilities/|Third Party Utilities]]
===Logging, Troubleshooting, and Development===
*[[/Logging_and_Troubleshooting|Logging and Troubleshooting]]
*[[/Development/]]
===Cookbook===
*[[/Cookbook/Remote_Processes/|Remote Processes]]
*[[/Cookbook/Tunnels|Tunnels]]
*[[/Cookbook/Automated_Backup|Automated Backup]]
*[[/Cookbook/File_Transfer_with_SFTP| File Transfer with SFTP]]
*[[/Cookbook/Public Key Authentication|Public Key Authentication]]
*[[/Cookbook/Certificate-based_Authentication/|Certificate-based Authentication]]
*[[/Cookbook/Host-based_Authentication/|Host-based Authentication]]
*[[/Cookbook/Load_balancing/|Load Balancing]]
*[[/Cookbook/Multiplexing/|Multiplexing]]
*[[/Cookbook/Proxies_and_Jump_Hosts|Proxies and Jump Hosts]]
== References ==
</noinclude>
{{reflist}}
{{Shelves|Internet|Open source software|Computing|System administration}}
<noinclude>
{{alphabetical|O}}
</noinclude>
{{status|100%}}
k1ofpecgcw3am3prtln4v5x0tlfp10z
4675855
4675852
2026-10-13T14:32:19Z
Larsnooden
430753
rounding error
4675855
wikitext
text/x-wiki
{{Featured book}}
OpenSSH was first released in late 1999, and has been actively developed ever since. It is the latest step in a very long and useful history of networked computing, remote access, and telecommuting.
The OpenSSH suite provides secure remote access and file transfer.<ref name="OpenSSH_homepage">{{cite web | url=http://www.openssh.com/ | title=OpenSSH | publisher=www.openssh.com}}</ref> Since its initial release, it has grown to become the most widely used implementation of the SSH protocol. During the first ten years of its existence, it had largely replaced older corresponding unencrypted tools and protocols.
The OpenSSH client is included by default in most operating system distributions, including MacOS, AIX, Linux, BSD, and Solaris. Any day you use the Internet, you are using and relying on hundreds if not thousands of machines operated and maintained using OpenSSH. A survey in 2008 showed that of the SSH servers found running, just over 80% were OpenSSH. <ref name="OpenSSH_marketshare_2008">{{cite web |url=http://www.openssh.com/usage/ssh-stats.html
|title=Statistics from the current scan results |publisher=OpenSSH.com |year=2008}}</ref> Even with the advent of the Internet of Things and the increased use of IPv6, a cursory search of Shodan <ref name="OpenSSH_marketshare_shodan">{{cite web |url=https://www.shodan.io/search/facet?query=ssh-2.0&facet=product | title=SSH-2.0 Search Results |publisher=shodan.io|accessdate=2026-10-13}}</ref> for SSH 2.0 services, on any port, in October 2026 showed about 93% of responding addresses running OpenSSH. Previously, in November 2022, around 87% of the responding addresses were running OpenSSH. Previously, in November 2022, around 87% of the responding addresses were running OpenSSH. <ref>On October 13, 2026, OpenSSH's 92% was 36,841,871 out of 39,640,574 systems. Dropbear made up just over 1% at 469,091 systems and then a long tail filled in the rest. </ref>
This book is for fellow users of OpenSSH to help save effort and time through using OpenSSH, and especially SFTP, where it makes sense to use it.
__NOTOC__
<noinclude>{{OpenSSH/TOC|mini}}
</noinclude>
<noinclude>
{{print version}}
{{PDF version|OpenSSH}}
{{Collection|OpenSSH}}
{{Statistics}}
</noinclude>
<noinclude>
===Introduction===
*[[/Overview/]]
*[[/Why Use Encryption/]]
*[[/SSH Protocols/]]
*[[/Other SSH Implementations/]]
===Client-Server===
*[[/Client Applications/]]
*[[/Client Configuration Files/]]
*[[/Server/|OpenSSH Server]]
*[[/Pattern Matching in OpenSSH Configuration/]]
===Utilities===
*[[/Utilities/]]
*[[/Third_Party_Utilities/|Third Party Utilities]]
===Logging, Troubleshooting, and Development===
*[[/Logging_and_Troubleshooting|Logging and Troubleshooting]]
*[[/Development/]]
===Cookbook===
*[[/Cookbook/Remote_Processes/|Remote Processes]]
*[[/Cookbook/Tunnels|Tunnels]]
*[[/Cookbook/Automated_Backup|Automated Backup]]
*[[/Cookbook/File_Transfer_with_SFTP| File Transfer with SFTP]]
*[[/Cookbook/Public Key Authentication|Public Key Authentication]]
*[[/Cookbook/Certificate-based_Authentication/|Certificate-based Authentication]]
*[[/Cookbook/Host-based_Authentication/|Host-based Authentication]]
*[[/Cookbook/Load_balancing/|Load Balancing]]
*[[/Cookbook/Multiplexing/|Multiplexing]]
*[[/Cookbook/Proxies_and_Jump_Hosts|Proxies and Jump Hosts]]
== References ==
</noinclude>
{{reflist}}
{{Shelves|Internet|Open source software|Computing|System administration}}
<noinclude>
{{alphabetical|O}}
</noinclude>
{{status|100%}}
ld8ekq6ta23s4vmriaozt5qvjjpd87o
4675859
4675855
2026-10-13T14:41:29Z
Larsnooden
430753
rounding error
4675859
wikitext
text/x-wiki
{{Featured book}}
OpenSSH was first released in late 1999, and has been actively developed ever since. It is the latest step in a very long and useful history of networked computing, remote access, and telecommuting.
The OpenSSH suite provides secure remote access and file transfer.<ref name="OpenSSH_homepage">{{cite web | url=http://www.openssh.com/ | title=OpenSSH | publisher=www.openssh.com}}</ref> Since its initial release, it has grown to become the most widely used implementation of the SSH protocol. During the first ten years of its existence, it had largely replaced older corresponding unencrypted tools and protocols.
The OpenSSH client is included by default in most operating system distributions, including MacOS, AIX, Linux, BSD, and Solaris. Any day you use the Internet, you are using and relying on hundreds if not thousands of machines operated and maintained using OpenSSH. A survey in 2008 showed that of the SSH servers found running, just over 80% were OpenSSH. <ref name="OpenSSH_marketshare_2008">{{cite web |url=http://www.openssh.com/usage/ssh-stats.html
|title=Statistics from the current scan results |publisher=OpenSSH.com |year=2008}}</ref> Even with the advent of the Internet of Things and the increased use of IPv6, a cursory search of Shodan <ref name="OpenSSH_marketshare_shodan">{{cite web |url=https://www.shodan.io/search/facet?query=ssh-2.0&facet=product | title=SSH-2.0 Search Results |publisher=shodan.io|accessdate=2026-10-13}}</ref> for SSH 2.0 services, on any port, in October 2026 showed about 93% of responding addresses running OpenSSH. Previously, in November 2022, around 87% of the responding addresses were running OpenSSH. Previously, in November 2022, around 87% of the responding addresses were running OpenSSH. <ref>On October 13, 2026, OpenSSH's 93% was 36,841,871 out of 39,640,574 systems. Dropbear made up just over 1% at 469,091 systems and then a long tail filled in the rest. </ref>
This book is for fellow users of OpenSSH to help save effort and time through using OpenSSH, and especially SFTP, where it makes sense to use it.
__NOTOC__
<noinclude>{{OpenSSH/TOC|mini}}
</noinclude>
<noinclude>
{{print version}}
{{PDF version|OpenSSH}}
{{Collection|OpenSSH}}
{{Statistics}}
</noinclude>
<noinclude>
===Introduction===
*[[/Overview/]]
*[[/Why Use Encryption/]]
*[[/SSH Protocols/]]
*[[/Other SSH Implementations/]]
===Client-Server===
*[[/Client Applications/]]
*[[/Client Configuration Files/]]
*[[/Server/|OpenSSH Server]]
*[[/Pattern Matching in OpenSSH Configuration/]]
===Utilities===
*[[/Utilities/]]
*[[/Third_Party_Utilities/|Third Party Utilities]]
===Logging, Troubleshooting, and Development===
*[[/Logging_and_Troubleshooting|Logging and Troubleshooting]]
*[[/Development/]]
===Cookbook===
*[[/Cookbook/Remote_Processes/|Remote Processes]]
*[[/Cookbook/Tunnels|Tunnels]]
*[[/Cookbook/Automated_Backup|Automated Backup]]
*[[/Cookbook/File_Transfer_with_SFTP| File Transfer with SFTP]]
*[[/Cookbook/Public Key Authentication|Public Key Authentication]]
*[[/Cookbook/Certificate-based_Authentication/|Certificate-based Authentication]]
*[[/Cookbook/Host-based_Authentication/|Host-based Authentication]]
*[[/Cookbook/Load_balancing/|Load Balancing]]
*[[/Cookbook/Multiplexing/|Multiplexing]]
*[[/Cookbook/Proxies_and_Jump_Hosts|Proxies and Jump Hosts]]
== References ==
</noinclude>
{{reflist}}
{{Shelves|Internet|Open source software|Computing|System administration}}
<noinclude>
{{alphabetical|O}}
</noinclude>
{{status|100%}}
gnkxndnuxbpkiysp2kxwg234wwnr8qh
OpenSSH/SSH Protocols
0
248397
4675838
4629158
2026-10-13T13:52:24Z
Larsnooden
430753
Update Privilege Separation process overview
4675838
wikitext
text/x-wiki
OpenSSH uses the SSH protocol which connects over TCP. Normally, one SSH session per TCP connection is made, but multiple sessions can be multiplexed over a single TCP connection if planned that way. The current set of Secure Shell protocols is SSH2. It is a rewrite of the old, deprecated SSH1 protocol. It contains significant improvements in security, performance, and portability. The default is now SSH2 and SSH1 support has been removed from both the client and server.
[[File:SSH-sequence-password.svg|frame|right|Sequence Diagram for SSH Password Authentication]]
The Secure Shell protocol is an open standard. As such, it is vendor-neutral and maintained by the Internet Engineering Task Force (IETF). The current protocol is described in RFC 4250 through RFC 4256 and standardized by the IETF secsh working group. The overall structure of SSH2 is described in RFC 4251, The Secure Shell (SSH) Protocol Architecture.
The SSH protocol is composed of three layers: the transport layer, the authentication layer, and the connection layer.
:'''SSH-CONNECT''' – The connection layer runs over the user authentication protocol. It multiplexes many different concurrent encrypted channels into logical channels over the authenticated connection. It allows for tunneling of login sessions and TCP-forwarding. It provides a flow control service for these channels. Additionally, various channel-specific options can be negotiated. This layer manages the SSH session, session multiplexing, X11 forwarding, TCP forwarding, shell, remote program execution, invoking SFTP subsystem.
:'''SSH-USERAUTH''' – The user authentication layer authenticates the client-side to the server. It uses the established connection and runs on top of the transport layer. It provides several mechanisms for user authentication. These include password authentication, public-key or host-based authentication mechanisms, challenge-response, pluggable authentication modules (PAM), Generic Security Services API (GSSAPI) and even dongles.
:'''SSH-TRANS''' – The transport layer provides server authentication, confidentiality and data integrity over TCP. It does this through algorithm negotiation and a key exchange. The key exchange includes server authentication and results in a cryptographically secured connection: it provides integrity, confidentiality and optional compression. <ref name="OpenSSH-Manual">{{cite web |url=https://www.openssh.org/manual.html |title=OpenSSH Manual Pages |publisher=OpenSSH| accessdate=2026-04-03}}</ref>
Among the differences between the current protocol, SSH2, and the deprecated SSH1 protocol, is that SSH2 uses host keys for authentication. Whereas SSH1 used both server and host keys to authenticate. There's not much which can be added about the protocols which is not already covered with more detail and authority in RFC 4251 <ref name="RFC42511">{{cite web |url=http://tools.ietf.org/html/rfc4251 | title=RFC 4251: The Secure Shell (SSH) Protocol Architecture | date=2006 |accessdate=2013-10-31}}</ref>.
==SSH File Transfer Protocol (SFTP)==
The SSH File Transfer Protocol (SFTP) is a binary protocol to provide secure file transfer, access and management.
SFTP was added by Markus Friedl on the server side in time for the 2.3.0 release of OpenSSH in November 2000. Damien Miller added support for SFTP to the client side in time for 2.5.0. Since then, many have added to both the client and the server.
===SFTP is not FTPS===
For basic file transfer, nothing more is needed than an account on the machine with the OpenSSH server. SFTP support is built into the OpenSSH server package. The SFTP protocol, in contrast to old FTP, has been designed from the ground up to be as secure as possible for both login and data transfer.
{{RightHalf|'''[[w:Samba_(software)|Samba]]''' is an interoperability suite providing fast file and print services for any client which can use the SMB/CIFS protocol. It is most often used for file sharing at the level of the local area network. }}
{{RightHalf|'''[[w:Andrew_File_System|AFS]]''', or the Andrew File System, is a distributed file system providing file sharing at an institutional level across a geographically diverse institution or set of collaborating institutions. Notably it provides a set of trusted servers and a homogeneous, location-transparent file name space to all the client workstations. }}
Unless the use-case calls for publicly available, read-only, downloads, don't worry about trying to fiddle with FTP. It is the protocol FTP itself that is inherently insecure. It's great for read-only, public data transfer. The programs '''vsftpd''' and '''proftpd''', for example, are secure insofar as the server software itself goes, although the protocol itself is still insecure. In other words the program itself is more or less fine and if you need to provide read-only, publicly available downloads then FTP maybe the right tool. Otherwise forget about FTP.
Nearly always when users ask for "FTP" they don't mean specifically the old file transfer protocol from 1971 as described in RFC 114, but a generic means of file transfer and there are many ways to solve that problem. This is especially true since the next part of their request is usually how to make it secure. The name "FTP" is frequently mis-used generically to mean any file transfer utility, much the same way as the term "Coke" is used in some of Southern United States to mean any carbonated soft drink, not just Coca-Cola. Consider SFTP or, for larger groups, even SSHFS, [[w:Samba_(software)|Samba]], or [[w:Andrew_File_System|AFS]]. While old FTP succeeded very well in achieving its main goal to promote use of networked computers by allowing users at any host on the network to use the file system of any cooperating host, it cannot be made secure. There's nothing to be done about that, so it is past time to get over it.
Again, it is the protocol itself, FTP, which is the problem.<ref name="StopUsingFTP1">{{cite web |url=http://blog.jdpfu.com/2011/07/10/why-you-need-to-stop-using-ftp |title=Why You Need To Stop Using FTP |publisher=JDPFu.com| date=2011-07-10 | accessdate=2012-01-09}}</ref> With FTP, the data, passwords and user name are all sent back and forth unencrypted.<ref name="StopUsingFTP2">{{cite web |url=http://olex.openlogic.com/wazi/2011/stop-using-ftp-how-to-transfer-files-securely/ |title=Stop Using FTP! How to Transfer Files Securely | author=Manolis Tzanidakis | publisher=Wazi| date=2011-09-09 | accessdate=2012-01-09}}</ref> Anyone on the client's subnet, the server's subnet or any subnet in between can 'sniff' the passwords and data when FTP is used. With extra effort it is possible to wrap FTP inside SSL or TLS, thus creating FTPS. However, tunneling FTP over SSL/TLS is complex to do and far from an optimum solution.
Unfortunately because of name confusion combined with the large number of posts and discussions created by complex, nit-picky tasks like wrapping FTP in SSL to provide FTPS, the wrong way still turns up commonly in web searches regarding file transfer. In contrast, easy, relatively painless solutions vanish because it is rarely necessary to post how to do those. Also, an easy solution can be summed up in very few lines and maybe a single answer. Thus, there is still a lot of talk online about 'securing' FTP and very little mention of using SFTP. It's a vicious cycle that this book hopes to help break: Difficult tasks mean lots of discussion and noise, lots of discussion and noise means strong web presence, strong web presence means high Google ranking.
SFTP tools are very common, but might be taken for granted and thus overlooked. SFTP tools are easy to use and more functional than old FTP clients. In fact a lot of improvements have been made in usability. There is no shortage of common, GUI-based SFTP clients to transfer files: Filezilla, Konqueror, Dolphin, Nautilus, Cyberduck, Fugu, and Fetch top the list but there are many more. Most are Free Software.
Again, these SFTP clients are very easy to use. For example, in Konqueror, just type in the URL to the sftp server, where the server name or address is xx.yy.zz.aa.
<pre>
sftp://xx.yy.zz.aa
</pre>
If it is desirable to start with a particular directory, then that too can be specified.
<pre>
sftp://xx.yy.zz.aa/var/www/pictures/
</pre>
One special client worth knowing about is '''sshfs'''. With '''sshfs''' as an SFTP client the other machine is accessible as an open folder on your machine's local file system. In that way any program you normally have to work with files, such as LibreOffice, Inkscape or Gimp can access the remote machine via that folder.
===Background of FTP===
FTP is from the 1970s. It's a well proven workhorse, but from an era when if you were on the net you were supposed to be there and if there was trouble it could usually be cleared up with a short phone call or an e-mail or two. It sends the login name, password and all of the data unencrypted for anyone to intercept.
FTP clients can connect to the FTP server in either passive or active modes. Both active and passive modes for FTP<ref name="activepassiveFTP">{{cite web |url=http://slacksite.com/other/ftp.html | title=Active FTP vs. Passive FTP, a Definitive Explanation | date=2002 |accessdate=2020-03-20 | publisher=Slacksite.com | author=Jay Ribak}}</ref> use two ports, one for control and one for data. In FTP Active mode, after the client makes a connection to the FTP server it then allows an incoming connection to be initiated from the server to for data transfer. In FTP Passive mode, after the client makes a connection to the FTP server, the server then responds with information about a second port for data transfer and the client initiates the second connection.
FTP is most relevant now as Anonymous FTP, which is still excellent for read-only downloads without login. FTP is still one way to go for transferring read-only data, as would be using the web (HTTP or HTTPS), or a P2P protocol like Bittorrent. So there are other options than FTP for offering read-only downloads. Preference is given lately to HTTPS for small files and Bittorrent for large files or large groups of files.
====Using tcpdump to show FTP activity====
An illustration of how the old protocol, FTP, is insecure can be had from the utility '''tcpdump'''. It can show what is going over the network during an Anonymous FTP session, or for that matter any FTP session. Look at the manual page for '''tcpdump''' for an explanation of the individual arguments, the usage example below displays the first FTP or FTP-Data packets going from the client to the server and vice versa.
The output below shows an excerpt from the output of '''tcpdump''' which captured packets between an FTP client and the FTP server, one line per packet.
<syntaxhighlight lang="shell">
$ sudo tcpdump -q -s 0 -c 10 -A -i eth0 \
"tcp and (port ftp or port ftp-data)"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
…
:18:36.010820 IP desk.55227 > server.ftp: tcp 16 E..D..@.@.....1.[.X.....G.r. ........l..... ."......USER anonymous
:18:36.073192 IP server.ftp > desk.55227: tcp 0 E..4jX@.7.3.[.X...1..... ...G.r#........... ....."..
:18:36.074019 IP server.ftp > desk.55227: tcp 34 E..VjY@.7.3.[.X...1..... ...G.r#....Y...... ....."..331 Please specify the password.
:18:36.074042 IP desk.55227 > server.ftp: tcp 0 E..4..@.@..+..1.[.X.....G.r# ..)........... ."......
:18:42.098941 IP desk.55227 > server.ftp: tcp 23 E..K..@.@.....1.[.X.....G.r# ..)....gv..... .".w....PASS user@example.net
:18:42.162692 IP server.ftp > desk.55227: tcp 23 E..KjZ@.7.3.[.X...1..... ..)G.r:........... .....".w230 Login successful.
…
:18:43.431827 IP server.ftp > desk.55227: tcp 14 E..Bj\@.7.3.[.X...1..... ..SG.rF.....j..... ....."..221 Goodbye.
…
</syntaxhighlight>
As can be seen in lines 3 and 7, data such as text from the server is visible. In lines 1 and 5, text entered by the user is visible and in this case it includes the user name and password used to log in. Fortunately the session is Anonymous FTP, which is read-only and used for downloading. Anonymous FTP is a rather efficient way to publish material for download. For Anonymous FTP, the user name is always "anonymous" and the password is the user’s e-mail address and the server's data always read-only.
If you have the package for the OpenSSH server already installed, no further configuration of the server is needed to start using SFTP for file transfers. Though comparatively speaking, FTPS is significantly more secure than FTP. If you want remote remote login access, then both FTP and FTPS should be avoided. A very large reason to avoid both is to save work.
===On FTPS===
FTPS is FTP tunneled over SSL or TLS. A goal of FTP was to encourage the use of remote computers which, along with the web, has succeeded. A goal of FTPS was to secure logins and transfers, and it was a necessary step in securing file transfers with the legacy protocol. However, since SFTP is so much easier to deploy and most systems now include both graphical and text-based SFTP clients, FTPS can really be considered deprecated for most occasions.
Some good background material can be found in the Request for Comments (RFCs) for FTP and FTPS. There, SFTP and even HTTPS are better matches and largely supersede FTPS. See the section on [[OpenSSH/Client Applications|Client Applications]] for an idea of the SFTP clients available.
==Privilege Separation==
Privilege separation is when a process is divided into sub-processes, each of which have just enough access to just the right parts of the system to do their part of the job. The goal of privilege separation is to compartmentalize any corruption and prevent a corrupt process from accessing other parts of the system. An underlying principle is that of least privilege, which is where each process has exactly enough privileges to accomplish a task, neither more nor less. Currently it's like this <ref name="Splitting_of_sshd_binaries_in_9_8">{{cite web |url=https://lists.mindrot.org/pipermail/openssh-unix-dev/2024-July/041486.html |title=Splitting of sshd binaries in 9.8? |publisher=openssh-unix-dev Mailing List | date=2024-07-17 | accessdate=2024-07-30}}</ref>:
<pre>
sshd [listener]
|
exec
|
sshd-session [privsep monitor]
| |
| fork (for auth)
| |
| sshd-auth: [net unpriv]
|
fork (after auth completes)
|
sshd-session [postauth unpriv]
</pre>
First, a privileged binary listens for incoming connections, seen here as PID 68746.
<syntaxhighlight lang="shell-session">
$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root 68746 1 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)
</syntaxhighlight>
Once a connection starts, it is passed off to a separate privileged monitor binary (seen as PID 53341 below) which makes an unprivileged fork (seen as PID 17952 below) under the account 'sshd' to address authentication.
<syntaxhighlight lang="shell-session">
$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root 68746 1 sshd: /usr/sbin/sshd [listener] 1 of 10-100 startups (sshd)
root 53341 68746 sshd-session: fred [priv] (sshd-session)
sshd 17952 53341 sshd-auth: fred [net] (sshd-auth)
</syntaxhighlight>
The fork owned by 'sshd' is terminated. If the authentication succeeds a new process (seen as PID 94635 below) owned by the authenticated account is forked from from the privileged monitor to deal with the session itself. At which point, the privileged monitor switches to its post-authentication state and runs until the unprivileged child exits.
<syntaxhighlight lang="shell-session">
$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root 68746 1 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)
root 53341 68746 sshd-session: fred [postauth] (sshd-session)
fred 30090 53341 sshd-session: fred@ttyp2 (sshd-session)
</syntaxhighlight>
This is a work in progress and future developments may move the post authentication, unprivileged process into a separate binary. The portable edition might acquire a PAM helper binary which would be called by the privilege separation monitor. But at least through 10.6, the above is managed through fork + exec.
Privilege separation has been the default in OpenSSH since version 3.3<ref name="Provos_Privilege_Separation">{{cite web |url=http://www.citi.umich.edu/u/provos/ssh/privsep.html |title=Privilege Separated OpenSSH |publisher=University of Michigan| author=Nils Provos| date=2003| accessdate=2011-02-17}}</ref> Starting with version 5.9, privilege separation further applies mandatory restrictions on which system calls the privilege separated child can perform. The intent is to prevent a compromised privilege separated child from being used to attack other hosts either by opening sockets and proxying or by probing the local kernel attack surface. <ref name="OpenSSH_release_notes_5.9">{{cite web |url=https://www.openssh.org/txt/release-5.9 |title=OpenSSH 5.9 Release Notes |publisher=OpenSSH | date=2011-09-06 | accessdate=2026-04-03}}</ref> Since version 6.1, this sandboxing has been the default.
[[File:OpenSSH-Privilege-Separation.svg|frame|right|Sequence Diagram for OpenSSH Privilege Separation]]
===Old Privilege Separation Prior to 9.8===
Privilege separation is applied in OpenSSH by using several levels of access, some higher some lower, to run [http://man.openbsd.org/sshd.8 sshd(8)] and its subsystems and components. The SSH server ➊ starts out with a privileged process ➋ which then creates an unprivileged process ➌ to work with the network traffic. Once the user has authenticated, another unprivileged process is created ➍ with the privileges of that authenticated user. See the "Sequence Diagram for OpenSSH Privilege Separation". As seen in the diagram, a total of four processes get run to create an SSH session. One process, the server, remains and listens for new connections and spawn new child processes.
<syntaxhighlight lang="shell-session">
$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1'
USER PID PPID STAT STARTED COMMAND
root 1473 1 I 05:44:01 sshd: /usr/sbin/sshd [listener] 0 of 10-10
</syntaxhighlight>
It is this privileged process that listens for the initial connection from clients. Here it is seen waiting and listening on port 22.
<syntaxhighlight lang="shell-session">
$ netstat -ntlp | awk '/sshd/ || NR<=2'
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1473/sshd
tcp6 0 0 :::22 :::* LISTEN 1473/sshd
</syntaxhighlight>
After the initial connection while waiting for password authentication from user 'fred', a privileged monitor process supervises an unprivileged process by user 'sshd' which handles the contact with the remote user's client.
<syntaxhighlight lang="shell-session">
$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1'
USER PID PPID S STARTED COMMAND
root 1473 1 S 05:44:12 sshd: /usr/sbin/sshd [listener] 1 of 10-10
root 9481 1473 S 14:40:37 sshd: fred [priv]
sshd 9482 9481 S 14:40:37 sshd: fred [net]
</syntaxhighlight>
Then after authentication is completed and a session established for user 'fred', a new privileged monitor process is created to supervise the process running as user 'fred'. At that point the other process running as user 'sshd' has gone away.
<syntaxhighlight lang="shell-session">
$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1'
USER PID PPID S STARTED COMMAND
root 1473 1 S 05:44:12 sshd: /usr/sbin/sshd [listener] 0 of 10-10
root 9481 1473 S 14:40:37 sshd: fred [priv]
fred 9579 9481 S 14:42:02 sshd: fred@pts/30
</syntaxhighlight>
Again, that is for the older method of privilege separation.
<noinclude>
== References ==
{{reflist}}
{{OpenSSH/TOC|mini}}
</noinclude>
{{BookCat}}
{{status|100%}}
rpv4hp9u89q4jy02gxcwyfpsqvaf593
4675840
4675838
2026-10-13T14:01:41Z
Larsnooden
430753
exec -> fork
4675840
wikitext
text/x-wiki
OpenSSH uses the SSH protocol which connects over TCP. Normally, one SSH session per TCP connection is made, but multiple sessions can be multiplexed over a single TCP connection if planned that way. The current set of Secure Shell protocols is SSH2. It is a rewrite of the old, deprecated SSH1 protocol. It contains significant improvements in security, performance, and portability. The default is now SSH2 and SSH1 support has been removed from both the client and server.
[[File:SSH-sequence-password.svg|frame|right|Sequence Diagram for SSH Password Authentication]]
The Secure Shell protocol is an open standard. As such, it is vendor-neutral and maintained by the Internet Engineering Task Force (IETF). The current protocol is described in RFC 4250 through RFC 4256 and standardized by the IETF secsh working group. The overall structure of SSH2 is described in RFC 4251, The Secure Shell (SSH) Protocol Architecture.
The SSH protocol is composed of three layers: the transport layer, the authentication layer, and the connection layer.
:'''SSH-CONNECT''' – The connection layer runs over the user authentication protocol. It multiplexes many different concurrent encrypted channels into logical channels over the authenticated connection. It allows for tunneling of login sessions and TCP-forwarding. It provides a flow control service for these channels. Additionally, various channel-specific options can be negotiated. This layer manages the SSH session, session multiplexing, X11 forwarding, TCP forwarding, shell, remote program execution, invoking SFTP subsystem.
:'''SSH-USERAUTH''' – The user authentication layer authenticates the client-side to the server. It uses the established connection and runs on top of the transport layer. It provides several mechanisms for user authentication. These include password authentication, public-key or host-based authentication mechanisms, challenge-response, pluggable authentication modules (PAM), Generic Security Services API (GSSAPI) and even dongles.
:'''SSH-TRANS''' – The transport layer provides server authentication, confidentiality and data integrity over TCP. It does this through algorithm negotiation and a key exchange. The key exchange includes server authentication and results in a cryptographically secured connection: it provides integrity, confidentiality and optional compression. <ref name="OpenSSH-Manual">{{cite web |url=https://www.openssh.org/manual.html |title=OpenSSH Manual Pages |publisher=OpenSSH| accessdate=2026-04-03}}</ref>
Among the differences between the current protocol, SSH2, and the deprecated SSH1 protocol, is that SSH2 uses host keys for authentication. Whereas SSH1 used both server and host keys to authenticate. There's not much which can be added about the protocols which is not already covered with more detail and authority in RFC 4251 <ref name="RFC42511">{{cite web |url=http://tools.ietf.org/html/rfc4251 | title=RFC 4251: The Secure Shell (SSH) Protocol Architecture | date=2006 |accessdate=2013-10-31}}</ref>.
==SSH File Transfer Protocol (SFTP)==
The SSH File Transfer Protocol (SFTP) is a binary protocol to provide secure file transfer, access and management.
SFTP was added by Markus Friedl on the server side in time for the 2.3.0 release of OpenSSH in November 2000. Damien Miller added support for SFTP to the client side in time for 2.5.0. Since then, many have added to both the client and the server.
===SFTP is not FTPS===
For basic file transfer, nothing more is needed than an account on the machine with the OpenSSH server. SFTP support is built into the OpenSSH server package. The SFTP protocol, in contrast to old FTP, has been designed from the ground up to be as secure as possible for both login and data transfer.
{{RightHalf|'''[[w:Samba_(software)|Samba]]''' is an interoperability suite providing fast file and print services for any client which can use the SMB/CIFS protocol. It is most often used for file sharing at the level of the local area network. }}
{{RightHalf|'''[[w:Andrew_File_System|AFS]]''', or the Andrew File System, is a distributed file system providing file sharing at an institutional level across a geographically diverse institution or set of collaborating institutions. Notably it provides a set of trusted servers and a homogeneous, location-transparent file name space to all the client workstations. }}
Unless the use-case calls for publicly available, read-only, downloads, don't worry about trying to fiddle with FTP. It is the protocol FTP itself that is inherently insecure. It's great for read-only, public data transfer. The programs '''vsftpd''' and '''proftpd''', for example, are secure insofar as the server software itself goes, although the protocol itself is still insecure. In other words the program itself is more or less fine and if you need to provide read-only, publicly available downloads then FTP maybe the right tool. Otherwise forget about FTP.
Nearly always when users ask for "FTP" they don't mean specifically the old file transfer protocol from 1971 as described in RFC 114, but a generic means of file transfer and there are many ways to solve that problem. This is especially true since the next part of their request is usually how to make it secure. The name "FTP" is frequently mis-used generically to mean any file transfer utility, much the same way as the term "Coke" is used in some of Southern United States to mean any carbonated soft drink, not just Coca-Cola. Consider SFTP or, for larger groups, even SSHFS, [[w:Samba_(software)|Samba]], or [[w:Andrew_File_System|AFS]]. While old FTP succeeded very well in achieving its main goal to promote use of networked computers by allowing users at any host on the network to use the file system of any cooperating host, it cannot be made secure. There's nothing to be done about that, so it is past time to get over it.
Again, it is the protocol itself, FTP, which is the problem.<ref name="StopUsingFTP1">{{cite web |url=http://blog.jdpfu.com/2011/07/10/why-you-need-to-stop-using-ftp |title=Why You Need To Stop Using FTP |publisher=JDPFu.com| date=2011-07-10 | accessdate=2012-01-09}}</ref> With FTP, the data, passwords and user name are all sent back and forth unencrypted.<ref name="StopUsingFTP2">{{cite web |url=http://olex.openlogic.com/wazi/2011/stop-using-ftp-how-to-transfer-files-securely/ |title=Stop Using FTP! How to Transfer Files Securely | author=Manolis Tzanidakis | publisher=Wazi| date=2011-09-09 | accessdate=2012-01-09}}</ref> Anyone on the client's subnet, the server's subnet or any subnet in between can 'sniff' the passwords and data when FTP is used. With extra effort it is possible to wrap FTP inside SSL or TLS, thus creating FTPS. However, tunneling FTP over SSL/TLS is complex to do and far from an optimum solution.
Unfortunately because of name confusion combined with the large number of posts and discussions created by complex, nit-picky tasks like wrapping FTP in SSL to provide FTPS, the wrong way still turns up commonly in web searches regarding file transfer. In contrast, easy, relatively painless solutions vanish because it is rarely necessary to post how to do those. Also, an easy solution can be summed up in very few lines and maybe a single answer. Thus, there is still a lot of talk online about 'securing' FTP and very little mention of using SFTP. It's a vicious cycle that this book hopes to help break: Difficult tasks mean lots of discussion and noise, lots of discussion and noise means strong web presence, strong web presence means high Google ranking.
SFTP tools are very common, but might be taken for granted and thus overlooked. SFTP tools are easy to use and more functional than old FTP clients. In fact a lot of improvements have been made in usability. There is no shortage of common, GUI-based SFTP clients to transfer files: Filezilla, Konqueror, Dolphin, Nautilus, Cyberduck, Fugu, and Fetch top the list but there are many more. Most are Free Software.
Again, these SFTP clients are very easy to use. For example, in Konqueror, just type in the URL to the sftp server, where the server name or address is xx.yy.zz.aa.
<pre>
sftp://xx.yy.zz.aa
</pre>
If it is desirable to start with a particular directory, then that too can be specified.
<pre>
sftp://xx.yy.zz.aa/var/www/pictures/
</pre>
One special client worth knowing about is '''sshfs'''. With '''sshfs''' as an SFTP client the other machine is accessible as an open folder on your machine's local file system. In that way any program you normally have to work with files, such as LibreOffice, Inkscape or Gimp can access the remote machine via that folder.
===Background of FTP===
FTP is from the 1970s. It's a well proven workhorse, but from an era when if you were on the net you were supposed to be there and if there was trouble it could usually be cleared up with a short phone call or an e-mail or two. It sends the login name, password and all of the data unencrypted for anyone to intercept.
FTP clients can connect to the FTP server in either passive or active modes. Both active and passive modes for FTP<ref name="activepassiveFTP">{{cite web |url=http://slacksite.com/other/ftp.html | title=Active FTP vs. Passive FTP, a Definitive Explanation | date=2002 |accessdate=2020-03-20 | publisher=Slacksite.com | author=Jay Ribak}}</ref> use two ports, one for control and one for data. In FTP Active mode, after the client makes a connection to the FTP server it then allows an incoming connection to be initiated from the server to for data transfer. In FTP Passive mode, after the client makes a connection to the FTP server, the server then responds with information about a second port for data transfer and the client initiates the second connection.
FTP is most relevant now as Anonymous FTP, which is still excellent for read-only downloads without login. FTP is still one way to go for transferring read-only data, as would be using the web (HTTP or HTTPS), or a P2P protocol like Bittorrent. So there are other options than FTP for offering read-only downloads. Preference is given lately to HTTPS for small files and Bittorrent for large files or large groups of files.
====Using tcpdump to show FTP activity====
An illustration of how the old protocol, FTP, is insecure can be had from the utility '''tcpdump'''. It can show what is going over the network during an Anonymous FTP session, or for that matter any FTP session. Look at the manual page for '''tcpdump''' for an explanation of the individual arguments, the usage example below displays the first FTP or FTP-Data packets going from the client to the server and vice versa.
The output below shows an excerpt from the output of '''tcpdump''' which captured packets between an FTP client and the FTP server, one line per packet.
<syntaxhighlight lang="shell">
$ sudo tcpdump -q -s 0 -c 10 -A -i eth0 \
"tcp and (port ftp or port ftp-data)"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
…
:18:36.010820 IP desk.55227 > server.ftp: tcp 16 E..D..@.@.....1.[.X.....G.r. ........l..... ."......USER anonymous
:18:36.073192 IP server.ftp > desk.55227: tcp 0 E..4jX@.7.3.[.X...1..... ...G.r#........... ....."..
:18:36.074019 IP server.ftp > desk.55227: tcp 34 E..VjY@.7.3.[.X...1..... ...G.r#....Y...... ....."..331 Please specify the password.
:18:36.074042 IP desk.55227 > server.ftp: tcp 0 E..4..@.@..+..1.[.X.....G.r# ..)........... ."......
:18:42.098941 IP desk.55227 > server.ftp: tcp 23 E..K..@.@.....1.[.X.....G.r# ..)....gv..... .".w....PASS user@example.net
:18:42.162692 IP server.ftp > desk.55227: tcp 23 E..KjZ@.7.3.[.X...1..... ..)G.r:........... .....".w230 Login successful.
…
:18:43.431827 IP server.ftp > desk.55227: tcp 14 E..Bj\@.7.3.[.X...1..... ..SG.rF.....j..... ....."..221 Goodbye.
…
</syntaxhighlight>
As can be seen in lines 3 and 7, data such as text from the server is visible. In lines 1 and 5, text entered by the user is visible and in this case it includes the user name and password used to log in. Fortunately the session is Anonymous FTP, which is read-only and used for downloading. Anonymous FTP is a rather efficient way to publish material for download. For Anonymous FTP, the user name is always "anonymous" and the password is the user’s e-mail address and the server's data always read-only.
If you have the package for the OpenSSH server already installed, no further configuration of the server is needed to start using SFTP for file transfers. Though comparatively speaking, FTPS is significantly more secure than FTP. If you want remote remote login access, then both FTP and FTPS should be avoided. A very large reason to avoid both is to save work.
===On FTPS===
FTPS is FTP tunneled over SSL or TLS. A goal of FTP was to encourage the use of remote computers which, along with the web, has succeeded. A goal of FTPS was to secure logins and transfers, and it was a necessary step in securing file transfers with the legacy protocol. However, since SFTP is so much easier to deploy and most systems now include both graphical and text-based SFTP clients, FTPS can really be considered deprecated for most occasions.
Some good background material can be found in the Request for Comments (RFCs) for FTP and FTPS. There, SFTP and even HTTPS are better matches and largely supersede FTPS. See the section on [[OpenSSH/Client Applications|Client Applications]] for an idea of the SFTP clients available.
==Privilege Separation==
Privilege separation is when a process is divided into sub-processes, each of which have just enough access to just the right parts of the system to do their part of the job. The goal of privilege separation is to compartmentalize any corruption and prevent a corrupt process from accessing other parts of the system. An underlying principle is that of least privilege, which is where each process has exactly enough privileges to accomplish a task, neither more nor less. Currently it's like this <ref name="Splitting_of_sshd_binaries_in_9_8">{{cite web |url=https://lists.mindrot.org/pipermail/openssh-unix-dev/2024-July/041486.html |title=Splitting of sshd binaries in 9.8? |publisher=openssh-unix-dev Mailing List | date=2024-07-17 | accessdate=2024-07-30}}</ref>:
<pre>
sshd [listener]
|
fork
|
sshd-session [privsep monitor]
| |
| fork (for auth)
| |
| sshd-auth: [net unpriv]
|
fork (after auth completes)
|
sshd-session [postauth unpriv]
</pre>
First, a privileged binary listens for incoming connections, seen here as PID 68746.
<syntaxhighlight lang="shell-session">
$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root 68746 1 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)
</syntaxhighlight>
Once a connection starts, it is passed off to a separate privileged monitor binary (seen as PID 53341 below) which makes an unprivileged fork (seen as PID 17952 below) under the account 'sshd' to address authentication.
<syntaxhighlight lang="shell-session">
$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root 68746 1 sshd: /usr/sbin/sshd [listener] 1 of 10-100 startups (sshd)
root 53341 68746 sshd-session: fred [priv] (sshd-session)
sshd 17952 53341 sshd-auth: fred [net] (sshd-auth)
</syntaxhighlight>
The fork owned by 'sshd' is terminated. If the authentication succeeds a new process (seen as PID 94635 below) owned by the authenticated account is forked from from the privileged monitor to deal with the session itself. At which point, the privileged monitor switches to its post-authentication state and runs until the unprivileged child exits.
<syntaxhighlight lang="shell-session">
$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root 68746 1 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)
root 53341 68746 sshd-session: fred [postauth] (sshd-session)
fred 30090 53341 sshd-session: fred@ttyp2 (sshd-session)
</syntaxhighlight>
This is a work in progress and future developments may move the post authentication, unprivileged process into a separate binary. The portable edition might acquire a PAM helper binary which would be called by the privilege separation monitor. But at least through 10.6, the above is managed through fork + exec.
Privilege separation has been the default in OpenSSH since version 3.3<ref name="Provos_Privilege_Separation">{{cite web |url=http://www.citi.umich.edu/u/provos/ssh/privsep.html |title=Privilege Separated OpenSSH |publisher=University of Michigan| author=Nils Provos| date=2003| accessdate=2011-02-17}}</ref> Starting with version 5.9, privilege separation further applies mandatory restrictions on which system calls the privilege separated child can perform. The intent is to prevent a compromised privilege separated child from being used to attack other hosts either by opening sockets and proxying or by probing the local kernel attack surface. <ref name="OpenSSH_release_notes_5.9">{{cite web |url=https://www.openssh.org/txt/release-5.9 |title=OpenSSH 5.9 Release Notes |publisher=OpenSSH | date=2011-09-06 | accessdate=2026-04-03}}</ref> Since version 6.1, this sandboxing has been the default.
[[File:OpenSSH-Privilege-Separation.svg|frame|right|Sequence Diagram for OpenSSH Privilege Separation]]
===Old Privilege Separation Prior to 9.8===
Privilege separation is applied in OpenSSH by using several levels of access, some higher some lower, to run [http://man.openbsd.org/sshd.8 sshd(8)] and its subsystems and components. The SSH server ➊ starts out with a privileged process ➋ which then creates an unprivileged process ➌ to work with the network traffic. Once the user has authenticated, another unprivileged process is created ➍ with the privileges of that authenticated user. See the "Sequence Diagram for OpenSSH Privilege Separation". As seen in the diagram, a total of four processes get run to create an SSH session. One process, the server, remains and listens for new connections and spawn new child processes.
<syntaxhighlight lang="shell-session">
$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1'
USER PID PPID STAT STARTED COMMAND
root 1473 1 I 05:44:01 sshd: /usr/sbin/sshd [listener] 0 of 10-10
</syntaxhighlight>
It is this privileged process that listens for the initial connection from clients. Here it is seen waiting and listening on port 22.
<syntaxhighlight lang="shell-session">
$ netstat -ntlp | awk '/sshd/ || NR<=2'
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1473/sshd
tcp6 0 0 :::22 :::* LISTEN 1473/sshd
</syntaxhighlight>
After the initial connection while waiting for password authentication from user 'fred', a privileged monitor process supervises an unprivileged process by user 'sshd' which handles the contact with the remote user's client.
<syntaxhighlight lang="shell-session">
$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1'
USER PID PPID S STARTED COMMAND
root 1473 1 S 05:44:12 sshd: /usr/sbin/sshd [listener] 1 of 10-10
root 9481 1473 S 14:40:37 sshd: fred [priv]
sshd 9482 9481 S 14:40:37 sshd: fred [net]
</syntaxhighlight>
Then after authentication is completed and a session established for user 'fred', a new privileged monitor process is created to supervise the process running as user 'fred'. At that point the other process running as user 'sshd' has gone away.
<syntaxhighlight lang="shell-session">
$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1'
USER PID PPID S STARTED COMMAND
root 1473 1 S 05:44:12 sshd: /usr/sbin/sshd [listener] 0 of 10-10
root 9481 1473 S 14:40:37 sshd: fred [priv]
fred 9579 9481 S 14:42:02 sshd: fred@pts/30
</syntaxhighlight>
Again, that is for the older method of privilege separation.
<noinclude>
== References ==
{{reflist}}
{{OpenSSH/TOC|mini}}
</noinclude>
{{BookCat}}
{{status|100%}}
2hyewq5ct8li3ibf58df5w6bdh9wqun
4675842
4675840
2026-10-13T14:02:57Z
Larsnooden
430753
fork -> exec
4675842
wikitext
text/x-wiki
OpenSSH uses the SSH protocol which connects over TCP. Normally, one SSH session per TCP connection is made, but multiple sessions can be multiplexed over a single TCP connection if planned that way. The current set of Secure Shell protocols is SSH2. It is a rewrite of the old, deprecated SSH1 protocol. It contains significant improvements in security, performance, and portability. The default is now SSH2 and SSH1 support has been removed from both the client and server.
[[File:SSH-sequence-password.svg|frame|right|Sequence Diagram for SSH Password Authentication]]
The Secure Shell protocol is an open standard. As such, it is vendor-neutral and maintained by the Internet Engineering Task Force (IETF). The current protocol is described in RFC 4250 through RFC 4256 and standardized by the IETF secsh working group. The overall structure of SSH2 is described in RFC 4251, The Secure Shell (SSH) Protocol Architecture.
The SSH protocol is composed of three layers: the transport layer, the authentication layer, and the connection layer.
:'''SSH-CONNECT''' – The connection layer runs over the user authentication protocol. It multiplexes many different concurrent encrypted channels into logical channels over the authenticated connection. It allows for tunneling of login sessions and TCP-forwarding. It provides a flow control service for these channels. Additionally, various channel-specific options can be negotiated. This layer manages the SSH session, session multiplexing, X11 forwarding, TCP forwarding, shell, remote program execution, invoking SFTP subsystem.
:'''SSH-USERAUTH''' – The user authentication layer authenticates the client-side to the server. It uses the established connection and runs on top of the transport layer. It provides several mechanisms for user authentication. These include password authentication, public-key or host-based authentication mechanisms, challenge-response, pluggable authentication modules (PAM), Generic Security Services API (GSSAPI) and even dongles.
:'''SSH-TRANS''' – The transport layer provides server authentication, confidentiality and data integrity over TCP. It does this through algorithm negotiation and a key exchange. The key exchange includes server authentication and results in a cryptographically secured connection: it provides integrity, confidentiality and optional compression. <ref name="OpenSSH-Manual">{{cite web |url=https://www.openssh.org/manual.html |title=OpenSSH Manual Pages |publisher=OpenSSH| accessdate=2026-04-03}}</ref>
Among the differences between the current protocol, SSH2, and the deprecated SSH1 protocol, is that SSH2 uses host keys for authentication. Whereas SSH1 used both server and host keys to authenticate. There's not much which can be added about the protocols which is not already covered with more detail and authority in RFC 4251 <ref name="RFC42511">{{cite web |url=http://tools.ietf.org/html/rfc4251 | title=RFC 4251: The Secure Shell (SSH) Protocol Architecture | date=2006 |accessdate=2013-10-31}}</ref>.
==SSH File Transfer Protocol (SFTP)==
The SSH File Transfer Protocol (SFTP) is a binary protocol to provide secure file transfer, access and management.
SFTP was added by Markus Friedl on the server side in time for the 2.3.0 release of OpenSSH in November 2000. Damien Miller added support for SFTP to the client side in time for 2.5.0. Since then, many have added to both the client and the server.
===SFTP is not FTPS===
For basic file transfer, nothing more is needed than an account on the machine with the OpenSSH server. SFTP support is built into the OpenSSH server package. The SFTP protocol, in contrast to old FTP, has been designed from the ground up to be as secure as possible for both login and data transfer.
{{RightHalf|'''[[w:Samba_(software)|Samba]]''' is an interoperability suite providing fast file and print services for any client which can use the SMB/CIFS protocol. It is most often used for file sharing at the level of the local area network. }}
{{RightHalf|'''[[w:Andrew_File_System|AFS]]''', or the Andrew File System, is a distributed file system providing file sharing at an institutional level across a geographically diverse institution or set of collaborating institutions. Notably it provides a set of trusted servers and a homogeneous, location-transparent file name space to all the client workstations. }}
Unless the use-case calls for publicly available, read-only, downloads, don't worry about trying to fiddle with FTP. It is the protocol FTP itself that is inherently insecure. It's great for read-only, public data transfer. The programs '''vsftpd''' and '''proftpd''', for example, are secure insofar as the server software itself goes, although the protocol itself is still insecure. In other words the program itself is more or less fine and if you need to provide read-only, publicly available downloads then FTP maybe the right tool. Otherwise forget about FTP.
Nearly always when users ask for "FTP" they don't mean specifically the old file transfer protocol from 1971 as described in RFC 114, but a generic means of file transfer and there are many ways to solve that problem. This is especially true since the next part of their request is usually how to make it secure. The name "FTP" is frequently mis-used generically to mean any file transfer utility, much the same way as the term "Coke" is used in some of Southern United States to mean any carbonated soft drink, not just Coca-Cola. Consider SFTP or, for larger groups, even SSHFS, [[w:Samba_(software)|Samba]], or [[w:Andrew_File_System|AFS]]. While old FTP succeeded very well in achieving its main goal to promote use of networked computers by allowing users at any host on the network to use the file system of any cooperating host, it cannot be made secure. There's nothing to be done about that, so it is past time to get over it.
Again, it is the protocol itself, FTP, which is the problem.<ref name="StopUsingFTP1">{{cite web |url=http://blog.jdpfu.com/2011/07/10/why-you-need-to-stop-using-ftp |title=Why You Need To Stop Using FTP |publisher=JDPFu.com| date=2011-07-10 | accessdate=2012-01-09}}</ref> With FTP, the data, passwords and user name are all sent back and forth unencrypted.<ref name="StopUsingFTP2">{{cite web |url=http://olex.openlogic.com/wazi/2011/stop-using-ftp-how-to-transfer-files-securely/ |title=Stop Using FTP! How to Transfer Files Securely | author=Manolis Tzanidakis | publisher=Wazi| date=2011-09-09 | accessdate=2012-01-09}}</ref> Anyone on the client's subnet, the server's subnet or any subnet in between can 'sniff' the passwords and data when FTP is used. With extra effort it is possible to wrap FTP inside SSL or TLS, thus creating FTPS. However, tunneling FTP over SSL/TLS is complex to do and far from an optimum solution.
Unfortunately because of name confusion combined with the large number of posts and discussions created by complex, nit-picky tasks like wrapping FTP in SSL to provide FTPS, the wrong way still turns up commonly in web searches regarding file transfer. In contrast, easy, relatively painless solutions vanish because it is rarely necessary to post how to do those. Also, an easy solution can be summed up in very few lines and maybe a single answer. Thus, there is still a lot of talk online about 'securing' FTP and very little mention of using SFTP. It's a vicious cycle that this book hopes to help break: Difficult tasks mean lots of discussion and noise, lots of discussion and noise means strong web presence, strong web presence means high Google ranking.
SFTP tools are very common, but might be taken for granted and thus overlooked. SFTP tools are easy to use and more functional than old FTP clients. In fact a lot of improvements have been made in usability. There is no shortage of common, GUI-based SFTP clients to transfer files: Filezilla, Konqueror, Dolphin, Nautilus, Cyberduck, Fugu, and Fetch top the list but there are many more. Most are Free Software.
Again, these SFTP clients are very easy to use. For example, in Konqueror, just type in the URL to the sftp server, where the server name or address is xx.yy.zz.aa.
<pre>
sftp://xx.yy.zz.aa
</pre>
If it is desirable to start with a particular directory, then that too can be specified.
<pre>
sftp://xx.yy.zz.aa/var/www/pictures/
</pre>
One special client worth knowing about is '''sshfs'''. With '''sshfs''' as an SFTP client the other machine is accessible as an open folder on your machine's local file system. In that way any program you normally have to work with files, such as LibreOffice, Inkscape or Gimp can access the remote machine via that folder.
===Background of FTP===
FTP is from the 1970s. It's a well proven workhorse, but from an era when if you were on the net you were supposed to be there and if there was trouble it could usually be cleared up with a short phone call or an e-mail or two. It sends the login name, password and all of the data unencrypted for anyone to intercept.
FTP clients can connect to the FTP server in either passive or active modes. Both active and passive modes for FTP<ref name="activepassiveFTP">{{cite web |url=http://slacksite.com/other/ftp.html | title=Active FTP vs. Passive FTP, a Definitive Explanation | date=2002 |accessdate=2020-03-20 | publisher=Slacksite.com | author=Jay Ribak}}</ref> use two ports, one for control and one for data. In FTP Active mode, after the client makes a connection to the FTP server it then allows an incoming connection to be initiated from the server to for data transfer. In FTP Passive mode, after the client makes a connection to the FTP server, the server then responds with information about a second port for data transfer and the client initiates the second connection.
FTP is most relevant now as Anonymous FTP, which is still excellent for read-only downloads without login. FTP is still one way to go for transferring read-only data, as would be using the web (HTTP or HTTPS), or a P2P protocol like Bittorrent. So there are other options than FTP for offering read-only downloads. Preference is given lately to HTTPS for small files and Bittorrent for large files or large groups of files.
====Using tcpdump to show FTP activity====
An illustration of how the old protocol, FTP, is insecure can be had from the utility '''tcpdump'''. It can show what is going over the network during an Anonymous FTP session, or for that matter any FTP session. Look at the manual page for '''tcpdump''' for an explanation of the individual arguments, the usage example below displays the first FTP or FTP-Data packets going from the client to the server and vice versa.
The output below shows an excerpt from the output of '''tcpdump''' which captured packets between an FTP client and the FTP server, one line per packet.
<syntaxhighlight lang="shell">
$ sudo tcpdump -q -s 0 -c 10 -A -i eth0 \
"tcp and (port ftp or port ftp-data)"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
…
:18:36.010820 IP desk.55227 > server.ftp: tcp 16 E..D..@.@.....1.[.X.....G.r. ........l..... ."......USER anonymous
:18:36.073192 IP server.ftp > desk.55227: tcp 0 E..4jX@.7.3.[.X...1..... ...G.r#........... ....."..
:18:36.074019 IP server.ftp > desk.55227: tcp 34 E..VjY@.7.3.[.X...1..... ...G.r#....Y...... ....."..331 Please specify the password.
:18:36.074042 IP desk.55227 > server.ftp: tcp 0 E..4..@.@..+..1.[.X.....G.r# ..)........... ."......
:18:42.098941 IP desk.55227 > server.ftp: tcp 23 E..K..@.@.....1.[.X.....G.r# ..)....gv..... .".w....PASS user@example.net
:18:42.162692 IP server.ftp > desk.55227: tcp 23 E..KjZ@.7.3.[.X...1..... ..)G.r:........... .....".w230 Login successful.
…
:18:43.431827 IP server.ftp > desk.55227: tcp 14 E..Bj\@.7.3.[.X...1..... ..SG.rF.....j..... ....."..221 Goodbye.
…
</syntaxhighlight>
As can be seen in lines 3 and 7, data such as text from the server is visible. In lines 1 and 5, text entered by the user is visible and in this case it includes the user name and password used to log in. Fortunately the session is Anonymous FTP, which is read-only and used for downloading. Anonymous FTP is a rather efficient way to publish material for download. For Anonymous FTP, the user name is always "anonymous" and the password is the user’s e-mail address and the server's data always read-only.
If you have the package for the OpenSSH server already installed, no further configuration of the server is needed to start using SFTP for file transfers. Though comparatively speaking, FTPS is significantly more secure than FTP. If you want remote remote login access, then both FTP and FTPS should be avoided. A very large reason to avoid both is to save work.
===On FTPS===
FTPS is FTP tunneled over SSL or TLS. A goal of FTP was to encourage the use of remote computers which, along with the web, has succeeded. A goal of FTPS was to secure logins and transfers, and it was a necessary step in securing file transfers with the legacy protocol. However, since SFTP is so much easier to deploy and most systems now include both graphical and text-based SFTP clients, FTPS can really be considered deprecated for most occasions.
Some good background material can be found in the Request for Comments (RFCs) for FTP and FTPS. There, SFTP and even HTTPS are better matches and largely supersede FTPS. See the section on [[OpenSSH/Client Applications|Client Applications]] for an idea of the SFTP clients available.
==Privilege Separation==
Privilege separation is when a process is divided into sub-processes, each of which have just enough access to just the right parts of the system to do their part of the job. The goal of privilege separation is to compartmentalize any corruption and prevent a corrupt process from accessing other parts of the system. An underlying principle is that of least privilege, which is where each process has exactly enough privileges to accomplish a task, neither more nor less. Currently it's like this <ref name="Splitting_of_sshd_binaries_in_9_8">{{cite web |url=https://lists.mindrot.org/pipermail/openssh-unix-dev/2024-July/041486.html |title=Splitting of sshd binaries in 9.8? |publisher=openssh-unix-dev Mailing List | date=2024-07-17 | accessdate=2024-07-30}}</ref>:
<pre>
sshd [listener]
|
exec
|
sshd-session [privsep monitor]
| |
| fork (for auth)
| |
| sshd-auth: [net unpriv]
|
fork (after auth completes)
|
sshd-session [postauth unpriv]
</pre>
First, a privileged binary listens for incoming connections, seen here as PID 68746.
<syntaxhighlight lang="shell-session">
$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root 68746 1 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)
</syntaxhighlight>
Once a connection starts, it is passed off to a separate privileged monitor binary (seen as PID 53341 below) which makes an unprivileged fork (seen as PID 17952 below) under the account 'sshd' to address authentication.
<syntaxhighlight lang="shell-session">
$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root 68746 1 sshd: /usr/sbin/sshd [listener] 1 of 10-100 startups (sshd)
root 53341 68746 sshd-session: fred [priv] (sshd-session)
sshd 17952 53341 sshd-auth: fred [net] (sshd-auth)
</syntaxhighlight>
The fork owned by 'sshd' is terminated. If the authentication succeeds a new process (seen as PID 94635 below) owned by the authenticated account is forked from from the privileged monitor to deal with the session itself. At which point, the privileged monitor switches to its post-authentication state and runs until the unprivileged child exits.
<syntaxhighlight lang="shell-session">
$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root 68746 1 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)
root 53341 68746 sshd-session: fred [postauth] (sshd-session)
fred 30090 53341 sshd-session: fred@ttyp2 (sshd-session)
</syntaxhighlight>
This is a work in progress and future developments may move the post authentication, unprivileged process into a separate binary. The portable edition might acquire a PAM helper binary which would be called by the privilege separation monitor. But at least through 10.6, the above is managed through fork + exec.
Privilege separation has been the default in OpenSSH since version 3.3<ref name="Provos_Privilege_Separation">{{cite web |url=http://www.citi.umich.edu/u/provos/ssh/privsep.html |title=Privilege Separated OpenSSH |publisher=University of Michigan| author=Nils Provos| date=2003| accessdate=2011-02-17}}</ref> Starting with version 5.9, privilege separation further applies mandatory restrictions on which system calls the privilege separated child can perform. The intent is to prevent a compromised privilege separated child from being used to attack other hosts either by opening sockets and proxying or by probing the local kernel attack surface. <ref name="OpenSSH_release_notes_5.9">{{cite web |url=https://www.openssh.org/txt/release-5.9 |title=OpenSSH 5.9 Release Notes |publisher=OpenSSH | date=2011-09-06 | accessdate=2026-04-03}}</ref> Since version 6.1, this sandboxing has been the default.
[[File:OpenSSH-Privilege-Separation.svg|frame|right|Sequence Diagram for OpenSSH Privilege Separation]]
===Old Privilege Separation Prior to 9.8===
Privilege separation is applied in OpenSSH by using several levels of access, some higher some lower, to run [http://man.openbsd.org/sshd.8 sshd(8)] and its subsystems and components. The SSH server ➊ starts out with a privileged process ➋ which then creates an unprivileged process ➌ to work with the network traffic. Once the user has authenticated, another unprivileged process is created ➍ with the privileges of that authenticated user. See the "Sequence Diagram for OpenSSH Privilege Separation". As seen in the diagram, a total of four processes get run to create an SSH session. One process, the server, remains and listens for new connections and spawn new child processes.
<syntaxhighlight lang="shell-session">
$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1'
USER PID PPID STAT STARTED COMMAND
root 1473 1 I 05:44:01 sshd: /usr/sbin/sshd [listener] 0 of 10-10
</syntaxhighlight>
It is this privileged process that listens for the initial connection from clients. Here it is seen waiting and listening on port 22.
<syntaxhighlight lang="shell-session">
$ netstat -ntlp | awk '/sshd/ || NR<=2'
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1473/sshd
tcp6 0 0 :::22 :::* LISTEN 1473/sshd
</syntaxhighlight>
After the initial connection while waiting for password authentication from user 'fred', a privileged monitor process supervises an unprivileged process by user 'sshd' which handles the contact with the remote user's client.
<syntaxhighlight lang="shell-session">
$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1'
USER PID PPID S STARTED COMMAND
root 1473 1 S 05:44:12 sshd: /usr/sbin/sshd [listener] 1 of 10-10
root 9481 1473 S 14:40:37 sshd: fred [priv]
sshd 9482 9481 S 14:40:37 sshd: fred [net]
</syntaxhighlight>
Then after authentication is completed and a session established for user 'fred', a new privileged monitor process is created to supervise the process running as user 'fred'. At that point the other process running as user 'sshd' has gone away.
<syntaxhighlight lang="shell-session">
$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1'
USER PID PPID S STARTED COMMAND
root 1473 1 S 05:44:12 sshd: /usr/sbin/sshd [listener] 0 of 10-10
root 9481 1473 S 14:40:37 sshd: fred [priv]
fred 9579 9481 S 14:42:02 sshd: fred@pts/30
</syntaxhighlight>
Again, that is for the older method of privilege separation.
<noinclude>
== References ==
{{reflist}}
{{OpenSSH/TOC|mini}}
</noinclude>
{{BookCat}}
{{status|100%}}
rpv4hp9u89q4jy02gxcwyfpsqvaf593
Radiation Oncology/Reirradiation
0
264712
4676008
2506984
2026-10-14T10:29:57Z
Jcb
90773
4676008
wikitext
text/x-wiki
<big>'''Reirradiation'''</big>
==General==
*'''Review (2000)''' {{PMID|11034632}} -- "Clinical experience with retreatment for palliation." (Morris DE, Semin Radiat Oncol. 2000 Jul;10(3):210-21.)
*'''Review (2000)''' {{PMID|11034631}} -- "Tissue tolerance to reirradiation." (Nieder C, Semin Radiat Oncol. 2000 Jul;10(3):200-9.)
*'''Review (1994)''' {{PMID|10717096}} -- "Retreatment Tolerance of Normal Tissues." (Stewart FA, Semin Radiat Oncol. 1994 Apr;4(2):103-111.)
'''''Practice Patterns:'''''
*'''2008, Canada''' {{PMID|18501531}} -- "Reirradiation after radical radiation therapy: a survey of patterns of practice among Canadian radiation oncologists." (Joseph KJ, Int J Radiat Oncol Biol Phys. 2008 Dec 1;72(5):1523-9.)
==Abdominal Reirradiation==
See page: [[Radiation Oncology/Reirradiation/Abdomen|Abdominal Reirradiation]]
==Lung Reirradiation==
See page: [[Radiation Oncology/Reirradiation/Lung|Lung Reirradiation]]
==Pelvic Reirradiation==
See page: [[Radiation Oncology/Reirradiation/Pelvis|Pelvic Reirradiation]]
{{BookCat}}
0d9t4wmz7228uxt4yfo8uu4kkt9bopc
Radiation Oncology/Reirradiation/Abdomen
0
264732
4676009
2306222
2026-10-14T10:30:30Z
Jcb
90773
4676009
wikitext
text/x-wiki
<big>'''Abdominal Reirradiation'''</big>
*'''MDACC; 2009''' (2002-2008) {{PMID|19922641}} -- "Reirradiation to the abdomen for gastrointestinal malignancies." (Haque W, Radiat Oncol. 2009 Nov 18;4:55.)
**13 pts reirradiated for recurrent or metastatic disease. Prior RT median 45 Gy, interval of 26 months. Treated with 1.5 Gy BID to median 30 Gy (range 24-48 Gy). Concurrent chemo in 8 pts (62%).
**1-yr freedom from local progression 50%, median duration of freedom of local progression 14 months. 1-yr OS 62%, Median OS 14 months. 1 pt with grade 3-4 toxicity.
**Conclusion: Hyperfractionated accelerated reirradiation to the abdomen was well-tolerated with low rates of acute and late toxicity.
{{BookCat}}
l37t9j8yqdi1xwkl1172mdsrxrfaxna
Haskell/Building vocabulary
0
269315
4675917
4443099
2026-10-13T22:44:44Z
Luciérnaga de conocimiento
3401314
4675917
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Haskell Basics|noexercises=1}}
This chapter will be a bit of an interlude with some advice for studying and using Haskell. We will discuss the importance of acquiring a vocabulary of functions and how this book and other resources can help. First, however, we need to understand function composition.
== Function composition ==
Function composition means applying one function to a value and then applying another function to the result. Consider these two functions:
{{Haskell/Example|1=Simple functions|2=<syntaxhighlight lang="haskell">
f x = x + 3
square x = x ^ 2
</syntaxhighlight>}}
We can compose them in two different ways, depending on which one we apply first:
{{Haskell/GHCi|1=
Prelude> square (f 1)
16
Prelude> square (f 2)
25
Prelude> f (square 1)
4
Prelude> f (square 2)
7
}}
The parentheses around the inner function are necessary; otherwise, the interpreter would think that you were trying to get the value of <code>square f</code>, or <code>f square</code>; and both of those would give type errors.
The composition of two functions results in a function in its own right. If we regularly apply f and then square (or vice-versa), we should generate a new variable name for the resulting combinations:
{{Haskell/Example|1=Composed functions|2=<syntaxhighlight lang="haskell">
squareOfF x = square (f x)
fOfSquare x = f (square x)
</syntaxhighlight>}}
There is a second, nifty way of writing composed functions. It uses <code>(.)</code>, the function composition operator and is as simple as putting a period between the two functions:
{{Haskell/Example|1=Composing functions with <code>(.)</code>|2=<syntaxhighlight lang="haskell">
squareOfF x = (square . f) x
fOfSquare x = (f . square) x
</syntaxhighlight>}}
Note that functions are still applied from right to left, so that <code>g(f(x)) == (g . f) x</code>. <code>(.)</code> is modeled after the mathematical operator <math>\circ</math>, which works in the same way: <math>(g \circ f)(x) = g(f(x))</math>.
Incidentally, our function definitions ''are'' effectively mathematical equations, so we can take
<syntaxhighlight lang="haskell">squareOfF x = (square . f) x</syntaxhighlight>
and cancel the <code>x</code> from both sides, leaving:
<syntaxhighlight lang="haskell">squareOfF = square . f</syntaxhighlight>
We will later learn more about such cases of functions without arguments shown. For now, understand that we can simply substitute our defined variable name for any case of the composed functions.
== The need for a vocabulary ==
Haskell makes it simple to write composed functions and to define variables, so we end up with relatively simple, elegant, and expressive code. Of course, to use function composition, we first need to have functions to compose. While functions we write ourselves will always be available, every installation of GHC comes with a vast assortment of libraries (i.e. packaged code), which provide functions for many common tasks. For that reason, effective Haskell programmers need some familiarity with the essential libraries. At the least, you should know how to find useful functions in the libraries when you need them.
Given only the Haskell syntax we will cover through the [[../Recursion|Recursion]] chapter, we will, in principle, have enough knowledge to write nearly any list manipulation program we want. However, writing full programs with only these basics would be terribly inefficient because we would end up rewriting large parts of the standard libraries. So, much of our study going forward will involve studying and understanding these valuable tools the Haskell community has already built.
== Prelude and the libraries ==
Here are a few basic facts about Haskell libraries:
First and foremost, ''Prelude'' is the core library loaded by default into every Haskell program. This ubiquitous library provides a useful set of functions, classes, and types. We refer to Prelude types and functions throughout these introductory chapters.
GHC provides a large set of core libraries having a wide range of tools, but only Prelude loads automatically. The other libraries are ''modules'' available for ''import'' into your program. Later on, we explain the minutiae of how modules work. For now, just know that your source file needs lines near the top to import any desired modules. For example, to use the function <code>permutations</code> from the module <code>Data.List</code>, add the line <code>import Data.List</code> to the top of your .hs file. Here's a full source file example:
{{Haskell/Example|1=Importing a module in a source file|2=<syntaxhighlight lang="haskell">
import Data.List
testPermutations = permutations "abc"
</syntaxhighlight>}}
For quick GHCi tests, just enter <code>:m +Data.List</code> at the command line to load that module.
{{Haskell/GHCi|1=
Prelude> :m +Data.List
Prelude Data.List> :t permutations
permutations :: [a] -> [[a]]
}}
== One exhibit ==
Before continuing, let us see one (slightly histrionic, we admit) example of what familiarity with a few basic functions from Prelude can bring us.<ref>The example here is inspired by the [http://www.haskell.org/haskellwiki/Simple_unix_tools Simple Unix tools] demo in the HaskellWiki.</ref> Suppose we need a function which takes a string composed of words separated by spaces and returns that string with the order of the words reversed, so that <code>"Mary had a little lamb"</code> becomes <code>"lamb little a had Mary"</code>. We ''could'' solve this problem using only the basics we have already covered along with a few insights in the upcoming Recursion chapter. Below is one messy, complicated solution. Don't stare at it for too long!
{{Haskell/Example|1=There be dragons|2=<syntaxhighlight lang="haskell">
monsterRevWords :: String -> String
monsterRevWords input = rejoinUnreversed (divideReversed input)
where
divideReversed s = go1 [] s
where
go1 divided [] = divided
go1 [] (c:cs)
| testSpace c = go1 [] cs
| otherwise = go1 [[]] (c:cs)
go1 (w:ws) [c]
| testSpace c = (w:ws)
| otherwise = ((c:w):ws)
go1 (w:ws) (c:c':cs)
| testSpace c =
if testSpace c'
then go1 (w:ws) (c':cs)
else go1 ([c']:w:ws) cs
| otherwise = go1 ((c:w):ws) (c':cs)
testSpace c = c == ' '
rejoinUnreversed [] = []
rejoinUnreversed [w] = reverseList w
rejoinUnreversed strings = go2 (' ' : reverseList newFirstWord) (otherWords)
where
(newFirstWord : otherWords) = reverseList strings
go2 rejoined ([]:[]) = rejoined
go2 rejoined ([]:(w':ws')) = go2 (rejoined) ((' ':w'):ws')
go2 rejoined ((c:cs):ws) = go2 (c:rejoined) (cs:ws)
reverseList [] = []
reverseList w = go3 [] w
where
go3 rev [] = rev
go3 rev (c:cs) = go3 (c:rev) cs
</syntaxhighlight>}}
There are too many problems with this ''thing''; so let us consider just three of them:
* To see whether <code>monsterRevWords</code> does what you expect, you could either take our word for it, test it exhaustively on all sorts of possible inputs, or attempt to understand it and get an awful headache (please don't).
* Furthermore, if we write a function this ugly and have to fix a bug or slightly modify it later on,<ref>''Co-author's note'': "Later on? I wrote that half an hour ago, and I'm not totally sure about how it works already..."</ref> we are set for an awful time.
* Finally, we have at least one easy-to-spot potential problem: if you have another glance at the definition, about halfway down there is a <code>testSpace</code> helper function which checks if a character is a space or not. The test, however, only includes the common space character (that is, <code>' '</code>), and no other whitespace characters (tabs, newlines, etc.).<ref>A reliable way of checking whether a character is whitespace is with the <code>isSpace</code> function, which is in the module <code>Data.Char</code>.</ref>
We can do much better than the junk above if we use the following Prelude functions:
* <code>words</code>, which reliably breaks down a string in whitespace delimited words, returning a list of strings;
* <code>reverse</code>, which reverses a list (incidentally, that is exactly what the <code>reverseList</code> above does); and
* <code>unwords</code>, which does the opposite of <code>words</code>;
then function composition means our problem is instantly solved.
{{Haskell/Example|1=<code>revWords</code> done the Haskell way|2=<syntaxhighlight lang="haskell">
revWords :: String -> String
revWords input = (unwords . reverse . words) input
</syntaxhighlight>}}
That's short, simple, readable and (since Prelude is reliable) bug-free.<ref>In case you are wondering, many other functions from Prelude or <code>Data.List</code> could help to make <code>monsterRevWords</code> somewhat saner — to name a few: <code>(++)</code>, <code>concat</code>, <code>groupBy</code>, <code>intersperse</code> — but no use of those would compare to the one-liner above.</ref> So, any time some program you are writing begins to look like <code>monsterRevWords</code>, look around and reach for your toolbox — the libraries.
== This book's use of the libraries ==
After the stern warnings above, you might expect us to continue diving deep into the standard libraries. However, the Beginner's Track is meant to cover Haskell functionality in a conceptual, readable, and reasonably compact manner. A systematic study of the libraries would not help us, but we will introduce functions from the libraries as appropriate to each concept we cover.
* In the Elementary Haskell section, several of the exercises (mainly, among those about list processing) involve writing equivalent definitions for Prelude functions. For each of these exercises you do, one more function will be added to your repertoire.
* Every now and then we will introduce more library functions; maybe within an example, or just with a mention in passing. Whenever we do so, take a minute to test the function and do some experiments. Remember to extend that habitual curiosity about types we mentioned in [[../Type basics|Type basics]] to the functions themselves.
* While the first few chapters are quite tightly-knit, later parts of the book are more independent. Haskell in Practice includes chapters on the [[../Hierarchical libraries|Hierarchical libraries]], and most of their content can be understood soon after having completed Elementary Haskell.
* As we reach the later parts of the Beginner's track, the concepts we will discuss (monads in particular) will naturally lead to exploration of important parts of the core libraries.
== Other resources ==
* First and foremost, all modules have basic documentation. You may not be ready to read that directly yet, but we'll get there. You can read the [https://www.haskell.org/onlinereport/haskell2010/haskellch9.html Prelude specification] on-line as well as the [http://www.haskell.org/ghc/docs/latest/html/libraries/index.html documentation of the libraries bundled with GHC], with nice navigation and source code just one click away.
* [http://hoogle.haskell.org Hoogle] is a great way to search through the documentation, beginner friendly. It covers a large set of libraries. You can search by function name (say, length) or by type ("function from lists to Int", which you'd write [a]->Int). This second type of search helps you find very specific functions and prevents reinventing the wheel.
* Beyond the libraries included with GHC, there is a large ecosystem of libraries, made available through [https://hackage.haskell.org/ Hackage] and installable with a tool called [http://www.haskell.org/cabal/users-guide/ cabal]. The Hackage site has documentation for its libraries. We will not venture outside of the core libraries in the Beginner's Track, but you should certainly use Hackage once you begin your own projects.
* When appropriate, we will give pointers to other useful learning resources, especially when we move towards intermediate and advanced topics.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Haskell Basics|noexercises=1}}
{{BookCat}}
qc8capsb604s1rjl43hfoulgvruix41
Haskell/The Functor class
0
269508
4676014
4666183
2026-10-14T11:06:01Z
Luciérnaga de conocimiento
3401314
4676014
wikitext
text/x-wiki
{{Haskell/Minitoc|chapter=Intermediate Haskell|noexercises=1}}
In this chapter, we will introduce the important <code>Functor</code> type class.
== Motivation ==
In [[../Other data structures|Other data structures]], we saw operations that apply to all elements of some grouped value. The prime example is <code>map</code> which works on lists. Another example we worked through was the following Tree datatype:
<syntaxhighlight lang="haskell">
data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving (Show)
</syntaxhighlight>
The map function we wrote for Tree was:
<syntaxhighlight lang="haskell">
treeMap :: (a -> b) -> Tree a -> Tree b
treeMap f (Leaf x) = Leaf (f x)
treeMap f (Branch left right) = Branch (treeMap f left) (treeMap f right)
</syntaxhighlight>
As discussed before, we can conceivably define a map-style function for any arbitrary data structure.
When we first introduced <code>map</code> in [[../Lists II|Lists II]], we went through the process of taking a very specific function for list elements and generalizing to show how <code>map</code> combines any appropriate function with all sorts of lists. Now, we will generalize still ''further''. Instead of map-for-lists and map-for-trees and other distinct maps, how about a general concept of maps for all sorts of mappable types?
== Introducing <code>Functor</code> ==
<code>Functor</code> is a Prelude class for types which can be mapped over. It has a single method, called <code>fmap</code>. The class is defined as follows:
<syntaxhighlight lang="haskell">
class Functor f where
fmap :: (a -> b) -> f a -> f b
</syntaxhighlight>
The usage of the type variable <code>f</code> can look a little strange at first. Here, <code>f</code> is a parametrized data type; in the signature of <code>fmap</code>, <code>f</code> takes <code>a</code> as a type parameter in one of its appearances and <code>b</code> in the other. Let's consider an instance of <code>Functor</code>: By replacing <code>f</code> with <code>Maybe</code> we get the following signature for <code>fmap</code>...
<syntaxhighlight lang="haskell">
fmap :: (a -> b) -> Maybe a -> Maybe b
</syntaxhighlight>
... which fits the natural definition:
<syntaxhighlight lang="haskell">
instance Functor Maybe where
fmap f Nothing = Nothing
fmap f (Just x) = Just (f x)
</syntaxhighlight>
(Incidentally, this definition is in Prelude; so we didn't really need to implement <code>maybeMap</code> for that example in the "Other data structures" chapter.)
The <code>Functor</code> instance for lists (also in Prelude) is simple:
<syntaxhighlight lang="haskell">
instance Functor [] where
fmap = map
</syntaxhighlight>
... and if we replace <code>f</code> with <code>[]</code> in the <code>fmap</code> signature, we get the familiar type of <code>map</code>.
So, <code>fmap</code> is a generalization of <code>map</code> for any parametrized data type.<ref>Data structures provide the most intuitive examples; however, there are functors which cannot reasonably be seen as data structures. A commonplace metaphor consists in thinking of functors as containers; like all metaphors, however, it can be stretched only so far.</ref>
Naturally, we can provide <code>Functor</code> instances for our own data types. In particular, <code>treeMap</code> can be promptly relocated to an instance:
<syntaxhighlight lang="haskell">
instance Functor Tree where
fmap f (Leaf x) = Leaf (f x)
fmap f (Branch left right) = Branch (fmap f left) (fmap f right)
</syntaxhighlight>
<!--Here there could be a digression about Data.Foldable and the catamorphisms in Other data structures. I fear it would grow too long and winding, though-->
Here's a quick demo of <code>fmap</code> in action with the instances above (to reproduce it, you only need to load the <code>data</code> and <code>instance</code> declarations for <code>Tree</code>; the others are already in Prelude):
{{Haskell/GHCi|1=
*Main> fmap (2*) [1,2,3,4]
[2,4,6,8]
*Main> fmap (2*) (Just 1)
Just 2
*Main> fmap (fmap (2*)) [Just 1, Just 2, Just 3, Nothing]
[Just 2, Just 4, Just 6, Nothing]
*Main> fmap (2*) (Branch (Branch (Leaf 1) (Leaf 2)) (Branch (Leaf 3) (Leaf 4)))
Branch (Branch (Leaf 2) (Leaf 4)) (Branch (Leaf 6) (Leaf 8))
}}
{{body note|1=
Beyond <code>[]</code> and <code>Maybe</code>, there are many other <code>Functor</code> instances already defined. Those made available from the Prelude are listed in the {{Haskell/Lib|v=latest|Data|Functor}} module.
}}
=== The functor laws ===
When providing a new instance of <code>Functor</code>, you should ensure it satisfies the two functor laws. There is nothing mysterious about these laws; their role is to guarantee <code>fmap</code> behaves sanely and actually performs a mapping operation (as opposed to some other nonsense). <ref>Some examples of nonsense that the laws rule out: removing or adding elements from a list, reversing a list, changing a <code>Just</code>-value into a <code>Nothing</code>.</ref> The first law is:
<syntaxhighlight lang="haskell">
fmap id = id
</syntaxhighlight>
<code>id</code> is the identity function, which returns its argument unaltered. The first law states that mapping <code>id</code> over a functorial value must return the functorial value unchanged.
Next, the second law:
<syntaxhighlight lang="haskell">
fmap (g . f) = fmap g . fmap f
</syntaxhighlight>
It states that it should not matter whether we map a composed function or first map one function and then the other (assuming the application order remains the same in both cases).
== What did we gain? ==
At this point, we can ask what benefit we get from the extra layer of generalization brought by the <code>Functor</code> class. There are two significant advantages:
* The availability of the <code>fmap</code> method relieves us from having to recall, read, and write a plethora of differently named mapping methods (<code>maybeMap</code>, <code>treeMap</code>, <code>weirdMap</code>, ''ad infinitum''). As a consequence, code becomes both cleaner and easier to understand. On spotting a use of <code>fmap</code>, we instantly have a general idea of what is going on.<ref>This is analogous to the gain in clarity provided by replacing explicit recursive algorithms on lists with implementations based on higher-order functions.</ref> Thanks to the guarantees given by the functor laws, this general idea is surprisingly precise.
* Using the type class system, we can write <code>fmap</code>-based algorithms which work out of the box with ''any'' functor - be it <code>[]</code>, <code>Maybe</code>, <code>Tree</code> or whichever you need. Indeed, a number of useful classes in the core libraries inherit from <code>Functor</code>.
Type classes make it possible to create general solutions to whole categories of problems. Depending on what you use Haskell for, you may not need to define new classes often, but you will certainly be ''using'' type classes all the time. Many of the most powerful features and sophisticated capabilities of Haskell rely on type classes (residing either in the standard libraries or elsewhere). From this point on, classes will be a prominent presence in our studies.
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Intermediate Haskell|noexercises=1}}
{{BookCat}}
bwucyhkgjhvugkty5e4inbj3f9auypc
On 2D Inverse Problems
0
279393
4675921
4675775
2026-10-13T22:55:11Z
DVD206
724793
TOC
4675921
wikitext
text/x-wiki
[[File:Book cover.jpg|thumbnail|DVD cover]]
<!-- EDIT BELOW THIS LINE -->
'''ON VERSE PROBLEMS'''
DVD version TOC
== [[On 2D Inverse Problems/Preface|The Volume I: Pretty preface]] ==
=== [[On 2D Inverse Problems/Body|Theory & "no problems..."]] ===
=== [[On 2D Inverse Problems/Bibliography|Bubbles]] ===
=== [[On 2D Inverse Problems/About the author|"Who is talking?"]] ===
===[[On 2D Inverse Problems/redial|Halloween]]===
== [[On 2D Inverse Problems/Ai|The volume II: AI DVD!?]] ==
=== [[On 2D Inverse Problems/Papirus|Paper Papirus]] ===
=== [[On 2D Inverse Problems/Rotation|Spinning Spectrum Disc]] ===
=== [[On 2D Inverse Problems/Spatial|Spatial Spectrum Spiritual Geometry]] ===
== [[On 2D Inverse Problems/Characteristic|Characteristic: companion and circulant matrices]] ==
=== [[On 2D Inverse Problems/Area|Energy integral sum]] ===
=== [[On 2D Inverse Problems/Orthogonal|Gravity is optional]] ===
=== [[On 2D Inverse Problems/Echo|Echo response]] ===
== [[On 2D Inverse Problems/Private|The volume III: Piracy!?]] ==
=== [[On 2D Inverse Problems/4|Ghost Spiderweb]] ===
=== [[On 2D Inverse Problems/5|Shape-shifting network]] ===
=== [[On 2D Inverse Problems/6|Six colors suffices surface]] ===
{{Shelves|Mathematical collections}}
{{Alphabetical|2}}
{{status|75%}}
{{reading level|Beginner}}
{{BookCat}}
k0n6x26fs5c86ljqwabzykl9seqzpt7
4675929
4675921
2026-10-13T23:07:43Z
DVD206
724793
/* "Who is talking?" */
4675929
wikitext
text/x-wiki
[[File:Book cover.jpg|thumbnail|DVD cover]]
<!-- EDIT BELOW THIS LINE -->
'''ON VERSE PROBLEMS'''
DVD version TOC
== [[On 2D Inverse Problems/Preface|The Volume I: Pretty preface]] ==
=== [[On 2D Inverse Problems/Body|Theory & "no problems..."]] ===
=== [[On 2D Inverse Problems/Bibliography|Bubbles]] ===
===[[On 2D Inverse Problems/redial|Halloween]]===
== [[On 2D Inverse Problems/Ai|The volume II: AI DVD!?]] ==
=== [[On 2D Inverse Problems/Papirus|Paper Papirus]] ===
=== [[On 2D Inverse Problems/Rotation|Spinning Spectrum Disc]] ===
=== [[On 2D Inverse Problems/Spatial|Spatial Spectrum Spiritual Geometry]] ===
== [[On 2D Inverse Problems/Characteristic|Characteristic: companion and circulant matrices]] ==
=== [[On 2D Inverse Problems/Area|Energy integral sum]] ===
=== [[On 2D Inverse Problems/Orthogonal|Gravity is optional]] ===
=== [[On 2D Inverse Problems/Echo|Echo response]] ===
== [[On 2D Inverse Problems/Private|The volume III: Piracy!?]] ==
=== [[On 2D Inverse Problems/4|Ghost Spiderweb]] ===
=== [[On 2D Inverse Problems/5|Shape-shifting network]] ===
=== [[On 2D Inverse Problems/6|Six colors suffices surface]] ===
{{Shelves|Mathematical collections}}
{{Alphabetical|2}}
{{status|75%}}
{{reading level|Beginner}}
{{BookCat}}
t1adz7lb9vpa0vmkq1c0wt51hpcvhfh
User:On 2D Inverse Problems/Acknowledgements
2
279403
4675923
3584530
2026-10-13T22:58:33Z
DVD206
724793
helpers
4675923
wikitext
text/x-wiki
Volume I: Wikipedia, StackExchange and SageMathCloud helped publishing the book @all stages of the process.
{{BookCat}}
Volumes II and III: Copilot/Covid, Gemini/Germany and Meta/eta/beta/zeta AI on cellphone and laptop...
l1s7uqurywvbp27m5i29no9k2bfxh30
On 2D Inverse Problems/Bibliography
0
279404
4675930
4629183
2026-10-13T23:12:31Z
DVD206
724793
plagiarism...
4675930
wikitext
text/x-wiki
=== [[On 2D Inverse Problems/About the author|"Who is talking?"]] ===
[https://x.com/i/grok/share/04b339fff0944559885cf8ed1a17aa6a Book 📖 Club]
* [AP] Astala, K. and P¨aiv¨arinta, L. [http://annals.math.princeton.edu/wp-content/uploads/annals-v163-n1-p05.pdf "Calder´on’s inverse conductivity problem in the plane"]
* [BIMS] Biesel, O.D., Ingerman D.V., Morrow J.A. and Shore W.T. [http://www.math.washington.edu/~reu/papers/2008/william/layered.pdf "Layered Networks, the Discrete Laplacian, and a Continued Fraction Identity"]
*<s>[BDK] Borcea, L., Druskin, V. and Knizhnerman, L. "On the continuum limit of a discrete inverse spectral problem on optimal finite difference grids", Communications on Pure and Applied Mathematics, Vol. 000, 0001–0048 (2000)</s>
* <s>[BDMV] Borcea, L., Druskin, V., Mamonov, A.V. and Vasquez, G.F. "Resistor network approaches to electrical impedance tomography", http://arxiv.org/abs/1107.0343</s>
* [CM] Curtis, E.B. and Morrow, J.A. [http://books.google.com/books/about/Inverse_Problems_for_Electrical_Networks.html?id=gLnohh95zFIC "Inverse Problems for Electrical Networks"]
* [CIM] Curtis, E.B., Ingerman, D.V. and Morrow, J.A. [http://www.math.washington.edu/~morrow/papers/cim.pdf "Circular Planar Graphs and Resistor Networks"]
* [CMM] Curtis, E.B., Mooers, E. and Morrow J.A. "Finding the conductors in circular networks from boundary measurements", RAIRO Model Math. Anal. Numer. 28 (1994), pp. 781-814.
* [DeV1] De Verdière, Yves Colin, "Réseaux électriques planaires", Prépublications de l'Institut Fourier 225 (1992), 1-20
* [DeV2] De Verdière, Yves Colin, [http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.224.133 "Reseaux electrique planaires I"]
*<s> [DIK] Druskin, V., Ingerman D.V. and </s>Knizhnerman, L. [http://onlinelibrary.wiley.com/doi/10.1002/1097-0312(200008)53:8%3C1039::AID-CPA4%3E3.0.CO;2-I/abstract "Optimal finite difference grids and rational approximations of the square root I. Elliptic problems"]
* [ES] Edelman, A. and Strang, G. [http://web.mit.edu/18.06/www/pascal-work.pdf "Pascal matrices"]
* [F] Fomin, S. "Loop-erased walks and total positivity", http://arxiv.org/pdf/math.CO/0004083.pdf
<s>Kernels and Small Vibrations of Mechanical Systems", Revised Edition]
</s>
* [K] Kac, M. "Can one hear the shape of a drum?", American Mathematical Monthly 73 (4, part 2): 1–23, (1966), doi:10.2307/2313748
* [M] Marshall, D.E. [http://projecteuclid.org/DPubS?verb=Display&version=1.0&service=UI&handle=euclid.mmj/1029001307&page=record "An elementary proof of the Pick-Nevanlinna interpolation theorem"]
* [N] Nachman, A.I. [http://www.jstor.org/discover/10.2307/2118653?uid=3739960&uid=2&uid=4&uid=3739256&sid=21101022816693 "Global uniqueness for a two-dimensional inverse boundary value problem"]
{{BookCat}}
cv61b71jeizmqosofp5eze5yaa0htlh
Aros/Platforms/Arm Raspberry Pi support
0
286123
4675817
4675814
2026-10-13T12:28:17Z
Jeff1138
301139
4675817
wikitext
text/x-wiki
{{ArosNav}}
[[#Native]]
[[#Hosted]]
[[#Build]]
[[#Hardware]]
[[#References]]
[[#Future]]
==Introduction==
[[File:Scalos00.png|thumb|Scalos on Aros Pi3b]]
Aros aims to cover Pi 3 to 5 512Mb+ RAM
Options to boot from using a good power source to prevent the yellow lightning symbol.
*With Pi3b+ the max you can get is 5.1V 2.5A with micro usb.
*With Pi4 5.1V 3A with usb-c
*With Pi5 5.1V 5A, the amps went ever upwards, even to 5.1V 9A with usb-c
* Pi500+ keyboard wedge - working
* Pi500 wedge with up to date bootloader via PiOS - working
* Pi 5 - Quad A76 64bit ARMv8 and RP1 "southbridge" with VideoCore 7 D0 (rev1.1) - untested
* Pi 5 - Quad A76 64bit ARMv8 and RP1 "southbridge" with VideoCore 7 Pre-D0 C1 (Rev1.0) - untested
* Pi400 RPI-400 keyboard wedge - resolution changing and audio from micro hdmi0 (near 40pin) and micro hdmi1 (near usb-c psu) - Fn F10 0x5e power on and off works or held down for over 7 seconds auto shutdown - keyboard ok - wifi and lan ethernet testing -
* Pi 4 - Quad A72 64bit ARMv8 with VideoCore 6
* Pi 3 - Quad A53 [https://www.raspberrypi.com/documentation/computers/processors.html 64 bit] ARMv8 with VideoCore 4 with '''fan''' to prevent overheating cpu 82C+ throttling
* Pi02W - Quad A53 64bit - boots but [https://forums.raspberrypi.com/viewtopic.php?p=2387984#p2387984 usb not working but did in the past],
* Pi 2 - Quad 32bit ARMv6 with VideoCore 4 - mostly not 64bit compatible
* Pi Model B+ 32bit ARMv6 with VideoCore 4 - not 64bit compatible
* Pi Model A and B 32bit ARMv6 with VideoCore 4 - not 64bit compatible
===Native===
* 2013-03 Kalamatee starts work
* 2015-04 Work continues with mschulz on the kernel and Kalamatee (NicJA) on gpio and usb
* 2018 [https://www.patreon.com/posts/i-owe-you-some-20956961 mschulz resume adding BE big endian support], [https://www.patreon.com/michal_schulz/posts Big endian on Pi]
* 2026 [https://github.com/aros-development-team/AROS/commits?author=bsek latest commits for pi 3b, 4 and 5 64bit]
* 2026 [https://github.com/aros-development-team/AROS/commits?author=metaneutrons latest commits for Pi5]
* 2026 [https://github.com/aros-development-team/AROS/commits?author=bitplane latest commits for ARM]
====64bit====
'''Download''' A [https://archive.org/details/piAROS Pi Distribution (Distro) has started] and the contents copied to fat32 8GB+ microSD card (there will be drawers/folders - boot c Classes Demos Developer Devs Extras etc only showing). The SD can be plugged in to the Pi. And power on. [https://pi.amiga.icu/ Repository]
[https://aros.sourceforge.io/nightly1.html RaspberryPi 3, 3+, 4 and 5 64bit ArmV8 nightly builds] [https://sourceforge.net/projects/aros/files/ Alternative site and nightly2] which is a test beta limited apps version with both raspi-aarch64-system and raspi-aarch64-contrib can be unbz2'd to a SD or SSD as appropriate.
64bit build works well on a single core LE little endian. Multicore [https://github.com/aros-development-team/AROS/commit/1df0747c2bda3523a43029725a709b1f377d84ec may follow]. Any issues booting could be down to the SD card so please use another SD to see if it is resolved. Remember Aros Arm uses FAT32 and Aros can detect issues with this format very acutely (once fault found, FAT 0x0FFFFFF7 bad cluster so no files written after that, no repair). Please report your experiences in the [https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2138&pid=15057#post_15057 Aros forum thread], [https://forums.raspberrypi.com/viewforum.php?f=179 Raspberry Pi Aros Dev and User forums], [https://forums.raspberrypi.com/viewtopic.php?p=2387984#p2387984 previous Raspberry Pi forum thread]. Any bugs or issues can be [https://github.com/aros-development-team/AROS/issues described here to fix]
Boots with '''USB3''' port based sata3 ssd on Pi400 but untested on Pi4 (may need eeprom update from PiOS or Pi SD Imager) and Pi5
Pi 3 B+ is pre-configured for USB sata3 boot - untested
Pi 3 B may need [https://www.youtube.com/watch?v=ubnwvxF3Klc PiOS to set OTP to boot from usb - do so at your own risk] - if OTP set to usb, boot works but slower than SD card
Speed write wise (top faster)
<pre>
*NVME Pi5 untested >1000MB/sec or faster if matched correctly
*Sata3 ssd 500MB/sec
*SD V90 90MB/sec 4K maybe 8K
*SD V60 60MB/sec 1080p
*SD U3 V30 30MB/sec 720p
*SD C10 U1 V10 A1 A2 10MB/sec minimum should be used now
*SD C06 6MB/sec
*SD C04 4MB/sec
</pre>
As a homage to the past, Aros shows a reduced number of icons but this can be changed by left mouse click in the window and then right click down to Window -> View -> All files
Windows can be manipulated by the top (moving) and the bottom right corner (resizing) only.
Zune like MUI gui interface, has a unique quirk in that after changing a setting in a text box, you may sometimes need to press Enter/Return before clicking OK, Save, etc
Double left mouse click on most picture (Developer/Debug/Tests/Datatypes), audio and video files are supported, via datatypes, by the multiview application.
Esc escape key usually closes open windows even the desktop
In Prefs/Appearance some decorative theming elements need work. There is a few Mason icons in /Prefs/Presets/Icons/Mason/ and the ever present default Gorilla - Icon exchange in works
For more intensive graphics applications, you may need to edit config.txt in the root folder and change 128M to 256M to adjust more memory to graphics usage
If your cursor should '''appear''' to vanish, fear not it is still there. Please head to the top of the screen i.e. the title bar, hold down the left click mouse and drag the screen down a little and the cursor will appear again. Then you can drag the screen up again.
Like most amiga like OSs the audio and networking need to be setup manually
Audio AHI prefs - Mode settings tab - needs both Music unit and Unit 0 set to RPiHDMI:16 bit stereo++ or RPiPWM:16 bit stereo++ at 44100Hz. Press '''Save or Use''' button after each choice
For wireless, please use the Wifi prefs and already selected device bwfm.device. Press Scan and double right click on the router and enter password. You may need to setup after every power off
*if asking for password again - press cancel and go to Network Prefs, Wireless Networks tab and highlight the router line and hit the remove button and press the cancel button. Retry with Wifi prefs again
*...waiting for an address - Disconnect and try Connect
Until, Connected to <router> - 192.168.x.x
For lan ethernet port, please use Network prefs and the following hardware is
*lan9514 Pi3b Pi2 not supported at the moment
*lan7515 Pi3b+ type into Device usblan78xx.device as net0: remove other device(s)
*bcmgenet Pi4 Pi400 choose for Device bcmgenet.device
* Pi5 Pi500 Pi500+ RP1 i/o
(network prefs may forget random information when rebooted)
Summary
<pre>
*3b ethernet not supported, usb ethernet not working but wifi prefs setup works
*3b+ wifi working and ethernet works
*4 untested
*400 wifi and ethernet untested
*5 wifi and ethernet untested
*500 wifi and ethernet untested
*500+ wifi works
</pre>
Type in 'aarch64' in the [https://archives.arosworld.org/index.php?function=search&tool=simple search box] and you will see available software packages / apps. apkg can be used to inspect and install applications.
[http://archives.arosworld.org/index.php?function=browse&cat=network/browser amelinium web browser (JS 1.6 ES9 ECMASCript 2018)] is available with an [https://eab.abime.net/showthread.php?t=122494&page=51 eab thread] reminiscent of [https://github.com/zapek/Voyager Voyager] and to a lesser extent [https://github.com/amigazen/aweb3/ Aweb JavaScript 1.5 (ECMAScript 3)] as css and javascript websites can be slow to load or resolve (no JIT) and nothing from facebook, reddit etc.
Press Cancel at screenmode selector or -wb argument to get windowed version. You could use the Shift + Del shortcut or mouse wheel should work to delete all text at once. To view wikibooks set Agent to Android (telefon) aka Google Chrome 126 or iPhone aka Safari 17 setting in menus. Html5test gives 189 (1.29), 300 (1.31), 311 (1.33) out of 555, some bigger Amiga like browsers are around 370+ but it does less better.
You may have to delete the cache (Menu -> Page -> Delete cache) to fully retest big Amelinium updates or free up space.
Be aware [https://pianetaamiga.it/en/reportage-pianeta-amiga-2026/ some site pages] can use up hundreds of MBs of cache very quickly
DNS lookup failed... close browser and reboot and setup wifi again - repeat until it works again
youtube video and audio - js button for javascript must be on/shaded - Settings -> Soundoutput - AHI
Usually restricted to lower resolutions due to [https://docs.invidious.io/faq/#q-where-are-the-360p480p1080p-quality-options bandwidth]. You can always [https://docs.invidious.io/installation/#install-the-dependencies self host] for better or wait for the newest version of Odyssey OWB (webkit browser).
Telegram https://t.me/s/channel_name for public messages from vamped_amiga chatamigagames demoscenecracktros
*art local js apps like dpaint.js
There is normally no Bluetooth support for most amiga like OSs but Aros has one [https://github.com/aros-development-team/AROS/commit/6942cbfbf66426d21963a7fcd8aba6aff611a9e0 work in progress] [https://forums.raspberrypi.com/viewtopic.php?t=338466 firmware]
*Bluetooth 4.1 BCM43430A1.hcd Pi3B, Pi3A, Zero 2W
*Bluetooth 4.2 BCM4345C0.hcd Pi3B+, Pi4
*Bluetooth 5.0 BCM4345C5.hcd Pi4B rev, CM4 and maybe Pi5 and CM5
<pre>
*bthid keyboard mouse support
*btserial serial
*btpan short range wireless connecting devices
</pre>
Only the Pi5 has a RTC real time clock, the other Pis will need to use ntp services [https://github.com/aros-development-team/AROS/commit/29cd4116330dc7f692d90757eacc59fb3f31ae70 sntp] with time.cloudflare.com pool.ntp.org or Cloudflare 162.159.200.1, 162.159.200.123, 2606:4700:f1::1, 2606:4700:f1::123 or [https://github.com/bohunamiga/PiNTP PiNTP -s goodtime.ijs.si or ntp1.ptb.de] to get the date and time from the internet. Can use date in a shell e.g. date 24-Dec-2026 23:59:59 but this will need to be done again after every reset/power off. Maybe [https://github.com/aros-development-team/AROS/commit/28674a157bc56175aa668e7b62dca6fa740578dc ds3231 rtc with dtoverlay=i2c-rtc,ds3231 in config.txt]
It helps to have all usb devices already plugged in before power on to detect at the moment. Even then some usb devices will freeze the mouse cursor and the only resolution is to remove the offending usb device and reinsert. Sometimes, the reinsert leads to the mouse cursor vanishing, it is still there and responds to left mouse clicks, top of the screen and pull down the screen.
USB classes support from Prefs/Trident is still work in process
*usbaudio working on usb3 port (blue) on pi4, 400 but not working (no rt isochronous) on usb2otg (white or black) for pi3b, zero 2w
*[https://aminet.net/package/mus/midi/camd camdusbmidi] detects midi devices without a preferences file (Prefs/Env-Archive/sys/midi.prefs) as [https://www.youtube.com/watch?v=RBxHkwy4Nrw auto setup now] possibly with [https://github.com/metaneutrons/mt32-pi metaneutrons mt32-pi] [https://github.com/rtzor/mt32-pi mt32-pi fork] [https://github.com/ahmadexp/mt32-pi fork] [https://github.com/gmcn42/mt32-pi-control control of] [https://github.com/dwhinham/mt32-pi mt32-pi pi3+]. Alternative of [https://homspace.nl/samplerbox/ SamplerBox].
Will need developer clang gcc tools to look at 64bit ports of [https://archives.arosworld.org/?function=showfile&file=driver/audio/usbmidi.i386-aros.lha usbmidi], [https://aminet.net/package/mus/midi/CAMD_Toolkit CAMD_Toolkit], [https://aminet.net/package/mus/midi/camdtools camdtools], [https://github.com/cnvogelg/amiditools amiditools], [https://github.com/timoinutilis/midi-sequencer-amigaos horny src], [https://aminet.net/package/mus/midi/horny-base horny-base], [http://bnp.hansfaust.de/index.html BnP], [https://arosarchives.os4depot.net/?function=showfile&file=audio/misc/timidity.lha timidity],
Regarding 680x0 emulation, there are several options (not implemented yet) that could be considered
*[https://github.com/aros-development-team/AROS/blob/6722a0ae9e03fe5d26e32703360bd2059e0864cc/rom/m68kemu/README.md?plain=1#L424 m68kemu.library] for some Amiga productivity where the cpu is emulated and the system calls are redirected to Aros ones
*[https://github.com/BlitterStudio/amiberry amiberry] (winuae) for everything else like games
*[https://github.com/jonx/AROS/tree/aarch64-darwin-graft/arch/all-darwin/libs/emu68k emu68k]
*[https://scriptedamigaemulator.net/ Scripted Amiga] with [https://github.com/naTmeg/ScriptedAmigaEmulator ScriptedAmigaEmulator] or older [https://github.com/gbraad-amiga/ScriptedAmigaEmulator2 ScriptedAmigaEmulator2]
Hopefully getting Pi3 up to 25Mhz 68040 (non JIT) and 75Mhz 68040 (JIT)
Pi4 getting up to 50Mhz 68040 (no JIT) and 150Mhz 68040 (JIT)
[https://pinout.xyz/ GPIO 40 pins] [https://learn.sparkfun.com/tutorials/raspberry-gpio/gpio-pinout pinout]
Some exceptions:
*Physical pins 27, 28 (GPIO0, 1) are an internal I2C bus and should not be used
*The other I2C on pins 3, 5 (GPIO 2, 3) can be used generally, but be aware they have permanent pull-up resistors to 3.3V
*For MIDI use USB but there are dedicated UART pins 8, 10 (GPIO 14, 15).
With a HAT it's more awkward -- you need to know which pins are used by the HAT and avoid them. Hopefully this will be documented.
Remember all GPIOs are 3.3V (not 5V tolerant), floating/noisy inputs can cause odd behavior, and that shorting the power supplies can cause instant death of the Pi.
In the shell (Cntrl + C to end)
GPIO PIN/A/N,SET/N,GET/S,MODE/K,PULL/K
Controls and queries hardware GPIO pins via gpio.resource which is stored in the rom or Devs/ '''please test'''
*PIN -- (Required) Target GPIO pin number (e.g. 12).
*SET -- Set pin output value to 0 (LOW) or 1 (HIGH).
*GET -- Read and print current digital input level (0 or 1).
*MODE -- Configure pin mode: IN (Input), OUT (Output), ALT (Alternate).
*PULL -- Configure pull resistor: NONE, UP, DOWN.
EXAMPLES
<pre>
GPIO 12 MODE OUT
GPIO 12 SET 1
GPIO 12 GET
GPIO 13 PULL UP
</pre>
[https://gpiozero.readthedocs.io/en/stable/installing.html Current] [https://gpiozero.readthedocs.io/en/v1.2.0/api_boards.html old support for gpiozero is unknown at present] [https://energenie4u.co.uk/res/pdfs/ENER314%20UM.pdf and associated 433MHz equipment] [ USA X10 security and lights via USB] [ OpenHab with Shelly Smart Plug connected over Wi-Fi, controlled by MQTT or HTTP]
Printing only with Postscript but [https://github.com/bohunamiga/MintPRINT one] of [https://github.com/boingball/MintPRINT two] [https://github.com/Andiweli/AmiAirPrint/tree/main AirPrint] IPP has been attempted with [https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2061&pid=13954#post_13954 discussion]
Youtube
[], [], [https://www.youtube.com/watch?v=X4fmWAIv7FE Aros native on Pi3b],
[], [], [https://www.youtube.com/watch?v=TSxlYb1eQWU Installed on Pi3b+],
[], [], [https://www.youtube.com/watch?v=NFF1H3jCoz8 testing Aros native on Pi400],
[], [], [https://www.youtube.com/watch?v=nIVx7mh1E1Q&pp=ygUHYXJvcyBwadIHCQkTDAGHKiGM7w%3D%3D Aros on Thumb 2 based 32bit-ish ARM STM32H743 board],
[https://www.youtube.com/watch?v=zQM4CD64xDE&t=612s&pp=ugUEEgJlbg%3D%3D Performance under Linux] but on Aros...
{| class="wikitable sortable" width="90%"
! width="10%" |Pi
! width="10%" |Single Core 2D
! width="10%" |Single Core 3D
! width="10%" |Single Core 3D
! width="10%" |SMP 2D
! width="10%" |SMP 3D
! width="10%" |SMP 3D
! width="35%" |Comments
|-
| <!--Pi-->Pi3
| <!--Single Core 2D-->
| <!--Single Core 3D-->
| <!--Single Core 3D-->
| <!--SMP 2D-->
| <!--SMP 3D-->
| <!--SMP 3D-->
| <!--Comments-->
|-
|}
==== 32bit ====
For the Pi1 Pi2 Pi2B the status of AROS native ARMv6 for 32bit RasPi was OK. System booting, USB working (although with some issues but plans to fix them). 32bit native [http://www.aros.org/nightly1.html ARMv6 32bit nightlys] raspi-armhf-system raspi-armhf-contrib unbz2'd to fat32 microSD
===Hosted===
AArch64 CPU backend for AROS, a Cocoa/Metal display, clipboard / host-volume / CoreAudio / BSD-sockets bridges, GPU 2D via gpufx.library, a 68k→AArch64 JIT (run68k), and a full Rust std port. On [https://www.jkn.me/blog/macaros-aros-on-apple-silicon/ latest Apple Silicon] [https://github.com/jonx/Macaros early buggy alpha version of hosted Aros .dmg on MacOS12+]. Please use [https://github.com/jonx/Macaros/issues MACAros github] for issues, features etc and possibly [https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2030&pid=13910#post_13910 here]
[http://www.aros.org/snapshots1.html old linux and android hosted 32bit]
==== Hosted ====
=====64bit=====
[https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2019&rowstart=80&pid=13667#post_13667 Ubuntu Linux PC hosted Pi compiler build]
[https://github.com/BlitterStudio/aros-compiler-docker Docker based cross compiler for various Aros systems],
[https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2019&rowstart=80 From the Aros Raspberry pi 3 64bit thread]
Instructions on building 64-bit Raspberry Pi AROS and cross-compiler from sources.
You will need:
- Ubuntu 24.04 or 26.04
- qemu-system-aarch64 installed
- Internet connection
- rpi-scripts.tar.gz downloaded (https://axrt.org/download/aros/rpi/rpi-scripts.tar.gz)
1) Install prerequisites:
sudo apt install git gcc g++ make gawk bison flex bzip2 netpbm autoconf automake libc6-dev liblzo2-dev libpng-dev gcc-multilib byacc python3-mako cmake yasm curl nasm
2) Clone sources
cd <project-directory>
git clone https://github.com/aros-development-team/AROS.git --recurse-submodules
3) Extract rpi-scripts.tar.gz. Copy all files into your project directory so that you have:
AROS (the directory with cloned sources)
fix-dotdot.py
rebuild.sh
recreate-sdcard.sh
run-qemu.sh
update-sdcard.sh
4) Run ./rebuild.sh. Select option 1) toolchain-core-aarch64
This will execute process of building a cross-compiler. During this process packages will be downloaded from Internet. This process can take up to 2 hours. If there are some missing dependencies, install them with 'sudo apt install' and restart this step.
5) Run ./rebuild.sh again. Select option 2) core-raspi-aarch64
This will build system files for 64-bit Raspberry Pi AROS. This process can take around an hour.
6) Run ./recreate-sdcard.sh
This will create an sdcard.img file with contents of previous step.
7) Run ./run-qemu.sh
This will start QEMU with SD card image and ROM images. It will boot into AROS.
=====32bit=====
Ubuntu VM approach to compiling [http://lallafa.de/blog/2013/06/building-aros-hosted-for-raspbian/ Linux hosted AROS June 04, 2013]
../AROS/configure --target=linux-armhf --enable-includes=/usr/arm-linux-gnueabihf/include --x-includes=/usr/arm-linux-gnueabihf/include --x-libraries=/usr/arm-linux-gnueabihf/lib
arm-elf- is symbol-linked to arm-linux-gnueabi- (arm-linux-gnueabi- is more correct in this case, because it's going to be compiling the ARM AROSBootstrap for ARM Linux)
*armel - many of the "android" machines require since the entire OS is made for soft float VFP.
*armfp - Efika MX target, Raspberry PI, EfikaMX, Pandora and virtually everything (VFP)
Keep in mind it's possible to start hardfp AROS hosted on softfp system, though, as long as no calls between AROS and host require floating point parameters. NOTE: hardfloat objects *cannot* be linked with softfloat objects - they have a different ABI.
Just keep in mind the arm nightly build machine is quite complex beast. It needs the x86_64 host compiler to compile AROS tools. The arm version is built every night using gcc-4.6.2 crosscompiler (built together with AROS) and successfully builds armel and armhf linux hosted targets.
*needs an AROS code compiler for ARM target
*as well as unix compiler for ARM linux host (would be best to have both softfp and armhf, we have softfp only now) with full set of libraries and includes.
with—disable-crosstools $AROS_CC is always a wrapper around $KERNEL_CC ? If so, this is wrong for some ports. This can break Darwin, Windows and Android port.
Yes, Android port will build. And even work. But it's not good because the port will not be ABI-compatible with other ARM ports. Android's ABI is different from GNUEABI. For example:
<pre>
enum test {foo, bar};
enum test testvar;
</pre>
sizeof(testvar) will be equal to sizeof(int) in GNUEABI (Linux and AROS) and sizeof(short) on Android. This affects linking objects from static linklibs, for example.
Previously everything worked because $AROS_CC was a wrapper on top of $HOST_CC. And a real crosscompiler was used on non-ELF hosts.
Android is the same. $KERNEL_CC is incompatible with AROS.
compiler=kernel is appropriate _ONLY FOR CODE WHICH RUNS ON HOST OS_ (or barebone hardware, if we talk about native). This includes bootstraps, their linklibs, and host-side dynamic libraries (Windows makes extensive use of them because of architectural considerations.
No single AROS object should be compiled with this setting. $KERNEL_CC is really compatible with AROS *ONLY IN LINUX-HOSTED* and no more. On other systems (Darwin, Windows, Android) this is not true any more, and compiler=kernel is never going to work.
If you want to compile your AROS module against host OS includes, append the following to USER_INCLUDES (or USER_CFLAGS, this is effectively the same):
-isystem $(GENINCDIR) $(KERNEL_INCLUDES)
$(KERNEL_INCLUDES) expands to:
-isystem <your_os_includes> -isystem <host_OS_gcc_private_includes>
-nostdinc
This makes AROS compiler adhering to host OS APIs.
If you want some preprocessor symbols based on what your host OS actually is, add something like -DHOST_OS_$(AROS_HOST_ARCH).
Why is there $(GENINCDIR) at all? Because host OS has its own libc includes, which would conflict with AROS ones. And the host OS libc is not binary-compatible with AROS one.
Why doesn't Windows-hosted port use $(KERNEL_INCLUDES) ? Because WinAPI includes conflict with AROS ones in fundamental typedefs, like WORD, BYTE and BOOL. It's almost impossible to deal with this in any other way than rewriting WinAPI definitions using AROS types.
Building under centos 6.3 (i386) currently, and AROS creates the toolchain itself. haven't yet committed the necessary changes but "./configure --target=raspi-armhf" is enough to start, then "make arosboot-raspi" will generate arosraspi.img (containing the bootstrap, kernel.resource, and exec.library) as well as arosraspi.rom (containing all the other essentials components such as dos, graphics etc). It will also copy over a config.txt file to make the raspi bootstrap code load the correct kernel, and a cmdline.txt that enables exec debug output.
*armel = typically Debian 6, Ubuntu Maverick, Android,
*armhf = typically Debian 7, Debian 8, Ubuntu Precise,
Cross-compiling Ubuntu ARM softfp
<pre>
sudo sh
echo 'foreign-architecture armel' >>/etc/dpkg/dpkg.cfg.d/multiarch
echo 'deb [arch=armel] http://ports.ubuntu.com/ precise main universe' >/etc/apt/sources.list.d/armel.list
apt-get update
apt-get install gcc-arm-linux-gnueabi libx11-dev:armel libsdl-dev:armel
</pre>
<pre>
./configure --target=linux-arm --x-includes=/usr/include \
--enable-includes=/usr/arm-linux-gnueabi/include
</pre>
Cross-compiling Ubuntu ARM hard-float
<pre>
sudo sh
echo 'foreign-architecture armhf' >>/etc/dpkg/dpkg.cfg.d/multiarch
echo 'deb [arch=armhf] http://ports.ubuntu.com/ precise main universe' >/etc/apt/sources.list.d/armhf.list
apt-get update
apt-get install gcc-arm-linux-gnueabihf libx11-dev:armhf libsdl-dev:armhf
</pre>
<pre>
./configure --target=linux-armhf --x-includes=/usr/include \
--enable-includes=/usr/arm-linux-gnueabihf/include
</pre>
Now, the AROS build is configured properly and all you need to do is:
make
==Build==
===64bit===
===32bit===
# download/checkout the source someplace, e.g. /build/AROS-Src/
# make a directory to store external sources AROS downloads, e.g. /build/Ports
# make a build directory, e.g. /build/aros-raspi-armhf
# cd into the build dir, configure, and then run make -:
<pre>
>cd /build/aros-raspi-armhf
>/build/AROS-Src/configure --target=raspberrypi-armhf --with-serial-debug --enable-ccache --with-portssources=/build/Ports
>make
>make arosboot-raspi
</pre>
then copy the files from /build/aros-raspi-armhf/bin/raspi-armhf/AROS/ onto an sdcard, and download/copy the Raspi firmware files onto it.
You should then be able to boot the sdcard on your RasPi.
The current W.I.P tree to svn. it can be built as follows ..
<pre>
./configure --target=raspi-armhf
make arosboot-raspi
</pre>
That will generate arosraspi.img, arosraspi.rom and config.txt in bin/raspi-arm/AROS - so either copy just those files to a fat formatted SD card (with the firmware files on), or copy the whole contents of the AROS folder.
NB - if you have a Linux/other install, backup the existing config.txt first
arosraspi.img contains the bootstrap (which has very basic mailbox code, framebuffer/gpio init, and console "emulation" via code pinched from our libbootconsole), kernel.resource, and exec.library
arosraspi.rom contains all the other components needed to boot AROS.
The config.txt file will tell the RasPI bootstrap to load the arosraspi kernel and ramdisk (rom).
the bootstrap has minimal mailbox code, planning on adding either a resource or library that driver/app code will use to access it (likewise for GPIO)
Help building AROS hosted on Linux ARM
Was looking a way to use more my Handheld ARM based called Pyra (Dragonbox Pyra) an ARM (Omap5 cpu with 4GB ram) linux based machine (Debian Buster v10 with kernel 5.6.19 adapted) and have a try to compile the latest Aros sources by Deadwood directly on this device.
Compilation stops after build libpopupmenu.a and trying to build libatomic have this error:
<pre>
Configuring build in bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic
configure: WARNING: unrecognized options: --disable-nls, --without-x
checking for --enable-version-specific-runtime-libs... no
checking for --enable-generated-files-in-srcdir... no
checking build system type... arm-unknown-linux-gnu
checking host system type... arm-unknown-aros
checking target system type... arm-unknown-aros
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for arm-aros-strip... /media/farox/pyra2/arosbuilds/toolchain-core-armhf/arm-aros-strip
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for arm-aros-gcc... /media/farox/pyra2/arosbuilds/toolchain-core-armhf/arm-aros-gcc
checking whether the C compiler works... no
configure: error: in /media/farox/pyra2/arosbuilds/toolchain-core-armhf-build/bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic':
configure: error: C compiler cannot create executables
See config.log' for more details
make[2]: *** [mmakefile:4489: /media/farox/pyra2/arosbuilds/toolchain-core-armhf-build/bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic/.configured] Error 77
[MMAKE] make --no-print-directory TOP=/media/farox/pyra2/arosbuilds/toolchain-core-armhf-build SRCDIR=/media/farox/pyra2/arosbuilds/AROS CURDIR=tools/crosstools/gnu TARGET=tools-crosstools-gcc-libatomic-configure -s --file=mmakefile tools-crosstools-gcc-libatomic-configure failed: 512
[MMAKE] Error: Error while running make in tools/crosstools/gnu: No such file or directory
make[1]: *** [Makefile:361: linklibs-libatomic] Error 10
make: *** [Makefile:183: crosstools] Error 2
</pre>
looking at config.log on arosbuilds/toolchain-core-armhf-build/bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic
found that arosbuilds/toolchain-core-armhf/arm-aros-ld: cannot find -laeabi
so do make linklibs-aeabi-arm-quick
and the missing lib was built.
now the next stop is at
fatal error: bits/libc-header-start.h: No such file or directory
and
fatal error: sys/cdefs.h: No such file or directory
in many places so after checking that have this missing include files i have noted that my include path is a bit different, standard searching path is /usr/arm-linux-gnueabihf but in my system is /usr/include/arm-linux-gnueabihf
so if i add my path to some mmakefiles compilation goes on....but is a better way to add this path to avoid every mmakefiles to be changed?
fixed with adding
-I/usr/include/arm-linux-gnueabihf
to where is missing on mmakefiles like
USER_INCLUDES := -isystem $(GENINCDIR) -I/usr/include/arm-linux-gnueabihf $(KERNEL_INCLUDES)
P.s. I have changed many mmakefiles and have at least compiled (after many hours) the toolchain doing make every time in arosbuilds/toolchain-core-armhf-build (also have to disable making tests under cplusplus but don't remember the directory ...) but ask an help to have an automated way to correctly build without modify mmakefiles.
Last time built armhf target was around 2 years ago. At that point built is via cross-compilation from linux (ubuntu 22.04) using linux armhf crosscompiler (this can explain the path differences you are experiencing) as well as using AROS gcc cross-compiler in version 6.5.0 (build with option 21) in rebuild.sh). Since then AROS GCC has been updated to 10.5.0 and don't believe anyone tried to build the armhf target again.
My suggestion would be to downgrade GCC to 6.5.0 (via editing AROS/config/gcc_def file) and try to first build using cross-compilation from x86_64 linux. Once that works, you will have a "template" to compare to native compilation under arm linux.
Thanks for your suggestion...but think the toolchain with GCC 10.5.0 is compilable if i found a way to pass the path of my system to the script that build (option 21 on rebuild).
The other only changes are (but don't know where to modify...) is to add the build of libaeabi and disable the building of some tests under cplusplus that use exceptions and is not supported under ARM. try to crosscompile with my Linux amd64 PC.
For paths look into core-linux-armhf/bin/linux-armhf/gen/config/target.cfg. A number of build-wide variable is set there containing paths to local build system. These variables and the target.cfg file are generated by AROS ./configure script.
Thanks compilation now go forward...changed target.cfg under "toolchain-core-armhf-build/bin/linux-arm/gen/config" and do make on "toolchain-core-armhf-build" dir.
Need to find where to enable build libaeabi.a so can build the entire toolchain with option 21 of rebuild.sh
Found something that looks like libeabi in AROS/arm-all/arm-aeabi/mmakefile.src. Try adding a third line there:
#MM- linklibs-armhd : libklibs-aeabi-arm
Don't remember needing this library. Possibly the 6.5.0 GCC somehow does this while 10.5.0 is missing this.
Try adding this line (and the variant "linklibs-armhf" instead of hd) but it did not solve the automatic building of the missing lib. I must do "linklibs-aeabi-arm-quick".
Anyway after have build the aeabi lib i succefully built the toolchain (after many hours...). Smile
To test I restarted from selecting option 21 (on rebuild.sh) but after many hours i get the same error of the kernel includes not found...maybe i need to modify the configure script for my case.
With the toolchain built i try to build the core-linux-armhf (DEBUG) (option 22) but after a while it stopped with
"cannot find -laeabi " so i made it built manually...and now i can continue compiling...i'll let you know if all goes ok.
== Hardware ==
===64bit===
====BCM2712====
With the Pi5
Broadcom VideoCore 7 vc7 is an integrated GPU with 12 cores and up to 800 MHz clock. VideoCore VII is capable of OpenGL ES 3.1 and Vulkan 1.2. The driver support for the Raspberry Pi continues to build upon the [https://lore.kernel.org/dri-devel/20230928114532.167854-1-itoral@igalia.com/ open-source V3D driver] stack within [https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25450 Mesa] hopefully be merged for Mesa 23.3. x265 HEVC accelerated untested, x264/h.264 and VP9 cpu only.
*Raspberry Pi M.2 HAT+ Expansion Board
*Geekworm X1001 PCIe to M.2 Key-M NVMe
*Geekworm X1003 PCIe to M.2 HAT NVMe SSD PIP Board for Raspberry Pi 5
*Pineboards Pi Hut HatDrive! M.2 HAT 2024/V4
*Hat+ Gen2 Gen3 Nvme
*GeeekPi 52Pi N04 for Raspberry Pi 5 NVME M.2
*
*2024 RPI AI HAT - Hailo 20TOPs no LLMs
*2026 RPI AI HAT+ 2 - Hailo 40TOPs slightly better?
[https://www.raspberrypi.com/documentation/accessories/camera.html Cameras for Pi]
*Raspberry Pi camera module, the V3 with Sony IMX708 back-illuminated CMOS 12 Megapixel sensor
*Raspberry Pi Camera Module V2 – 8MP Sony IMX219 Sensor
*Raspberry Pi camera Rev 1.3, 5MP 1080P OV5647 image/video module, 2592 x 1944 pixels
====BCM2711====
With the Pi4 an ARM a72 cpu is about x3 times the size of an a53 in the Pi3
the 2711b line used more power when idle, compared to the 2711c
*2018 Raspberry Pi PoE HAT Power Over Ethernet Hat - design issues
*2020 Raspberry Pi PoE+ HAT Power Over Ethernet Hat Pi3b+ Pi4 only - better design
*Waveshare PoE HAT (B) with cooling fan for Raspberry Pi 3B+/4B 802.3af PoE
*[https://github.com/axizo-pi/V3DLib vc6 V3D 4.2] is derived from [https://docs.broadcom.com/doc/12358545 vc4], but it is significantly different
The QPU pipeline stays mostly the same, you still have an add ALU and a multiply ALU and it can issue two ALU OPs per cycle. There is still 4 SIMD lanes, interleaved over 4 cycles.
The instruction encoding for the QPUs is different, but the core instructions are the same.
Instructions for packed 8 bit int math has been dropped, along with most of the pack modes.
Instructions for packed 16bit float math has been added (2 floats at in a single operation)
With vc5/vc6, you write two packed 16f value to the tilebuffer (or four writes of 32f, if you are using the rgba32f framebuffer). And there is a handy vfpack operation which allows you to pack two f32s into a single 32bit value in a single instruction. You can vfpack directly into the tile buffer register.
the multiply ALU can now fadd, so you can issue two fadds per instruction. the add ALU has gained a bunch of new instructions
the A and B register files have been merged. You still only get an A read and a B read per instruction, but they read from one big register file (which means the underlying memory block has gone from two sets of "one read port, one write port" to one "two read ports, one write port" block)
The theoretical max FLOPs per QPU remains the same at two per cycle, other than the bump from 400mhz to 500mhx but it looks like a lot of effort has been put putting those theoretical FLOPs to better use.
*vc4 could run one or two threads per QPU. When you ran in two thread mode, the available register file halfed to 32 registers.
*vc5 added a four thread per QPU mode, with 16 registers per thread.
*vc6 doubled the size of the register file. You could now use all 64 threads in two thread mode and 32 registers in for thread mode. Single thread mode was removed, you always have at least two threads.
With the threading improvements, the QPUs should spent much less time idle waiting NOPs for memory requests. Most of the design changes have gone to improving the fixed function hardware around the QPUs. A fixed function blend unit has been added, which should reduce load on the QPUs when doing alpha blending. hope software blending is still possible
The tile buffer can now store upto 4 render targets (up to 128bits per pixel, so if you are using 4 32bit render targets, you can't have a depth buffer)
A MMU, allowing a much simpler/faster kernel driver.
Many more texture formats, framebuffer formats.
h264/x264 as Pi3
All the features needed for opengl es 3.0
H.265 / HEVC decoder is a HEVCv2 Main 4:4:4 10 design supporting bitstreams up to profile 5.1
HEVC hardware decode supports 4kp60, 10-bit. Audio output is pretty much unchanged, but the HDMI audio channels now support 8x192kHz bitrates
Each ALU typically have 2 floating point operators, and as you pointed out in a earlier post videocore 6 is no exception, with both a multiply and additive floating point operator. Thus theoretical GFLOPs are calculated with both operators in mind. That is what the 2 in my formula represents, and is common across any modern programmable shader, whether you calculate Nvidia, AMD, Intel, Boardcom or any other company's GPUs. Total ALUs * 2 * GHz clock = GFLOPs, In the case of Raspberry Pi 3, it's 24 ALUs * 2 operators * 0.4GHz = 19.2GFLOPs
If the Videocore 6 does indeed only have 16 ALUs (16 * 2 * 0.5GHz), you'd have only 16GFLOPs but they are better utilised
Possible maximum performance
<pre>
VideoCore IV @ 250MHz: 250 [MHz] x 3 [slice] x 4 [qpu/slice] x 4 [processor] x 2 [op/clock] = 24 Gflop/s
VideoCore IV @ 300MHz: 300 [MHz] x 3 [slice] x 4 [qpu/slice] x 4 [processor] x 2 [op/clock] = 28.8 Gflop/s
VideoCore VI @ 500MHz: 500 [MHz] x 2 [slice] x 4 [qpu/slice] x 4 [processor] x 2 [op/clock] = 32 Gflop/s
</pre>
Faster LPDDR4 memory.
====BCM2837====
With the Pi3
* Broadcom BCM43438 chip provides 2.4 GHz 802.11n wireless LAN, Bluetooth Low Energy, and Bluetooth 4.1 Classic radio support, 3B+ [https://github.com/aros-development-team/AROS/commit/afa5bc0bb17d5dd06bcfdbac00853a3799ca8d76 LAN7515]
The overclock ability has diminished with each chip version as the energy usage has increased. BCM2837 is one of the warmest yet and benefits from active fan cooling if all four cpu cores are in use for a short while. Video playback is not affected due to the custom support in the GPU. 5 V / 2.4 or 2.5 amp power supply recommended if all four cpu cores are running, else throttling (cpu slowdown) might occur.
Dual VDP and scalable QPU in VC4 and x.264/h.264 accelerated untested only and VP9 on cpu or neon help
ARMv8-A has [https://developer.arm.com/documentation/102412/0100/Privilege-and-Exception-levels privilege levels] where userspace typically runs at ‘EL0’, the kernel at ‘EL1’ or ‘EL2’ and the firmware at the highest level ‘EL3’.
===32bit===
=== Core Kernel ===
====BCM2708(family)====
which includes the [http://elinux.org/RPi_Hardware BCM2835] (ARM1176JZF-S 700 MHz CPU + VideoCore IV GPU + up to 1GB RAM)
*Framebuffer (fb) using mailbox
*IRQ scheduler, etc
*Arasan based SD Card controller
*Synopsis DesignWare USB 2.0 OTG controller [http://networkdirection.net/index.php?option=com_content&view=article&id=106:rasperry-pi-usb-controller&catid=45:raspberry-pi&Itemid=54 Unofficial DOCS pdf], [dwc_otg.c FreeBSD], [], [https://www.riscosopen.org/viewer/view/mixed/RiscOS/Sources/HWSupport/USB/Controllers/DWCDriver/ RiscOS USB Driver], [https://www.riscosopen.org/forum/forums/5/topics/878 RiscOS USB Discussion], [https://www.riscosopen.org/forum/forums/11/topics/1893 Other USB RiscOS], [http://plan9.bell-labs.com/plan9/index.html Plan9 Miller's usb] http://plan9.bell-labs.com/sources/contrib/miller/, [https://github.com/Chadderz121/csud CSUD driver],
*[http://www.smsc.com/media/Downloads_Public/Data_Sheets/9512.pdf SMSC 9512] USB LAN/Hub chip
*CMOS RAM
*VCHIQ port which sends messages to the GPU e.g. for mouse, keyboard, audio on HDMI, etc
*Audio Driver
*Serial Peripheral Interface Bus (SPI)
*[http://www.susa.net/wordpress/2012/06/raspberry-pi-pcf8563-real-time-clock-rtc/ I2C registers]
*I2S
*Universal Asynchronous Receiver Transmitter (UART)
*[http://elinux.org/RPi_BCM2835_GPIOs GPIOs] and [http://www.adafruit.com/blog/2012/08/17/broadcom-bcm2835-peripheral-memory-map-and-gpio-alternate-use-chart-piday-raspberrypi-raspberry_pi/ Alternative view of GPIO]
BCM2836
* For Pi B+, PI 2 and Pi 3 SMSC LAN9514 chip adding 10/100 Ethernet connectivity and four USB channels to the board
*[http://www.andrewscheller.co.uk/rpi_pcb_modules.html PCB], [http://elinux.org/RPi_Low-level_peripherals Low level features],
Implemented so far...
# Modify the configure system so that it correctly builds for the arm hardware float raspi target.
# Implemented the bootstrap to load the aros modules and prepare the arm to jump into them. Reworked the x86 console support so that parts can be stolen for raspi to use since t has no basic functionality to output to the display.
# Implemented a kernel.resource to prepare the raspi for running aros and provide the low level api calls to expose available resources and allow exec, etc function.
# Implemented serial debug support
# Implemented the exec (and kernel) functionality required to make multitasking work (and interrupts, exceptions, syscalls, etc)
# Implemented a timer.device to utilise the hardware timers.
# Implemented a very basic gfx driver to expose the hardware's framebuffer.
# Implemented an SD-Card driver for AROS which presently only supports the raspi's chipset but can easily be modified to support all sd-card hardware and media.
# Fixed the fat filesystem support in AROS so that it can boot on RasPi's normal SD-Card setup. The "rom" image files needed use a different filename than the default linux, etc images so can be easily installed without harming the existing files - you only need to change the loaded images in the config file to get aros to boot.
# Updated the build scripts to automatically download the necessary raspi firmware files and wrap it all up so that you can simply extract the archive to a fat formatted sdcard and boot it on the raspi without having to get anything else.
# fix everything in contrib and ports to build for raspi (needs proper testing/fixes but allows every component to actually compile at least, including owb) + numerous other fixes to get things working on arm/raspi ..
Improvements...
# Implement a USB chipset driver "OR" finish the existing one [https://github.com/aros-development-team/AROS/commit/c07d13c724f944674be5db54fc6a71ee72a01809 usb otg] - the current code is mostly a skeleton that should initialise the chipset and then needs relevant code to support the different transfer types. It also has the "virtual" hub code in place to represent the raspi's USB port (from poseidons p.o.v)
# Implement a driver for the USB NIC (a few weeks - depends on USB above)
# Write an [https://github.com/aros-development-team/AROS/commit/d55d0f74d20b769bbb8c8d386e5c1d7a9154f05a audio driver] (a few weeks - independent of USB) and [https://github.com/aros-development-team/AROS/commit/e93a4c245f27a87c9c4c1d39206694b39059998a HDMI]
# fix syscall bug in the current raspi kernel code
# Graphics depend on having a decent "bcmdma.resource" implemented as to use the cpu's dma engine. The sd card driver needs to use it for transfers to/from the controller - and the gfx system needs to use it for "blitting".
# [https://github.com/aros-development-team/AROS/commit/4019d84e4975d4dad987a12d57fe108f5ac048e6 Improve the gfx driver], [ vc4gfx HIDD] add [http://dri.freedesktop.org/wiki/VC4/ Gallium3D support]
# [https://github.com/aros-development-team/AROS/commit/b13905b3e8e45b089f520b44692c81affddd066f Improve] the [https://github.com/aros-development-team/AROS/commit/3a876755c070f5c73c4f53c7f4d35b4f923088b9 sdcard] device driver - which is also pretty basic but should work with most cards, rework it to also support pci, etc. sd card interfaces on x86
# The current code using very rudimentary access to the gpio interface - so that should be implemented as some resource for other components to access, as-well as the i2c interface exposed over the gpio interface. that should have a hidd class implemented which uses the gpio resource to communicate.
Boot up typical for most other OSs before the open sourcing of many binary blobs from 2017 onwards
On power-up, the rpi [http://www.open.com.au/mikem/bcm2835/ BCM 2835] [https://github.com/hermanhermitage/videocoreiv VideoCore4] GPU, not the ARM CPU, is in control, and the SD card slot is the only peripheral device with power. The firmware burned into the BCM2835's VideoCoreIV GPU PROM requires a DOS-style partition table; a FAT-formatted first partition; and the freely redistributable but closed sourced Broadcom files “bootcode.bin” and “start.elf” in that partition.
The boot sequence carries out several pre-boot tasks
*On powering of the rpi, the GPU reads and executes bootcode.bin, which then loads start.elf
*The GPU loads the “start.elf” file, eventually, into the L2 cache and then executes it
*configures the memory split for the CPU and GPU
*reads and parses “config.txt” from the same partition on the SD card and applies the settings (like a PC’s BIOS settings)
*loads the “kernel.img” file, again from the same partition
*activates the CPU to begin executing the loaded kernel image
The CPU/GPU memory split is hard-coded into start.elf, so Broadcom provides three start.elf images, to give 32M, 64M, or 128M to the GPU for multimedia performance, and the remainder to the CPU.
RPi uses [https://github.com/raspberrypi/firmware some closed source loaders] and at some point it loads a binary blob named "kernel.img" at 0x8000, at that point there would be a rudimentary Aros alive. If one wants to use the SD-card then there would have to be a driver for the interface and a fat filesystem handler (SD-card has to be formatted to fat filesystem)
Boot code and kernel are now linked together and made into that binary blob, just for starters. Raspberry Pi uses [http://kernelnomicon.org/?p=133 u-boot] and [http://kernelnomicon.org/?p=138 UBoot] as bootloader, there's already some code in the Efika MX port for that. UBoot is a native bootloader and not just for the raspberry pi, it loads after start.elf.
You can find Efika MX port from arch implementations, some hacking is needed for the mmakefile.src'es as iit dates back to before the Aros crosstool era or else you get some weird errors while building. You also need to code the bootstrap and serial handling.
At the moment it seems that a fastest route for the native build would be to make one binary blob without using the package system. Raspberry's memory layout is pretty simple and if the implemented u-boot doesn't support loading other modules
<pre>
? - alias for 'help'
mtest - simple RAM test
autoscr - run script from memory
base - print or set address offset
bbm - BBM sub-system
bdinfo - print Board Info structure
boot - boot default, i.e., run 'bootcmd'
bootd - boot default, i.e., run 'bootcmd'
bootm - boot application image from memory
bootp - boot image via network using BootP/TFTP protocol
cmp - memory compare
coninfo - print console devices and information
cp - memory copy
crc32 - checksum calculation
echo - echo args to console
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls - list files in a directory (default /)
go - start application at address 'addr'
help - print online help
iminfo - print header information for application image
itest - return true/false on integer compare
jade -
loadb - load binary file over serial line (kermit mode)
loads - load S-Record file over serial line
loady - load binary file over serial line (ymodem mode)
loop - infinite loop on address range
md - memory display
mm - memory modify (auto-incrementing)
mtest - simple RAM test
mw - memory write (fill)
nfs - boot image via network using NFS protocol
nm - memory modify (constant address)
pci - list and access PCI Configuration Space
ping - send ICMP ECHO_REQUEST to network host
printenv - print environment variables
rarpboot - boot image via network using RARP/TFTP protocol
reset - Perform RESET of the CPU
run - run commands in an environment variable
saveenv - save environment variables to persistent storage
saves - save S-Record file over serial line
setenv - set environment variables
sleep - delay execution for some time
tftpboot - boot image via network using TFTP protocol
USB - USB sub-system
usbboot - boot from USB device
version - print monitor version
</pre>
And there is one more thing about modular ports. In order to actually implement this, your bootstrapping environment should provide the ability to load several files. On PC this is provided by GRUB2. on CHRP you can read filesystem via OpenFirmware, and Sam's Parthenope relies on modified u-boot. If your bootstrap allows to load only a single file, then you stuck with monolithic kickstart. By the way... u-boot allows not only to boot up a single uImage or zImage, it also allows to write client programs AFAIK. With this approach, you actually can write modular bootstrap for ARM AROS using unmodified u-boot.
Most used [http://www.compulab.co.il/workspace/mediawiki/index.php5/U-Boot_quick_reference uboot options] are fatls usb 0:1,
the reason behind INTB_KERNEL is to allow use of the standard Exec function AddIntServer() to add interrupt handlers for
hardware drivers etc. AmigaOS never used it for abstract hardware drivers. AmigaOS routed only raw hardware IRQs there. Their assignment was hardcoded. As well as number of them. Actually on AmigaOS every bus has its own interrupt subsystem. For example PCI bus. PCI interrupts on Amiga are routed to a single exec interrupt. 1:1 relationship between CPU and hardware interrupts is present only on PC.
IMHO we miss things like AddInterrupt/RemInterrupt methods on our PCI subsystem's device class. PCI bus class should map these methods to whatever is appropriate. This is how it is done on AmigaOS and friends. When these are implemented, raw kernel.resource API will be needed only for several PC-specific drivers with hardwired resources. Exec IRQs are real IRQs only on Amiga hardware. On other machines they can be emulated where appropriate (VBlank is a good example). kernel.resource is meant to be different, its IRQs are hardware-agnostic, they are plain "Hardware IRQ number X, whatever this means". They are low-level actually, and meaningful only in the context of a particular system.
Was that not the transition from irq.hidd to kernel.resource? No. A long time ago there was another hacky bit named INTB_TIMERTICK. It was "abstract timer interrupt", used by timer.device. It was the same as VBlank, but with larger frequency. I removed it, because kernel.resource API was a cleaner way to access this interrupt. Furthermore, there can be more than one timer in the system. Thinking about bringing back timer HIDD definitions again. hpet.resource is a bad idea.
Can someone please enlighten me a little on how the scheduler is meant to work?
Poseidon.library creates its "Poseidon Event Task" during RTF_COLDSTART -> then calls Wait(), and ends up in limbo because wait disables interrupts (used for the scheduler heartbeat), and basically waits forever because the sigbit is never set, since krnSwitch doesn't switch the task unless TF_SWITCH is set, and no codepath run during this seems to set it?? TF_SWITCH does not disable/enable switching. This flag just enables to run user-supplied hook when the task is being switched away. It is completely safe to call Wait() in Disable()d state. Doing this actually temporarily breaks this state. IDNestCnt gets remembered in struct Task, then next task is selected, and its IDNestCnt is restored in sysbase (see kernel_scheduler.c). If there are no other tasks, then your cpu_Dispatch() should enable interrupts on the CPU and enter idle mode. See x86 implementation for good example.
You miss what happens next...
1. KrnSwitch() saves context of your task, saves IDNestCnt (core_Switch() and cpu_Switch()), then drops into cpu_Dispatch().
2. cpu_Dispatch() calls core_Dispatch. Then two cases are possible:
2a. There is a READY task. It is picked up, its IDNestCnt is restored in SysBase, then cpu_Dispatch() needs to restore registers and exit. The next task is run.
2b. There are no READY tasks. core_Dispatch() returns NULL. In this case your cpu_Dispatch() should enter idle loop. It should just enable interrupts on the CPU and put it on halt. This allows it to process hardware interrupts. Eventually some of your interrupt handlers wakes up your task and puts it into READY list.
My heartbeat interrupt has been slowed atm to help debugging - but it never actually gets a chance to fire because of the Wait() disabling interrupts. Perhaps you have forgotten to enable interrupts in your idle loop.
There is a change in the format of AROS executables. Until now we were using Elf RELocable files which are usually used as intermediate object files. We had them for various reasons, one of them was how AROS files were built in the past. That days we had no real aros cross compiler and the option to embed relocation data in unix executables (or in executable files in general) was rather new and not every linux/unix system had it. Therefore we have decided to use intermediate files. Although it was somehow working (and it is still working :-)), it has some drawbacks. Therefore decided to introduce real Elf EXEC types, in first turn implemented on ARM target with option to expand in future to all other AROS architectures.
The first patch was pretty easy and appeared to work somehow. It generated nice executables with embedded relocation info. Not only that, it also removed all global symbols adjusting relocation data to be relative to the beginning of the sections. That move reduced number of symbols in each executable significantly (depending on the file between 20 and 80% of all symbols could be removed). The only symbols that stayed in the file are local ones - due to the nature of the patch wasn't able to remove them since we have not seen them in the symbol hash table.
The patch didn't worked though. The files were relocated, AROS kernel loaded, but it crashed very early. What happened? Well, the nature of ARM relocations happened :)
Most of the relocation data on all machines is rather simple. Relocation can be absolute or pc-relative, sometimes the offset has to be bit shifted. On ARM v7 there is another one. There, when one wants to load an address of function/variable into register a combination of two instructions can be used: movw and movt. The first one loads immediate into lower 16 bits of a register while clearing upper 16 bits. The second one loads immediate into upper 16 bits without touching lower halfword. Loading of a pointer into a register looks like this:
movw r0, #:lower16:label
movt r0, #:upper16:label
In this case there are two relocations - one for lower halfword and another for upper. If an overflow of lower 16 bits occurs during relocation process, the upper one should be updated as well. Unfortunately with current patch and with typical ARM executables there is not enough information to perform the calculations.
There are two options - the first one would be to give up and go back to "fake" executables, another one would be to change from REL to RELA relocation info. The latter contains an addend, extra data which can be used to perform all the relocation calculations I need.
Decided for the second option. The patch is already in the works. There is another function for the binutils' bfd backend to perform the final relocation. There can decide what to do with every reloc info, modify data and eventually strip some symbols. An advantage is - at this stage of the linking process have also full access to all local symbols so can change all relocations section relative and eventually strip all symbols from the files.
GPU
VCore developed by Alphamosaic Ltd and now owned by Broadcom. Most of start.elf runs on the GPU. Placing ALL the userland GPU code in the videocore.hidd isn't going to be a terribly big problem because the code they published is nothing more than a shim that sends data straight to the GPU to execute.
The good news about this is that we only need to write our HIDD using the OpenVG API. The shim is relatively small codewise and lives in the ARM memory (the actual OpenVG code itself lives in the GPU RAM area and its loaded from start.elf). That's also the bad news. Our driver has to translate AROS video calls to OpenVG calls, for most tasks it should be easy, for some, not so much. It's still probably less difficult and less work, than controlling the GPU directly.
The other good news is that anything done through OpenVG happens on the GPU, its truly accelerated. It also has some nice font functions, meaning we can lead into an accelerated text mode later.
Basically, AROS resets or locks up when it tries to use AROS_ATOMIC_INC or DEC. If I comment out the byte/word operations in the header files and use non-atomic operations, the code works as expected.
have read that the L1 cache needs to be enabled to use LDREX and co (which I also read is only meant to be used on multi processor systems with shared memory) - however I am certain this is correctly enabled.
If you are using LREX or STREX, you should have L1 cache enabled, at least on the ARM CPU I work with at work.
L1 cache is enabled by enabling the MMU *AND* setting the C and I bits in the CPU - the C bit is ignored, and the I bit only covers the 16 byte instruction pipeline if the MMU is not enabled.
Can you verify that your assembly is generating LDREX/STREX? From the behavior, it almost sounds like its generating the default Semaphore locked atomics.
Impossible. There are no semaphore-locked atomics. There are Disable()/Enable()-based ones instead. And there's a special #define AROS_NO_ATOMIC_OPERATIONS in this case, which tweaks Disable()/Enable() implementations not to recurse forever.
I have tested this on ARMv5 which does not have ldrex/strex, it works fine. On those ARMs there's no way to have real atomics. On other OSes (like Linux) this is done by introducing things like atomic_t, which appears to be a complex structure, holding the value together with accompanying spinlock (implemented using swp).
#warning "TODO: lookup optimal mmu table settings for raspi memory"
/* Set up an identity-mapping for all 4GB */
for(x = 0; x < 4096; x ++)
{
pagetable[x] = x<<20 | (0x40002|0x80000|0x010000|0x00C00|0x04);
}
Shouldn't there be a second loop that sets the 'C' bit in the descriptor for the RAM pages?
Currently, you have TEX=0, C=0, B=1 for all pages (Shared Device).
You should have TEX=0, C=1, B=0 for RAM (Write-Through, Cached)
So ..
pagetable[x] = x<<20 | 2;
should be enough?
No, for RAM you need to change the '| 0x40' to '| 0x80'
tell dosboot the correct defaults to use
Please don't do this. This bootconfig.c is a deprecated legacy thing. I wanted it to go away completely with time. Instead, display drivers should auto-install themselves during own initialization phase. I. e. detect hardware=>instantiate itself. This should make things way simpler. With this approach you only need to add the driver into KS image to get the device autobooted. No hardcoded stuff.
Currently VESA and VGA drivers do this, look there for examples. never rewrote ATI driver because i don't have any test system for it.
they defined a smaller AROSCPUContext than the ExceptionContext - yet reference it as ExceptionContext in other places, and since it hasn't allocated enough storage for ExceptionContext, are corrupting memory/the structure (since the elements that are there don't map 1 to 1 with the exception context).
AFAIK, AROS has been moving in a different direction to this in recent years. It is the job of graphics HIDDs to allocate bitmaps etc. so that they have the most suitable characteristics, including allocating them from GPU RAM where possible. The concept of chip RAM is only for legacy code, and most if not all non-68k platforms should have all system RAM
marked as chip.
BTW, is the video processing code you mention CPU code or GPU code?
Also, IIRC we have support for "external memory allocators". Perhaps that's what we need for the allocation of GPU RAM through the mailbox.
All hosted and x86 native ports should use proper context formats.
trying to clarify if the vblank handler has to have run by this point to prevent this deadlock. Actually, no. Unless you have installed VBlank handler which should wake up at some point. Without VBlank there will be no quantum count. Consequently, there will be no forced preemption. But the rest will work, and multitasking will be cooperative (switch happens only when current task voluntarily gives up the CPU). Does it depend on the vblank having run before this point? and if yes what does that mean on systems where it might be able to run enough code (e.g. get to this point) before the vblank interrupt has triggered? What is it waiting for? It could wait for timer, in this case you need timer.device working. VBlank is currently needed for exec's quantum counter. In current native ports we have only a single timer, which is served by timer.device. VBlank is simulated by timer.device also. If your machine has two timers, then you can use one of them for VBlank, and another for timer.device, this will simplify things down. VBlank needs to be 50 Hz for historical reasons, many programs use it as cheap timer. I am periodically thinking about making some abstract mechanism to be able to change quantum source (and untie it from 50 Hz), but have no time to come up with something good. Additionally i started disliking timer.device hardcoded design when PC has got many timers (old 8253, APIC, HPET).
Currently i think there should be some low-level entity representing tick source. timer.device should just select the most appropriate source for its units.
The BCM2835 has 4 GPU based timer sources - 2 are used by the GPU, so im using Timer3 for our heartbeat and the remaining one will be free to the system. There is also the less capable ARM timer but that is dependent on the CPU frequency. Very good. You won't need any emulation. Set the heartbeat to 50 Hz and drive VBlank from it. Use other timer for MicroHZ.
Can you use the 'econsole.hook' I make for debugging the Sam460 via the serial port?
It provides a before-anything-else shell prompt on the serial port. You can then do 'NewCLI' to test your graphics, or use any DOS command in shellcommands.resource.
You should just be able to add econsole.hook to your module list, and use 'econsole' in your bootargs.
So long as you have a working Exec/RawMayGetChar and Exec/RawPutChar, it should work.
Also make sure to add shell.resource and shellcommands.resource for this.
That should have done it.
If you set "#define DEBUG 1" in arch/all-native/econsole/econsole.c, do you get any additional serial output?
have added it to the build and added econsole to the command line - and can see the bootloader picks up on the emergency bootconsole tag, but I still only get the insert bootable media display?
Im assuming it exposes a fake filesystem that tricks aros into booting?
The contents of which are: ECON:AROS.boot
Way to handle the scheduling code? The implementations I had been following were causing problems, due to cascading interrupts which I cant handle properly in the asm stubs just now (when they break disable etc.) - since it means detecting the interrupted codes cpu mode and getting the correct sp/lr for it, and that's just too tedious for arm.
To work around this ive added a system idle task which does nothing - and when the scheduling code has no task to run switches this in and lets it run, thereby allowing the interrupts etc to resume until something does need to happen.
Also, by adding accounting code to cpu_Switch() and cpu_Dispatch(), it should allow the system to log idle time correctly (as well as running tasks).
have thought of also adding an additional task that never runs, solely to record time spent in IRQ handlers, but I digress..
was under the impression that kernel.resource should *never* be used outside of exec.library. This is a wrong impression.
Michal started designing it because portable nature of AROS does not fit well into exec's API with all its assumptions. So, he started the new, hardware-agnostic kernel API from scratch. Yes, exec sits on top of it in places. But kernel always meant to be open thing. Otherwise it would not exist.
it wasn't meant to be just used willy nilly by user code - but by lower system components (e.g. exec) so that they could be implemented in a more generic fashion, and the kernel resource itself hide the systems quirks.
Adding new things there perfectly keeps up with our decision to minimize AROS-specific intervention into APIs which can clash with MorphOS or Amiga OS4 extensions. We want at least source-level compatibility there. Binary compatibility on PPC would be extremely cool, but at the other hand we have no maintainer for this, as well as their ABIs splintering.
It depends on what exactly is being implemented - there's no reason we should have everything crammed into kernel.resource if it doesn't need to be (i.e. if its better suited as a separate component/subsystem in its own right)
The _LE versions are for when you have endian swapping taking place. If the graphics are the same endian as the CPU, no swapping should occur. I ran into a similar terminology problem in SDL with a friend insisting that his Radeon 7000 on his PC was big-endian. It is not, it just uses the same endianness for the graphics card and the CPU so no swapping was necessary. They were both little-endian.
The _LE versions are because the PixFmts refer to the bitmap data being in big endian format in memory, for which the normal version would need to do endianness conversion before applying the shifts/masks. on this platform it is in _LE in memory also so we don't need the conversion hence using the _LE version of the call). would use _LE (if it's really little endian 16 bit mode).
What is the bare minimum needed to implement a framebuffer based gfx driver, with our software handling the rest?
Have tried with just a gfx class that only expose new/dispose/newbitmap - and having an onscreenbitmap used only for the framebuffer itself (with all other bitmaps being chunkybm, and the framebuffer's superclass also being chunkybm), but that alone isn't enough it seems?
You can use workbench/hidds/sm502/ as your example - it is as simple as I could make it.
So, AROS creates the framebuffer bitmap (verified this) -> so surely it should be capable of then rendeing into it? I don't actually create the framebuffer "bitmap object" myself - only as a result of being asked to. The code I currently have on SVN seems to create the framebuffers bitmap object fine, but then crashes in intuitions DisplayDriver callback. In particular it crashes performing the getattr on the system default pointer. don't expose MEMF_CHIP in an allocatable form so AllocSpriteData was failing (and other code later doesn't check if the values are valid == illegal memory accesses)
So far have -:
vc_init: queries the gpus memory, and sets up a fake memory handler for it, then adds the bootmode driver and returns saying all is well
vc_gfxhidd:New: sets up some fake syncmodes to test with and creates the real gfx object.
vc_gfxhidd:NewBitmap: checks if its a framebuffer and uses the onbitmap class or uses the chunkybm class otherwise
vc_onbitmap:New; creates a chunkybm object and then pushes the real framebuffer address into it as the buffer,
vc4 had v8adds, v8subs, v8muld, v8min and v8max which operated on four 8bit uint values packed into a 32bit register. Multiplication was in the range 0.0 to 1.0 and addition/subtraction saturated. There were also a range unpacking/packing modes that allowed you to pack and unpack 8bit values into 32bit registers.
RasPi has to speak to the "operating system" which runs on the GPU itself and request/free memory - it cant directly manage it itself, and so the managed functions were used to wrap these calls.
The Arm and GPU share memory space. The framebuffer is shared. The Arm can write a pixel and it will appear on the screen (through GPU hardware) without flushing/copying being required.
The GPU can composite multiple FB's in real time - so you have a number of surfaces defined which are rotated etc and composited in real time to the output. Copying can map from the address space of the Arm to the flat space of the GPU which takes some code, but I don't think whole buffers are copied.
The DMA hardware can also access the whole memory space and can perform 2D fills and blits (no blending). This is documented in the peripheral spec posted. The DMA is just an Arm accessible peripheral and can be set up with low latency (e.g. microseconds).
must use a 0xc0000000-based bus address to access SDRAM, yet non-DMA access should go via a 0x0-based bus address.
For 2D dma, set TDMODE, and the spec says "interpret the TXFR_LEN register as YLENGTH number of transfers each of XLENGTH, and add the strides to the address after each transfer." so set STRIDE to pitch of the image, the width is XLENGTH and height is YLENGTH. You would fill by not setting the SRC_INC and point source to your fill data.
The DMA cannot see the ARM's L1 cache, so you would map the framebuffer with ioremap_nocache. Depending on where the source data comes from, it may need an L1 cache flush. The DMA can see the L2 cache. Use 0xC0000000 bus addresses when L2 is disabled and 0x40000000 bus addresses when L2 is enabled. (actually just call virt_to_bus and you'll get the right address out).
openGLES/openVG has high latency. Writing to framebuffer then reading it back is very inefficient (e.g. milliseconds). If you can drive it a unidirectional way, just streaming commands at then that is efficient. openVG is not implemented on top of openGLES - it uses the same hardware but as a first class interface
To improve the Gfx driver, we will need a DMA resource implemented so can use to perform DMA operations. The Gfx driver will need this to perform blits.
Actually MEMF_CHIP has to present, for historical reasons.
This has been never fully agreed upon, but in ports i wrote i exposed the whole memory as MEMF_CHIP. The idea behind this is that CHIP is originally the memory where graphics and sound data can be put. On non-Amiga platforms there are no restrictions on this, so the whole memory is CHIP.
Yes, many old software can misbehave with CHIP memory size larger than 2MB. But this actually applies only to m68k AROS which is going to run m68k binaries. In other cases it's quite logical to fix the program when porting.
As to original question: yes, it's enough to have a framebuffer bitmap (one with aoHidd_BitMap_FrameBuffer set to TRUE) and PutPixel routine. It framebuffer can be served by chunky bitmap class, then you can simply create chunky bitmap with your own buffer (see how VESA driver does this). Chunky PutPixel is already there.
struggling to determine what is the correct pixfmt to use for the 24/16/15 bit gfx modes on the RasPi. AFAIK it uses RGB565, for 16bit but im unsure what shifts etc should go with it? suffice to say Im getting the wrong colors so far lol.
<pre>
redmask: 0x0000F800
greenmask: 0x000007E0
bluemask: 0x0000001F
alphamask: 0
redshift: 16
greenshift: 21
blueshift: 27
alphashift: 0
</pre>
It should likely be vHidd_StdPixFmt_RGB16_LE
This stuff is a bit confusing. The "names" of the stdpixfmts are based on the layout in memory,
ignoring endianess. So for example:
ARGB32: will be 0xAA 0xRR 0xGG 0xBB in memory on both big endian and little endian machines.
The shifts and masks OTOH are based on pixel access (ULONG in this case), so differ depending
on whether you run on big endian machine or little endian machine (that's why there's stdpixfmt_le.h and
stdpixfmt_be.h in rom/hidds/graphics/).
With the 16 bit pixel format it's even more confusing, as for example it's impossible on little endian machine
to describe RGB16 with shifts/masks alone. That's why there's vHidd_PixFmt_SwapPixelBytes_Flag.
(RGB16 == RRRRRGGG GGGBBBBB in memory, and for pixel (WORD) access on little endian machine it needs to
be accessed as GGGBBBBBRRRRRGGGG).
The shifts btw indicate how much to shift the component to the left (!) so that it is moved to the highest bit (31).
The aHidd_PixFmt_StdPixFmt you specify will be ignored most of the time, because when the pixelfmt is registered,
the gfx hidd checks if there's an identical pixfmt (shifts/masks/etc., but ignoring pixfmt->stdpixfmt) already in the system,
and if so, it uses the already existing one and does not create a new one.
In theory it would be better if gfx drivers could simply/only specify a StdPixFmt without all the shifts/masks stuff when the
gfx driver uses pixfmt which matches one of the stdpixfmts exactly. Another possibility would be for gfx drivers to use
HIDD_Gfx_GetPIxFmt(stdpixfmt_gfx_driver_wants_to_use) and then peek shifts/masks from it and fill out a pixfmt
tag list based on that.
15bit very blue/green: Try to pass same shifts/masks/etc. as in 16 bit pixfmt (maybe you think it's using 15 bit R5G5B5
(or swapped) but it's actually still using 16 bit R5G6B5 (or swapped).
aHidd_PixFmt_StdPixFmt you pass is mostly ignored. It's the shift/masks/etc. that count.
But I would still pass the correct one (_LE) == whatever rom/hidds/graphics/stdpixfmts_??.h uses
in the entry where you have looked up shifts/masks/etc.
Use the shifts/masks/etc. from the entry in stdpixfmt_le.h (if you are running on little endian machine) or stdpixfmt_be.h (if you
are running on little endian machine) that matches the pixfmt that its meant to be.
0xAA,0xRR,0xGG,0xBB on little endian (->entry in stdpixfmt_le.h which says vHidd_StdPixFmt_ARGB32)
0xBB,0xGG,0xRR,0xAA on little endian (->entry in stdpixfmt_le.h which says vHidd_StdPixFmt_BGRA32)
0xAA,0xRR,0xGG,0xBB on big endian (->entry in stdpixfmt_be.h which says vHidd_StdPixFmt_ARGB32)
0xBB,0xGG,0xRR,0xAA on big endian (->entry in stdpixfmt_be.h which says vHidd_StdPixFmt_BGRA32)
it feels like AROS trashes the alpha component, otherwise it should be 8A8R8G8B.
read on the subject suggest its in 1x5r5g5b (x is ignored) to keep 16bit alignment .
Suggests to me that wrong shift/mask are being applied - however going by the 16bit versions it all looks correct to me so I am really confused as to what is happening.
The output image looks to have too much green/blue, and very weak red.
Kickstart
The idea is to minimize amount of archirecture-specific modules to make the user's life easier. So, the kickstart was split into 'base' (which does not contain anything machine-specific) and 'BSP' (Board Support Package) which contains all hardware-specific stuff. This way, for example, distribution makers can save up space on CD and make CDs with multiple platform support. Different configuration would load the same base with different BSP's.
Next there was some part which is entirely missing on hosted. These are filesystems. Hosted ports do not need them to boot up, so on hosted they are left out. At the other hand, they are also architecture-agnostic. So i put them into 'FS' package (standing for 'filesystem').
USB
Poseidon is one more big part. I made it into separate package in order to allow users to omit it if they don't need it (for example, to run on retro PCs without USB). Personally i have one. Again, Poseidon is hardware-agnostic (well, there are USB drivers but HCIs are pretty standard).
AFAIK its HCI 1.0 compliant but not familiar enough with poseidons drivers, nor USB, to just hack away at the existing code. Perhaps once i'm more familiar with the workings I can merge in the changes needed to get it operating but for now I will focus on getting it running. Also our drivers have known issues so perhaps a fresh set of eyes might shed some light on what is going wrong.
Another interesting question is whether Poseidon can operate on device side. Is it flexible enough? How similar is being a USB host and USB device? think it will need a bit of work on Poseidon's side. Until then I will force the driver into Host/Master mode in the init code, but leave open device etc to configure the chipset for either's use - and look at trying to add support for working in Device/Slave mode & switching modes once it's up and running.
Actually USBROMStartup is some kind of kludge. Can there be any alternative? Could device drivers be self-installing, like our HIDDs? This would get rid of need to list them in USBRomStartup.
* Model A and B limited to 150 mA per port.
* Model B+ and Pi 2 introduced configurable 600 mA to 1.2 A support over all ports - anything above that requires a powered USB hub.
Implementing the hardware driver that Poseidon uses to interact with the USB components.
Have code in place to (try) and initialise the USB chipset, and configure host/device mode operation (though AFAICT Poseidon doesn't support device mode). Started to get the "virtual" root hub written for the single USB port so that Poseidon should at least list it correctly in the GUI - and try to interact with it to find peripherals.
The BCM2835 uses a soft IP block from Synopsys’ DesignWare library (DWC), specifically the block is called dwc_usb_2_0_hs_otg_subsystem-ahb_se (“USB 2.0 Hi-Speed OTG Controller Subsystem w/AHB Interface SE”).
There is no public documentation for this, and pretty much zero chance of anyone getting hold of it even with NDA. However, there's a Linux driver written by Synopsys ([https://github.com/raspberrypi/linux dwc_usb]). Specifically directories [https://github.com/raspberrypi/linux/tree/rpi-patches/drivers/usb/host dwc_common_port] and [https://github.com/raspberrypi/linux/tree/rpi-patches/drivers/usb/host dwc_otg].
The Synopsys code is actually under a fairly permissive licence – it's not GPL, it's similar to BSD (’don't sue us if it breaks’ is pretty much the only clause). So this should not be a barrier to porting the code.
The code is really well written, with a nice partition between the work done by the driver (dwc_otg, which is fairly involved, given the host does more work than a conventional EHCI driver), and the interface to Linux (dwc_common_port).
Probably only need provision of relevant changes to dwc_common_port. Other things to consider....
* Provision of necessary headers to get it to compile
* Provision of necessary functions (main issues are wait queues, threads, work queues, tasklets, timers, spinlocks and mutexes (multithreading) )
* Interfacing between USB stack and the driver. dwc_otg/dwc_otg_hcd_linux.c looks like the place to start.
the Linux bits of the headers are only required for the dwc_common_port library. dwc_common_port includes a variety of crypto functions which are not used – it appears to also be used for ultrawideband (UWB) and wireless USB (WUSB) drivers where crypto will be an issue, but it isn't going to be for plain wired USB.
Every USB driver acts as an USB hub as well in order to let Poseidon control the state of USB ports. The code there was reading status of the only USB port in Raspberry's CPU but when changing the status it erroneously deleted some of the status bits, including the port enable one. It was so because those bits in the status register are of a type Read/WriteToClear. It means, if one does not want to change their value from 1 back to 0, one has to actually write the 0 value. Very practical thing e.g. in interrupt handlers, where one reads the interrupt status register to learn what was the interrupt reason, and writes it back to the same register in order to clear the interrupts.
After fixing that code it turned out that the communication was still unsuccessful. Apparently the USB device was not understanding the host for some reason. That should not happen since the request sent was one of the standard ones implemented by virtually anything with an USB connector, assumed that Poseidon clears the data caches before forwarding the work to the USB drivers but that's the responsibility of the driver itself.
The USB device responded and acknowledged the transmission! But why were all the request sent after address change failing with timeout? They should not. Once again, address set is supported just by anything. Tried to contact the device at address 0 once again and there it was, still responding properly. The enlightenment came. The bus address for DMA transmissions was, as it is in many bare metal USB implementations, just the pure memory address of the buffer as seen by the ARM cpu. Have "prefixed" it with the real location of uncached RAM and booted AROS once again.
Trident saw this:
Product : Hub: Vdr=0424/PID=9514
Manufacturer: Standard Microsystems Corp.
SerialNumber: n/a
/Users/michal/git/AROS/rom/USB/poseidon/./poseidon.library.c:psd_20_psdEnumerateDevice/3092: USBVersion: 0200
Class : 9
SubClass : 0
DevProto : 2
VendorID : 1060
ProductID : 38164
DevVers : 0200
and this:
Product : Vendor: Vdr=0424/PID=EC00
Manufacturer: Standard Microsystems Corp.
SerialNumber: n/a
/Users/michal/git/AROS/rom/USB/poseidon/./poseidon.library.c:psd_20_psdEnumerateDevice/3092: USBVersion: 0200
Class : 255
SubClass : 0
DevProto : 1
VendorID : 1060
ProductID : 60416
DevVers : 0200
and even this:
Product : Hub: Vdr=0424/PID=9514
Manufacturer: Standard Microsystems Corp.
SerialNumber: n/a
/Users/michal/git/AROS/rom/USB/poseidon/./poseidon.library.c:psd_20_psdEnumerateDevice/3092: USBVersion: 0200
Class : 9
SubClass : 0
DevProto : 2
VendorID : 1060
ProductID : 38164
DevVers : 0200
What are these things? The first one is USB hub built in the Raspberry. Thanks to this one the Pi machines (with exception of Pi0 and computing modules) have more than just one single USB port. The second one is the network chip in raspberry, the third one is my USB SD card reader which have just connected to see what happens. AROS tried, of course, to boot from it ;)
So, the first step towards working USB is done. The control transfers are working as you can see above. Next step is to implement bulk and interrupt transfers, having the basics in place. Finally some error handling will be added and USB for Pi will be as complete as the PC version.
[http://www.raspyfi.com/raspberry-pi-usb-audio-fix/ Issue with USB Audio]
Audio
The Pi 4B is the only Pi that can output HD Audio as an HD Audio passthrough bitstream, and it does it over HDMI. It's possible to use the two HDMI output for separate HDMI video and HDMI audio outputs to allow UHD HDR video and HD Audio with non-UHD HDR compatible AVRs.
The Pi3B+ and earlier will decode to PCM 5.1/7.1 and output over HDMI. HDMI is the only interconnect that has a standard for carrying Dolby True HD, DTS HD MA etc. as a bitstream - you can't carry it as a bitstream on any other interface.
Pi3 and Pi4 audio jack output derived from 12bit pulse width modulation is relatively poor. For better, choose USB Audio or I2C versions.
[https://github.com/raspberrypi/linux/tree/rpi-patches/sound/arm audio] and its [https://github.com/raspberrypi/firmware/issues/2 very high speed message passing interface type of thing VCHI]
The Model B+ added an additional voltage regulator for the audio output and an additional output driver to drive low-resistance loads like headphones. However it is still using pulse-width modulation (PWM), which has a major impact on sound quality
the old Raspberry Pi used a linear voltage regulator to provide the 3.3V to many of the components on the board while the new one uses a switching regulator. Both can perform reasonably well. However switch mode power supplies often show higher noise figures
Analogue audio
Audio over HDMI rev 1.3 & 1.4
Ethernet
10/100 BaseT Ethernet RJ45 socket
GPIO
GPIO shouldn't be too bad but bear in mind it is already accessed in places so they would need to allocate pins etc through it (e.g. sdcard to flicker the activity light, serial debug to output data on the GPIO pins)
Probably a resource rather than a device...
Started an i2c driver that will need to allocate GPIO pins. Feel free to work on it if you are interested ;p
GPU graphics with 2D and 3D acceleration
Sadly none yet for 32bit but for 64bit...
Miscellanous
hdmi issues
Setting the hdmi_force_hotplug=1 makes sure the Pi believes the monitor/TV is really there.
You might also need to set config_hdmi_boost=4 or even higher (up to 9) if your display needs a stronger signal.
If the display is a computer monitor or newer tv, use hdmi_group=1 (auto HDMI use) and if it is an older TV, try hdmi_group=2 (for DMT formats, i.e. for PC monitors) then you HAVE to "set hdmi_drive = 2 to enable HDMI output as this forces HDMI mode rather than DVI mode
Do not set hdmi_safe=1 as that overrides many of the previous options.
Using a shorter or better quality HDMI cable might help. Make sure your Pi's power supply delivers 1 A and not 500 mA.
If you see a problem with the red colour - either absent, or interference - then try a boost
composite video
changing the RCA cable, then the composite port worked out of the box
Boot it as you are doing, without HDMI. If you now plug in the HDMI, do you get the image? In other words, does the Pi think HDMI is connected even when it isn't?
Rename all the files in the first partion of the card except bootcode.bin, start.elf and fixup.dat What's the result?
Put back config.txt What's the result?
for PAL mode sdtv_mode=2
dmi_ignore_hotplug Pretends HDMI hotplug signal is not asserted so it appears a HDMI display is not attached
hdmi_ignore_hotplug=1 Use composite mode even if HDMI monitor is detected
<pre>
# NOOBS Auto-generated Settings:
#hdmi_force_hotplug=1
#config_hdmi_boost=4
#overscan_left=24
#overscan_right=24
#overscan_top=16
#overscan_bottom=16
#disable_overscan=0
start_x=1
gpu_mem=128
</pre>
tvservice -c "PAL 4:3"
<pre>
/opt/vc/bin/tvservice -s or tvservice -s
state: HPD high|HDMI mode|HDCP off|composite off (0x12001a), 1920x1080 @ 60 Hz, progressive
/opt/vc/bin/tvservice -m CEA
Group CEA has 1 modes:
(native) mode 16: 1920x1080 @ 60 Hz, progressive
/opt/vc/bin/tvservice -m DMT
Group DMT has 0 modes:
</pre>
sudo amixer cset numid=3 1
forces the audio to the headphone jack, even with the HDMI video output plugged in
config.txt
the hdmi_ignore_edid_audio=1 option sems relevant as it should tell ALSA that the only available audio is analog, no matter what the display says
There are several different ways that these 4 pole (ring) composite analog cables can be wired up, so some work great in some applications and can be a waste of time in others.
What is needed for the Raspberry Pi B+ and above, which like many camcorders needs the ring contact next to the base contact to be the ground.
The wiring for the 4 pole are:
TIP (LEFT AUDIO CHANNEL)
RING 1 (RIGHT AUDIO CHANNEL)
RING 2 (GROUND/EARTH)
RING 3 BASE/SLEEVE (VIDEO) YELLOW
Most Apple based Players and the Microsoft Zune (TM) are wired this way.
Most analogue camcorders are wired this way as well, where the ground in on Ring 2 will work with the Pi although you may need to swap your Video plug with the Right Audio plug.
Nearly all other MP3 players are not wired this way, the ground is on another ring ie the wrong one.
External devices
* Camera Module Omnivision ov5647 Sunny 5MP (NoIR version) V1.3 - NoIR at 850 nm, peak at 880 nm and trails off at 940 nm wavelengths
* Camera V2 Sony IMX219 V2.1 8mpixel 8MP 8megapixel - 3280 x 2464 pixels - video at 1080p30, 720p60 and 640x480p90 - wider field of view, 62 vs 54 degrees horizontally -
* Branded WIFI usb BCM43143 dongle
N.B. dreaded error after changing cameras (stupidly without turning off the power first) and lasted through several power cycles. It can be a bad 15-pin FFC ribbon cable, when swapped, camera(s) and the Pi itself are working OK. It can be an instance of a cold solder joint on the CSI connector on the pi board. the camera can be detected (that's done via I2C) but may still not be able to receive image data (done via CSI-2) if something is broken. CSI-2 is uni-directional. Control is generally done via I2C.
The CSI-2 receiver always writes to memory, not direct to the ISP. That's the way the Broadcom architecture works as it allows multipass processing easily. GPU memory is accessible from the ARM. Processing using the QPU graphics processors may be possible. currently the only supported sensor is OV5647 and IMX219. The linux drivers are all in the firmware blob, else you'd be looking at at least a man-month of work in a fully fledged imaging lab to do a decent tuning of the camera modules' ISP parameters.
Static electricity maybe an issue for the camera module and slightly less for the pi board.
== References ==
===Good sites to visit===
*[https://github.com/raspberrypi/firmware/tree/master/ Raspberry Pi Firmware build]
*[https://www.raspberrypi.com/documentation/computers/software-sources.html Documentation]
*[https://rpilocator.com/ RPiLocator]
Linux only
*[https://github.com/raspberrypi/linux Raspberry Pi Linux Build]
*[https://dietpi.com/ DietPi]
*[http://www.tinycorelinux.net/ports.html piCore]
*[https://wiki.alpinelinux.org/wiki/Raspberry_Pi Alpine Linux]
*[https://github.com/armbian/build Armbian]
*[ FydeOS]
*[ TwisterOS based on ChromiumOS]
*[https://note.com/jamesmondo/n/nc76e31402be8?hl=en BSD]
*[https://www.raspberrypi.com/software/operating-systems/ PiOS Lite] and then [https://hstwb.firstrealize.com/ HST]
*[ PiMiga for pi4 and pi5]
*[ amibian for pi2 and pi3]
*[ retropie pi1 and 2]
Other alternative lighter smaller than Pi OS
*[https://aros.sourceforge.io/nightly1.html Aros 64bit ARMV8 single core]
*[https://www.riscosopen.org/wiki/documentation/show/Welcome%20to%20RISC%20OS%20Pi RiscOS on Pi3 and Pi4]
*[https://github.com/michalsc/Emu68 ARM based realtime JIT 68k for amiga computers]
*[https://github.com/JJDSNT/bellatrix/releases/ Alternative use of Emu68 on Pi3b]
*[https://github.com/stevereaver/uaos uaOS with Emu68k]
*[https://github.com/aros-development-team/AROS/commit/f80a268607dfae81b2db94755ab4e4d31ccb72d6 m68kemu library reference]
*[ HaikuOS]
*[https://github.com/raspberrypi/noobs NOOBS] os loader with successor [https://github.com/procount/pinn PINN]
*[https://github.com/maxnet/berryboot berryboot]
*[https://github.com/brianwiddas/pi-baremetal Bare Metal Access on Pi 32bit]
Testing procedure is put sd card in, connect board to board if necessary, plug in hdmi and then power nothing else is done especially CSI DSI etc
[https://www.raspberrypi.com/documentation/computers/compute-module.html CM5] has the same 55mm x 40mm 2x100pin connectors form factor as the CM4 but [https://www.epdtonthenet.net/article/214508/Key-Considerations-When-Migrating-from-Raspberry-Pi-CM4-to-CM5.aspx some pins and other small things] have changed. Will need the [https://raspipcb.com/tech-blog/raspberry-pi-cm4-vs-cm5-difference-in-booting-from-sd-card/ right IO board to suit]
*Green [ Raspberry Pi Compute Module 5 IO Board REV2 [https://pip.raspberrypi.com/categories/1097-raspberry-pi-compute-module-5-io-board SC1967]] - untested
*Green [ RPi Compute Module 5 IO board REV1 [https://pip.raspberrypi.com/categories/1097-raspberry-pi-compute-module-5-io-board SC1751]] - untested
*Black SupTronics Geekbord X1500 CM5 IO Carrier Board - untested
*Black DeskPi Super6C Cluster Mini-ITX Board - untested
*[https://sipeed.com/nanocluster Sipeed NanoCluster] - untested up to 7 CM5
*Green BentoIO CMX0 - untested
*Box EDATec ED-CLAWBOX - untested
*Home Assistant Yellow - Kit with PoE with Raspberry Pi Compute Module 5 - untested
*Blue [https://www.waveshare.com/wiki/CM5_PoE_BASE_A Waveshare CM5-PoE-BASE-A] - untested
*Box Waveshare [ CM5-POE-BOX-A] - untested
*Blue [https://www.waveshare.com/wiki/CM5-IO-BASE-B Waveshare CM5-IO-BASE-B] - untested
*Blue [https://www.waveshare.com/wiki/CM5-IO-BASE-A Waveshare CM5-IO-BASE-A] - untested
*Blue Waveshare [https://www.waveshare.com/wiki/CM5-NANO-B CM5-NANO-B] - untested
*[https://carboncomputers.us/products/pi-flux piFlux]
*[https://carboncomputers.us/products/ Zitaotech Hackberry] CM5 lite only -
*Portable [https://www.waveshare.com/pocketterm35.htm Waveshare PocketTerm35] with Pi4B or Pi5 - untested
*Box [https://www.clockworkpi.com/uconsole ClockworkPi uConsole][https://www.youtube.com/watch?v=EtI_bAahbR8 CM4 into an adapter or CM3 into so-dimm - Cyberdeck] - untested
*Green RPi [https://datasheets.raspberrypi.com/cm4io/CM4IO-KiCAD.zip Compute Module 4] [https://datasheets.raspberrypi.com/cm4io/cm4io-datasheet.pdf IO board] V1.4 [https://datasheets.raspberrypi.com/cm4io/CM4IOUSB3-KiCAD.zip USB3] [https://datasheets.raspberrypi.com/cm4io/cm4iousb3-appnote.pdf CM4ISO] [https://datasheets.raspberrypi.com/cm4/cm4-datasheet.pdf Dual100pin] (2020) aka Development Platform Board - untested
*Purple Pi Hut Cytron CM4 Maker Board - untested
*Black DeskPi Super6C Cluster Mini-ITX Board - untested
*[ KubeSail PiBox mini 2]
*Home Assistant Yellow with Raspberry Pi Compute Module 4 - untested
*[ Turing Pi V2] - untested CM4 with 260-pin SO-DIMM socket adapters and/or nvidia jetson nanos - untested
*Blue [https://www.waveshare.com/wiki/CM4-IO-BASE-C Waveshare CM4-IO-BASE-C] - untested but binary blobs Rev01 Rev02
*Blue [https://www.waveshare.com/wiki/CM4-IO-BASE-B Waveshare CM4-IO-BASE-B] - untested but binary blobs
*Blue [https://www.waveshare.com/wiki/CM4-IO-BASE-A Waveshare CM4-IO-BASE-A] - untested but binary blobs
*Blue [https://www.waveshare.com/wiki/CM4-NANO-B Waveshare CM4-NANO] - untested but usb and audio turned off or rerouted
*Black [ Seeed Studio with BigTreeTech BTT pad 7] - bin blobs?
CM3 has a 200 pin sodimm ddr2 connector form factor but not electrically SC0028, SC0029
*Blue [https://wiki.geekworm.com/CM_IO_Board Geekworm RPi Compute Module IO Board] [https://github.com/geekworm-com/cm-io-board CSI DSI] with CM3 in ddr2 slot underside - '''works''' if SW1 on but CM3+ '''does not'''
*Green [https://cdn-shop.adafruit.com/product-files/3442/CMIO_schematic.pdf RPi V3 IO board CM3IO] and CM3 Lite - untested
*Green [https://turingpi.com/ turingpi v1 cluster] - untested up to 7 cm3 7xlan9514 12V discontinued, 3 x Pi4 homelab maybe better
*Blue [https://www.waveshare.com/wiki/Compute_Module_PoE_Board Waveshare Compute Module PoE Board] and CM3 lite (if not lite, write files to internal eMMC fat32) '''AVOID''' bin blobs
*Blue [https://www.waveshare.com/compute-module-io-board-plus.htm Waveshare Compute Module IO Board Plus] [https://www.waveshare.com/wiki/Compute_Module_IO_Board_Plus wiki] [https://forums.raspberrypi.com/viewtopic.php?t=235695 pin settings] with CM3+ Lite - '''AVOID''' binary blob
*[ Pi02w on Geekworm SupTronics X305 Raspberry Pi Zero IO Baseboard] - untested
*[ Spotpear Pi Zero 2w to Pi3b format-ish] - untested
*[ pi-top v4] box has 128x64 oled display, micro hdmi, 19Whr battery with pi4 and 15V PD 36W min needed
*[ pi-top v3] three green pieces, heatsink covers most of the base tray, pi-top hub mk1 lhs and Pi1B Pi2b Pi3b rhs secured from below, black rounded strip with pi-top above keyboard, 13.3" HD 1366 x 768 display, small touchpad,
*[ pi-top Model 2.0] pi-top on bottom bezel of 14-inch green laptop, large trackpad, keyboard slide down to reveal main system hub on slide rails moved to the right, Raspberry Pi3b screws down, hub slides in, 18V 2.5A 45W charger brick, battery 11.1V 3500mAh 38.85Wh and storage PiTopOS
*[ Pi-Top CEED Raspberry Pi Modular Educational Desktop with RPI3] monitor
*[https://www.indiegogo.com/en/projects/jesselozano/pi-top-a-raspberry-pi-laptop-you-build-yourself Pi-Top v1] wedge laptop with RPi2
<pre>
2008 Trustees collected for Foundation
2009 Pi Foundation charity status gained
2010
2011 First Raspberry prototypes
2012 First boards go on sale at CPC and RS. The Model A and B 700 MHz Arm11 - February 29th BCM 2835
2012 First million sold - more than the 10,000 original planned and anticipated
2013 First Alpha Experimental builds of AROS Native for the 32bit Pi
2013 Pi Trading launched making grants available, providing in house educational resources and Pi Academy for teacher training
2013 Over two million sold
2014 Over three million sold
2014 Pi 1 Model B+ introduced that moved composite video to audio jack and same half gig of memory
2014 Pi Model A+ v1.1 no ethernet and 1 usb - a little smaller -
2015 Over four million first gen pis sold
2015 Pi Zero 1.2 BCM2835 first production revision released with no camera port
2016 Pi0 1.3 released with camera csi connector
2017 Pi Zero W v1.1 1GHz Pi0W, single-core 32bit CPU BCM2835 released with Cypress CYW43438 wireless
2020 Raspberry Pi Pico SC0919 with RP2040 32-bit 2Core ARM Cortex-M0+ up to 133 MHz - 264KB of SRAM and 2MB of on-board QSPI Flash -
2024 Raspberry Pi Pico 2 with RP2350 2Core 32bit Arm Cortex-M33 and 2core open-hardware [https://github.com/wren6991/hazard3 Hazard3 RISC-V]
2015 Pi 2 Model B v1.1 BCM2836 900/600 MHz ARM Cortex-A7 Armv7 quad 32bit, 32bit VideoCore IV GPU - 1Gb RAM - 5V 2A micro usb - SMSC LAN9514 chip -
2015 Over a million pi2s sold
2015 Raspberry Pi 2 Model B version 1.2 Pi2bv1.2, aka Pi2B2 has armv8 BCM2837 underclocked to 900Mhz without wifi/bluetooth module
2016 Pi 3 Model B - Broadcom BCM2837 SOC four 64bit ARMv8 Cortex-A53 1.2GHz 32bit 1080p VideoCore IV GPU - 1Gb DDR2 - bluetooth 4.1, Cypress CYW43438 wireless 802.11n - 4 x USB2.0 ports - 5.1V 2.5A - SMSC LAN9514 chip
2016 PIs total over 10 million worldwide
2017 Compute Module 3 CM3 with BCM2837B0 armv8 Quad 64-bit - small 67.6mm x 31mm board which fits DDR2 SODIMM connector but not electrically compatible which plugs into needed IO board - beware of the I2C protocol issue
1Gb LPDDR2 RAM - Lite or 4Gb Emmc storage
2017 12 million pis sold in total
2018 Pi 3 Model B+ - 4c A53 BCM2837B0 1.4Ghz - 1Gb, wireless 802.11ac, gigabit ethernet (300Mbit/s) and bluetooth 4.2 - power over ethernet - 4 x USB2.0 ports - Microchip LAN7515 chip
2019 Over 15 million sold
2019 Pi 3 Model A+ with BCM2837b0 Cortex-A53 64-bit SoC @ 1.4 GHz with 512Mb LPDDR2, 1 usb2, 1 hdmi, 1 micro usb 5V 2A - no ethernet -
2019 Raspberry Pi Compute Module 3+ CM3+ - Broadcom BCM2837B0 1.2Ghz, Cortex-A53 (ARMv8) 64-bit SoC on DDR2 SODIMM mechanically compatible only factor - IO board required
1Gb DDR2 and 8GB, 16GB, 32GB or a Lite variant without eMMC
2021 Pi zero 2 (w or no W) RP3A0 quad 1GHz Cortex-A53 64bit BCM2710A1 512mB SDRam
2025 edaTEC CM0 ED-CM0NANA with additional dev board with quad 1Ghz A53 with 512Mb Raysan RAM, 2 USB2 and 10/100 ethernet - pico castellated edge
2019 Pi 4 Model B RPI4B - BCM2711B0T quad 64bit A72 1.5GHz, 4K VideoCore VI, AC wifi, Bluetooth 5.0, GbE Broadcom BCM54213PE (PHY ID 0x600d84a2), 2 micro hdmi decode up to 4K, USB-C 5.1V 3A power, 2xVLI VL805 USB 3, 2xUSB 2.0, 2GB 9LDWW D9WHZ or 4GB 9FDWW D9WHV, 8GB 0AA47 D9ZCL ddr4 ram
2020 Silent Pi 4 v1.2 upgrade with more USB-c psu support
2020 PI400 BCM2711C0T 1.8GHz 4Gb DDR4 inside keyboard, 5.1V 5A 27W usb-c psu, 2 micro hdmi, external ide style 40pin gpio, no audio port -
2020 Raspberry Pi Compute Module 4 BCM2711B0T on new 55mm x 40mm 2x100 pin form factor with extra breakout IO board
CM4101000 1Gb RAM Lite SOM
CM4102000 2GB RAM Lite
CM4104000 4GB RAM Lite
CM4004008-4GB-RAM 8GB-EMMC SOM System on Modules
CM4104032 4GB RAM 32GB emmc
CM4108000 8GB RAM Lite
CM4008016 8GB RAM 16Gb eMMc
2021 Raspberry Pi SC0763 Compute Module 4S CM4S with ddr2 sodimm pinouts but not electrically the same with suitable IO board extra cost -
CM4S01000 1GB RAM Lite
CM4S01008 1GB RAM 8GB eMMC Flash
CM4S02000 2GB RAM Lite
CM4S04000 4GB RAM Lite
CM4S04016 4GB RAM 16Gb KLMAG1JETD-B041
CM4S08000 8GB RAM Lite
2021 Pi 4 v1.4 BCM2711B1 upgraded power regulator, to deal with 8gig of ram being more power hungry -
2021-48 Raspberry Pi 4 model B v1.5 2GB
2023 Pi 5 v1.0 BCM2712 Quad A76 @2.4Ghz - VideoCore VII - no audio socket - dual 4k from mini hdmi - fan connector - 5.1V 5A psu
2024 Pi 5 2GB DDR4 version uses BCM2712D0
2024 Pi-500 with 8Gb LPDDR5 and membrane keyboard
2024 Pi 5 v1.1
2024 Raspberry Pi Compute Module 5 CM5 BCM2712 55mm x 40mm form factor with additional IO board
CM5004000 04GB RAM 0GB eMMC Lite
CM5008000 08GB RAM 0GB eMMC Lite
CM5016000 16GB RAM 0GB eMMC Lite
2025 Pi-500+ with 256GB NVMe storage, 16GB LPDDR4 RAM, and Gateron KS-33 Low Profile Blue mechanical keyboard switches
2025 Pi5 1GB DDR4 announced
2022 PiOS linux goes 64bit
2024 Pi Trading IPO stockmarket stock exchange listing
2026 April and May Aros 64bit fixed, added AHI audio, VC4 gfx started, usb functions added to rom
2026 June and July Aros 64bit usb2otg started, dma.resource, sdio.resource, bwfm.device wifi added
2026 Late July daily 64bit Pi3 LE little endian builds start
2026 August Pi 4, 400, 5 and 500 DTBs added, expanding existing support and wifi for Pi4 and Pi5
2026 August Pi5 HAT+ nvme and HDMI, AHI RPiI2S added, Pi4 HVS5 video scaler started,
2026
2027
2028 Pi 6
</pre>
The vcgencmd can be used to inspect and dump the current system configuration.
vcgencmd runs on top of VCHIQ as an RPC. The mailbox interface is an alternate but much simpler RPC.
VCHIQ is a bridge (queue) between the CPU and the GPU so they can communicate with the firmware.
Loads of [https://github.com/6by9/rpi3-gpiovirtbuf/blob/master/rpi3-gpiovirtbuf.c mailbox] which uses the GPIO control calls. [https://github.com/raspberrypi/firmware/wiki/Mailboxes may also be of interest]
A fair number of vcgencmd examples (search for vc_vchi_gencmd_init). [https://www.raspberrypi.org/forums/viewtopic.php?t=229203#p1406112 sends the relevant vcgencmd commands] to update the scaling kernel, but the [https://github.com/raspberrypi/userland/blob/master/host_applications/linux/apps/gencmd/gencmd.c command] is just a text string. Parsing and execution of the instructions is performed by the VideoCore firmware.
The Raspberry Pi runs two separate operating systems: Linux/Aros on the ARM, and a threedx RTOS called vcos running on the Videocore 4 VPU: vcos is commonly called "the firmware". Vcos is tasked with performing certain system services, for example running the display and audio outputs. The VCHI driver provides an interface to allow drivers to talk to vcos.
Doubtful, on any [https://www.web3d.org/ Web3d] [https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API WebGL] or [https://github.com/immersive-web/webxr WebXR] [https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API Device API] [https://developer.mozilla.org/en-US/docs/Web/API/XRInputSource XRInputSource] support. Hopefully, never/limited support features like location, peer-to-peer, invasive web apps, unwarranted storage, payments, proprietary video streaming etc
*spreadsheet [https://git.sheetjs.com/sheetjs/sheetjs sheetjs] [https://github.com/mleibman/SlickGrid SlickGrid] [https://github.com/6pac/SlickGrid SlickGrid] [https://github.com/jspreadsheet/ce jspreadsheet ce] [https://github.com/dream-num/Luckysheet Luckysheet] [https://github.com/ruilisi/fortune-sheet fortune-sheet] [https://github.com/dream-num/univer/ univer] probably without xlsx support
*presentations [https://github.com/impress/impress.js/ impress.js simplified] [https://github.com/bwlewis/slides slides] [https://zenomt.github.io/mdslides/ github markdown slides] [https://github.com/Patternslib/slides Patternslib slides markdown] probably without pptx support
*weather [https://github.com/kaushalsahu07/weather weather], [https://github.com/Himanshu3412/Weather-Forecast Weather Forecast],
==Future==
[https://github.com/ARMSX2/ARMSX2 Arm pi of pcsx2]
{{BookCat}}
9d4z63o35ohwm99qv9kqenp1vf2rlug
4675837
4675817
2026-10-13T13:26:19Z
Jeff1138
301139
4675837
wikitext
text/x-wiki
{{ArosNav}}
[[#Native]]
[[#Hosted]]
[[#Build]]
[[#Hardware]]
[[#References]]
[[#Future]]
==Introduction==
[[File:Scalos00.png|thumb|Scalos on Aros Pi3b]]
Aros aims to cover Pi 3 to 5 512Mb+ RAM
Options to boot from using a good power source to prevent the yellow lightning symbol.
*With Pi3b+ the max you can get is 5.1V 2.5A with micro usb.
*With Pi4 5.1V 3A with usb-c
*With Pi5 5.1V 5A, the amps went ever upwards, even to 5.1V 9A with usb-c
* Pi500+ keyboard wedge - working
* Pi500 wedge with up to date bootloader via PiOS - working
* Pi 5 - Quad A76 64bit ARMv8 and RP1 "southbridge" with VideoCore 7 D0 (rev1.1) - untested
* Pi 5 - Quad A76 64bit ARMv8 and RP1 "southbridge" with VideoCore 7 Pre-D0 C1 (Rev1.0) - untested
* Pi400 RPI-400 keyboard wedge - resolution changing and audio from micro hdmi0 (near 40pin) and micro hdmi1 (near usb-c psu) - Fn F10 0x5e power on and off works or held down for over 7 seconds auto shutdown - keyboard ok - wifi and lan ethernet testing -
* Pi 4 - Quad A72 64bit ARMv8 with VideoCore 6
* Pi 3 - Quad A53 [https://www.raspberrypi.com/documentation/computers/processors.html 64 bit] ARMv8 with VideoCore 4 with '''fan''' to prevent overheating cpu 82C+ throttling
* Pi02W - Quad A53 64bit - boots but [https://forums.raspberrypi.com/viewtopic.php?p=2387984#p2387984 usb not working but did in the past],
* Pi 2 - Quad 32bit ARMv6 with VideoCore 4 - mostly not 64bit compatible
* Pi Model B+ 32bit ARMv6 with VideoCore 4 - not 64bit compatible
* Pi Model A and B 32bit ARMv6 with VideoCore 4 - not 64bit compatible
===Native===
* 2013-03 Kalamatee starts work
* 2015-04 Work continues with mschulz on the kernel and Kalamatee (NicJA) on gpio and usb
* 2018 [https://www.patreon.com/posts/i-owe-you-some-20956961 mschulz resume adding BE big endian support], [https://www.patreon.com/michal_schulz/posts Big endian on Pi]
* 2026 [https://github.com/aros-development-team/AROS/commits?author=bsek latest commits for pi 3b, 4 and 5 64bit]
* 2026 [https://github.com/aros-development-team/AROS/commits?author=metaneutrons latest commits for Pi5]
* 2026 [https://github.com/aros-development-team/AROS/commits?author=bitplane latest commits for ARM]
====64bit====
'''Download''' A [https://archive.org/details/piAROS Pi Distribution (Distro) has started] and the contents copied to fat32 8GB+ microSD card (there will be drawers/folders - boot c Classes Demos Developer Devs Extras etc only showing). The SD can be plugged in to the Pi. And power on. [https://pi.amiga.icu/ Repository]
[https://aros.sourceforge.io/nightly1.html RaspberryPi 3, 3+, 4 and 5 64bit ArmV8 nightly builds] [https://sourceforge.net/projects/aros/files/ Alternative site and nightly2] which is a test beta limited apps version with both raspi-aarch64-system and raspi-aarch64-contrib can be unbz2'd to a SD or SSD as appropriate.
64bit build works well on a single core LE little endian. Multicore [https://github.com/aros-development-team/AROS/commit/1df0747c2bda3523a43029725a709b1f377d84ec may follow]. Any issues booting could be down to the SD card so please use another SD to see if it is resolved. Remember Aros Arm uses FAT32 and Aros can detect issues with this format very acutely (once fault found, FAT 0x0FFFFFF7 bad cluster so no files written after that, no repair). Please report your experiences in the [https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2138&pid=15057#post_15057 Aros forum thread], [https://forums.raspberrypi.com/viewforum.php?f=179 Raspberry Pi Aros Dev and User forums], [https://forums.raspberrypi.com/viewtopic.php?p=2387984#p2387984 previous Raspberry Pi forum thread]. Any bugs or issues can be [https://github.com/aros-development-team/AROS/issues described here to fix]
Boots with '''USB3''' port based sata3 ssd on Pi400 but untested on Pi4 (may need eeprom update from PiOS or Pi SD Imager) and Pi5
Pi 3 B+ is pre-configured for USB sata3 boot - untested
Pi 3 B may need [https://www.youtube.com/watch?v=ubnwvxF3Klc PiOS to set OTP to boot from usb - do so at your own risk] - if OTP set to usb, boot works but slower than SD card
Speed write wise (top faster)
<pre>
*NVME Pi5 untested >1000MB/sec or faster if matched correctly
*Sata3 ssd 500MB/sec
*SD V90 90MB/sec 4K maybe 8K
*SD V60 60MB/sec 1080p
*SD U3 V30 30MB/sec 720p
*SD C10 U1 V10 A1 A2 10MB/sec minimum should be used now
*SD C06 6MB/sec
*SD C04 4MB/sec
</pre>
As a homage to the past, Aros shows a reduced number of icons but this can be changed by left mouse click in the window and then right click down to Window -> View -> All files
Windows can be manipulated by the top (moving) and the bottom right corner (resizing) only.
Zune like MUI gui interface, has a unique quirk in that after changing a setting in a text box, you may sometimes need to press Enter/Return before clicking OK, Save, etc
Double left mouse click on most picture (Developer/Debug/Tests/Datatypes), audio and video files are supported, via datatypes, by the multiview application.
Esc escape key usually closes open windows even the desktop
In Prefs/Appearance some decorative theming elements need work. There is a few Mason icons in /Prefs/Presets/Icons/Mason/ and the ever present default Gorilla - Icon exchange in works
For more intensive graphics applications, you may need to edit config.txt in the root folder and change 128M to 256M to adjust more memory to graphics usage
If your cursor should '''appear''' to vanish, fear not it is still there. Please head to the top of the screen i.e. the title bar, hold down the left click mouse and drag the screen down a little and the cursor will appear again. Then you can drag the screen up again.
Like most amiga like OSs the audio and networking need to be setup manually
Audio AHI prefs - Mode settings tab - needs both Music unit and Unit 0 set to RPiHDMI:16 bit stereo++ or RPiPWM:16 bit stereo++ at 44100Hz. Press '''Save or Use''' button after each choice
For wireless, please use the Wifi prefs and already selected device bwfm.device. Press Scan and double right click on the router and enter password. You may need to setup after every power off
*if asking for password again - press cancel and go to Network Prefs, Wireless Networks tab and highlight the router line and hit the remove button and press the cancel button. Retry with Wifi prefs again
*...waiting for an address - Disconnect and try Connect
Until, Connected to <router> - 192.168.x.x
For lan ethernet port, please use Network prefs and the following hardware is
*lan9514 Pi3b Pi2 not supported at the moment
*lan7515 Pi3b+ type into Device usblan78xx.device as net0: remove other device(s)
*bcmgenet Pi4 Pi400 choose for Device bcmgenet.device
* Pi5 Pi500 Pi500+ RP1 i/o
(network prefs may forget random information when rebooted)
Summary
<pre>
*3b ethernet not supported, usb ethernet not working but wifi prefs setup works
*3b+ wifi working and ethernet works
*4 untested
*400 wifi and ethernet untested
*5 wifi and ethernet untested
*500 wifi and ethernet untested
*500+ wifi works
</pre>
Type in 'aarch64' in the [https://archives.arosworld.org/index.php?function=search&tool=simple search box] and you will see available software packages / apps. apkg can be used to inspect and install applications.
[http://archives.arosworld.org/index.php?function=browse&cat=network/browser amelinium web browser (JS 1.6 ES9 ECMASCript 2018)] is available with an [https://eab.abime.net/showthread.php?t=122494&page=51 eab thread] reminiscent of [https://github.com/zapek/Voyager Voyager] and to a lesser extent [https://github.com/amigazen/aweb3/ Aweb JavaScript 1.5 (ECMAScript 3)] as css and javascript websites can be slow to load or resolve (no JIT) and nothing from facebook, reddit etc.
Press Cancel at screenmode selector or -wb argument to get windowed version. You could use the Shift + Del shortcut or mouse wheel should work to delete all text at once. To view wikibooks set Agent to Android (telefon) aka Google Chrome 126 or iPhone aka Safari 17 setting in menus. Html5test gives 189 (1.29), 300 (1.31), 311 (1.33) out of 555, some bigger Amiga like browsers are around 370+ but it does less better.
You may have to delete the cache (Menu -> Page -> Delete cache) to fully retest big Amelinium updates or free up space.
Be aware [https://pianetaamiga.it/en/reportage-pianeta-amiga-2026/ some site pages] can use up hundreds of MBs of cache very quickly
DNS lookup failed... close browser and reboot and setup wifi again - repeat until it works again
youtube video and audio - js button for javascript must be on/shaded - Settings -> Soundoutput - AHI
Usually restricted to lower resolutions due to [https://docs.invidious.io/faq/#q-where-are-the-360p480p1080p-quality-options bandwidth]. You can always [https://docs.invidious.io/installation/#install-the-dependencies self host] for better or wait for the newest version of Odyssey OWB (webkit browser).
Telegram https://t.me/s/channel_name for public messages from vamped_amiga chatamigagames demoscenecracktros
*art local js apps like dpaint.js
There is normally no Bluetooth support for most amiga like OSs but Aros has one [https://github.com/aros-development-team/AROS/commit/6942cbfbf66426d21963a7fcd8aba6aff611a9e0 work in progress] [https://forums.raspberrypi.com/viewtopic.php?t=338466 firmware]
*Bluetooth 4.1 BCM43430A1.hcd Pi3B, Pi3A, Zero 2W
*Bluetooth 4.2 BCM4345C0.hcd Pi3B+, Pi4
*Bluetooth 5.0 BCM4345C5.hcd Pi4B rev, CM4 and maybe Pi5 and CM5
<pre>
*bthid keyboard mouse support
*btserial serial
*btpan short range wireless connecting devices
</pre>
Only the Pi5 has a RTC real time clock, the other Pis will need to use ntp services [https://github.com/aros-development-team/AROS/commit/29cd4116330dc7f692d90757eacc59fb3f31ae70 sntp] with time.cloudflare.com pool.ntp.org or Cloudflare 162.159.200.1, 162.159.200.123, 2606:4700:f1::1, 2606:4700:f1::123 or [https://github.com/bohunamiga/PiNTP PiNTP -s goodtime.ijs.si or ntp1.ptb.de] to get the date and time from the internet. Can use date in a shell e.g. date 24-Dec-2026 23:59:59 but this will need to be done again after every reset/power off. Maybe [https://github.com/aros-development-team/AROS/commit/28674a157bc56175aa668e7b62dca6fa740578dc ds3231 rtc with dtoverlay=i2c-rtc,ds3231 in config.txt]
It helps to have all usb devices already plugged in before power on to detect at the moment. Even then some usb devices will freeze the mouse cursor and the only resolution is to remove the offending usb device and reinsert. Sometimes, the reinsert leads to the mouse cursor vanishing, it is still there and responds to left mouse clicks, top of the screen and pull down the screen.
USB classes support from Prefs/Trident is still work in process
*usbaudio working on usb3 port (blue) on pi4, 400 but not working (no rt isochronous) on usb2otg (white or black) for pi3b, zero 2w
*[https://aminet.net/package/mus/midi/camd camdusbmidi] detects midi devices without a preferences file (Prefs/Env-Archive/sys/midi.prefs) as [https://www.youtube.com/watch?v=RBxHkwy4Nrw auto setup now] possibly with [https://github.com/metaneutrons/mt32-pi metaneutrons mt32-pi] [https://github.com/rtzor/mt32-pi mt32-pi fork] [https://github.com/ahmadexp/mt32-pi fork] [https://github.com/gmcn42/mt32-pi-control control of] [https://github.com/dwhinham/mt32-pi mt32-pi pi3+]. Alternative of [https://homspace.nl/samplerbox/ SamplerBox].
Will need developer clang gcc tools to look at 64bit ports of [https://archives.arosworld.org/?function=showfile&file=driver/audio/usbmidi.i386-aros.lha usbmidi], [https://aminet.net/package/mus/midi/CAMD_Toolkit CAMD_Toolkit], [https://aminet.net/package/mus/midi/camdtools camdtools], [https://github.com/cnvogelg/amiditools amiditools], [https://github.com/timoinutilis/midi-sequencer-amigaos horny src], [https://aminet.net/package/mus/midi/horny-base horny-base], [http://bnp.hansfaust.de/index.html BnP], [https://arosarchives.os4depot.net/?function=showfile&file=audio/misc/timidity.lha timidity],
Regarding 680x0 emulation, there are several options (not implemented yet) that could be considered
*[https://github.com/aros-development-team/AROS/blob/6722a0ae9e03fe5d26e32703360bd2059e0864cc/rom/m68kemu/README.md?plain=1#L424 m68kemu.library] for some Amiga productivity where the cpu is emulated and the system calls are redirected to Aros ones
*[https://github.com/BlitterStudio/amiberry amiberry] (winuae) for everything else like games
*[https://github.com/jonx/AROS/tree/aarch64-darwin-graft/arch/all-darwin/libs/emu68k emu68k]
*[https://scriptedamigaemulator.net/ Scripted Amiga] with [https://github.com/naTmeg/ScriptedAmigaEmulator ScriptedAmigaEmulator] or older [https://github.com/gbraad-amiga/ScriptedAmigaEmulator2 ScriptedAmigaEmulator2]
Hopefully getting Pi3 up to 25Mhz 68040 (non JIT) and 75Mhz 68040 (JIT)
Pi4 getting up to 50Mhz 68040 (no JIT) and 150Mhz 68040 (JIT)
[https://pinout.xyz/ GPIO 40 pins] [https://learn.sparkfun.com/tutorials/raspberry-gpio/gpio-pinout pinout]
Some exceptions:
*Physical pins 27, 28 (GPIO0, 1) are an internal I2C bus and should not be used
*The other I2C on pins 3, 5 (GPIO 2, 3) can be used generally, but be aware they have permanent pull-up resistors to 3.3V
*For MIDI use USB but there are dedicated UART pins 8, 10 (GPIO 14, 15).
With a HAT it's more awkward -- you need to know which pins are used by the HAT and avoid them. Hopefully this will be documented.
Remember all GPIOs are 3.3V (not 5V tolerant), floating/noisy inputs can cause odd behavior, and that shorting the power supplies can cause instant death of the Pi.
In the shell (Cntrl + C to end)
GPIO PIN/A/N,SET/N,GET/S,MODE/K,PULL/K
Controls and queries hardware GPIO pins via gpio.resource which is stored in the rom or Devs/ '''please test'''
*PIN -- (Required) Target GPIO pin number (e.g. 12).
*SET -- Set pin output value to 0 (LOW) or 1 (HIGH).
*GET -- Read and print current digital input level (0 or 1).
*MODE -- Configure pin mode: IN (Input), OUT (Output), ALT (Alternate).
*PULL -- Configure pull resistor: NONE, UP, DOWN.
EXAMPLES
<pre>
GPIO 12 MODE OUT
GPIO 12 SET 1
GPIO 12 GET
GPIO 13 PULL UP
</pre>
[https://gpiozero.readthedocs.io/en/stable/installing.html Current] [https://gpiozero.readthedocs.io/en/v1.2.0/api_boards.html old support for gpiozero is unknown at present] [https://energenie4u.co.uk/res/pdfs/ENER314%20UM.pdf and associated 433MHz equipment] [ USA X10 security and lights via USB] [ OpenHab with Shelly Smart Plug connected over Wi-Fi, controlled by MQTT or HTTP]
Printing only with Postscript but [https://github.com/bohunamiga/MintPRINT one] of [https://github.com/boingball/MintPRINT two] [https://github.com/Andiweli/AmiAirPrint/tree/main AirPrint] IPP has been attempted with [https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2061&pid=13954#post_13954 discussion]
Youtube
[], [], [https://www.youtube.com/watch?v=X4fmWAIv7FE Aros native on Pi3b],
[], [], [https://www.youtube.com/watch?v=TSxlYb1eQWU Installed on Pi3b+],
[], [], [https://www.youtube.com/watch?v=NFF1H3jCoz8 testing Aros native on Pi400],
[], [], [https://www.youtube.com/watch?v=nIVx7mh1E1Q&pp=ygUHYXJvcyBwadIHCQkTDAGHKiGM7w%3D%3D Aros on Thumb 2 based 32bit-ish ARM STM32H743 board],
[https://www.youtube.com/watch?v=zQM4CD64xDE&t=612s&pp=ugUEEgJlbg%3D%3D Performance under Linux] but on Aros...
{| class="wikitable sortable" width="90%"
! width="10%" |Pi
! width="10%" |Single Core 2D
! width="10%" |Single Core 3D
! width="10%" |Single Core 3D
! width="10%" |SMP 2D
! width="10%" |SMP 3D
! width="10%" |SMP 3D
! width="35%" |Comments
|-
| <!--Pi-->Pi3
| <!--Single Core 2D-->
| <!--Single Core 3D-->
| <!--Single Core 3D-->
| <!--SMP 2D-->
| <!--SMP 3D-->
| <!--SMP 3D-->
| <!--Comments-->
|-
|}
==== 32bit ====
For the Pi1 Pi2 Pi2B the status of AROS native ARMv6 for 32bit RasPi was OK. System booting, USB working (although with some issues but plans to fix them). 32bit native [http://www.aros.org/nightly1.html ARMv6 32bit nightlys] raspi-armhf-system raspi-armhf-contrib unbz2'd to fat32 microSD
===Hosted===
AArch64 CPU backend for AROS, a Cocoa/Metal display, clipboard / host-volume / CoreAudio / BSD-sockets bridges, GPU 2D via gpufx.library, a 68k→AArch64 JIT (run68k), and a full Rust std port. On [https://www.jkn.me/blog/macaros-aros-on-apple-silicon/ latest Apple Silicon] [https://github.com/jonx/Macaros early buggy alpha version of hosted Aros .dmg on MacOS12+]. Please use [https://github.com/jonx/Macaros/issues MACAros github] for issues, features etc and possibly [https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2030&pid=13910#post_13910 here]
[http://www.aros.org/snapshots1.html old linux and android hosted 32bit]
==== Hosted ====
=====64bit=====
[https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2019&rowstart=80&pid=13667#post_13667 Ubuntu Linux PC hosted Pi compiler build]
[https://github.com/BlitterStudio/aros-compiler-docker Docker based cross compiler for various Aros systems],
[https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2019&rowstart=80 From the Aros Raspberry pi 3 64bit thread]
Instructions on building 64-bit Raspberry Pi AROS and cross-compiler from sources.
You will need:
- Ubuntu 24.04 or 26.04
- qemu-system-aarch64 installed
- Internet connection
- rpi-scripts.tar.gz downloaded (https://axrt.org/download/aros/rpi/rpi-scripts.tar.gz)
1) Install prerequisites:
sudo apt install git gcc g++ make gawk bison flex bzip2 netpbm autoconf automake libc6-dev liblzo2-dev libpng-dev gcc-multilib byacc python3-mako cmake yasm curl nasm
2) Clone sources
cd <project-directory>
git clone https://github.com/aros-development-team/AROS.git --recurse-submodules
3) Extract rpi-scripts.tar.gz. Copy all files into your project directory so that you have:
AROS (the directory with cloned sources)
fix-dotdot.py
rebuild.sh
recreate-sdcard.sh
run-qemu.sh
update-sdcard.sh
4) Run ./rebuild.sh. Select option 1) toolchain-core-aarch64
This will execute process of building a cross-compiler. During this process packages will be downloaded from Internet. This process can take up to 2 hours. If there are some missing dependencies, install them with 'sudo apt install' and restart this step.
5) Run ./rebuild.sh again. Select option 2) core-raspi-aarch64
This will build system files for 64-bit Raspberry Pi AROS. This process can take around an hour.
6) Run ./recreate-sdcard.sh
This will create an sdcard.img file with contents of previous step.
7) Run ./run-qemu.sh
This will start QEMU with SD card image and ROM images. It will boot into AROS.
=====32bit=====
Ubuntu VM approach to compiling [http://lallafa.de/blog/2013/06/building-aros-hosted-for-raspbian/ Linux hosted AROS June 04, 2013]
../AROS/configure --target=linux-armhf --enable-includes=/usr/arm-linux-gnueabihf/include --x-includes=/usr/arm-linux-gnueabihf/include --x-libraries=/usr/arm-linux-gnueabihf/lib
arm-elf- is symbol-linked to arm-linux-gnueabi- (arm-linux-gnueabi- is more correct in this case, because it's going to be compiling the ARM AROSBootstrap for ARM Linux)
*armel - many of the "android" machines require since the entire OS is made for soft float VFP.
*armfp - Efika MX target, Raspberry PI, EfikaMX, Pandora and virtually everything (VFP)
Keep in mind it's possible to start hardfp AROS hosted on softfp system, though, as long as no calls between AROS and host require floating point parameters. NOTE: hardfloat objects *cannot* be linked with softfloat objects - they have a different ABI.
Just keep in mind the arm nightly build machine is quite complex beast. It needs the x86_64 host compiler to compile AROS tools. The arm version is built every night using gcc-4.6.2 crosscompiler (built together with AROS) and successfully builds armel and armhf linux hosted targets.
*needs an AROS code compiler for ARM target
*as well as unix compiler for ARM linux host (would be best to have both softfp and armhf, we have softfp only now) with full set of libraries and includes.
with—disable-crosstools $AROS_CC is always a wrapper around $KERNEL_CC ? If so, this is wrong for some ports. This can break Darwin, Windows and Android port.
Yes, Android port will build. And even work. But it's not good because the port will not be ABI-compatible with other ARM ports. Android's ABI is different from GNUEABI. For example:
<pre>
enum test {foo, bar};
enum test testvar;
</pre>
sizeof(testvar) will be equal to sizeof(int) in GNUEABI (Linux and AROS) and sizeof(short) on Android. This affects linking objects from static linklibs, for example.
Previously everything worked because $AROS_CC was a wrapper on top of $HOST_CC. And a real crosscompiler was used on non-ELF hosts.
Android is the same. $KERNEL_CC is incompatible with AROS.
compiler=kernel is appropriate _ONLY FOR CODE WHICH RUNS ON HOST OS_ (or barebone hardware, if we talk about native). This includes bootstraps, their linklibs, and host-side dynamic libraries (Windows makes extensive use of them because of architectural considerations.
No single AROS object should be compiled with this setting. $KERNEL_CC is really compatible with AROS *ONLY IN LINUX-HOSTED* and no more. On other systems (Darwin, Windows, Android) this is not true any more, and compiler=kernel is never going to work.
If you want to compile your AROS module against host OS includes, append the following to USER_INCLUDES (or USER_CFLAGS, this is effectively the same):
-isystem $(GENINCDIR) $(KERNEL_INCLUDES)
$(KERNEL_INCLUDES) expands to:
-isystem <your_os_includes> -isystem <host_OS_gcc_private_includes>
-nostdinc
This makes AROS compiler adhering to host OS APIs.
If you want some preprocessor symbols based on what your host OS actually is, add something like -DHOST_OS_$(AROS_HOST_ARCH).
Why is there $(GENINCDIR) at all? Because host OS has its own libc includes, which would conflict with AROS ones. And the host OS libc is not binary-compatible with AROS one.
Why doesn't Windows-hosted port use $(KERNEL_INCLUDES) ? Because WinAPI includes conflict with AROS ones in fundamental typedefs, like WORD, BYTE and BOOL. It's almost impossible to deal with this in any other way than rewriting WinAPI definitions using AROS types.
Building under centos 6.3 (i386) currently, and AROS creates the toolchain itself. haven't yet committed the necessary changes but "./configure --target=raspi-armhf" is enough to start, then "make arosboot-raspi" will generate arosraspi.img (containing the bootstrap, kernel.resource, and exec.library) as well as arosraspi.rom (containing all the other essentials components such as dos, graphics etc). It will also copy over a config.txt file to make the raspi bootstrap code load the correct kernel, and a cmdline.txt that enables exec debug output.
*armel = typically Debian 6, Ubuntu Maverick, Android,
*armhf = typically Debian 7, Debian 8, Ubuntu Precise,
Cross-compiling Ubuntu ARM softfp
<pre>
sudo sh
echo 'foreign-architecture armel' >>/etc/dpkg/dpkg.cfg.d/multiarch
echo 'deb [arch=armel] http://ports.ubuntu.com/ precise main universe' >/etc/apt/sources.list.d/armel.list
apt-get update
apt-get install gcc-arm-linux-gnueabi libx11-dev:armel libsdl-dev:armel
</pre>
<pre>
./configure --target=linux-arm --x-includes=/usr/include \
--enable-includes=/usr/arm-linux-gnueabi/include
</pre>
Cross-compiling Ubuntu ARM hard-float
<pre>
sudo sh
echo 'foreign-architecture armhf' >>/etc/dpkg/dpkg.cfg.d/multiarch
echo 'deb [arch=armhf] http://ports.ubuntu.com/ precise main universe' >/etc/apt/sources.list.d/armhf.list
apt-get update
apt-get install gcc-arm-linux-gnueabihf libx11-dev:armhf libsdl-dev:armhf
</pre>
<pre>
./configure --target=linux-armhf --x-includes=/usr/include \
--enable-includes=/usr/arm-linux-gnueabihf/include
</pre>
Now, the AROS build is configured properly and all you need to do is:
make
==Build==
===64bit===
===32bit===
# download/checkout the source someplace, e.g. /build/AROS-Src/
# make a directory to store external sources AROS downloads, e.g. /build/Ports
# make a build directory, e.g. /build/aros-raspi-armhf
# cd into the build dir, configure, and then run make -:
<pre>
>cd /build/aros-raspi-armhf
>/build/AROS-Src/configure --target=raspberrypi-armhf --with-serial-debug --enable-ccache --with-portssources=/build/Ports
>make
>make arosboot-raspi
</pre>
then copy the files from /build/aros-raspi-armhf/bin/raspi-armhf/AROS/ onto an sdcard, and download/copy the Raspi firmware files onto it.
You should then be able to boot the sdcard on your RasPi.
The current W.I.P tree to svn. it can be built as follows ..
<pre>
./configure --target=raspi-armhf
make arosboot-raspi
</pre>
That will generate arosraspi.img, arosraspi.rom and config.txt in bin/raspi-arm/AROS - so either copy just those files to a fat formatted SD card (with the firmware files on), or copy the whole contents of the AROS folder.
NB - if you have a Linux/other install, backup the existing config.txt first
arosraspi.img contains the bootstrap (which has very basic mailbox code, framebuffer/gpio init, and console "emulation" via code pinched from our libbootconsole), kernel.resource, and exec.library
arosraspi.rom contains all the other components needed to boot AROS.
The config.txt file will tell the RasPI bootstrap to load the arosraspi kernel and ramdisk (rom).
the bootstrap has minimal mailbox code, planning on adding either a resource or library that driver/app code will use to access it (likewise for GPIO)
Help building AROS hosted on Linux ARM
Was looking a way to use more my Handheld ARM based called Pyra (Dragonbox Pyra) an ARM (Omap5 cpu with 4GB ram) linux based machine (Debian Buster v10 with kernel 5.6.19 adapted) and have a try to compile the latest Aros sources by Deadwood directly on this device.
Compilation stops after build libpopupmenu.a and trying to build libatomic have this error:
<pre>
Configuring build in bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic
configure: WARNING: unrecognized options: --disable-nls, --without-x
checking for --enable-version-specific-runtime-libs... no
checking for --enable-generated-files-in-srcdir... no
checking build system type... arm-unknown-linux-gnu
checking host system type... arm-unknown-aros
checking target system type... arm-unknown-aros
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for arm-aros-strip... /media/farox/pyra2/arosbuilds/toolchain-core-armhf/arm-aros-strip
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for arm-aros-gcc... /media/farox/pyra2/arosbuilds/toolchain-core-armhf/arm-aros-gcc
checking whether the C compiler works... no
configure: error: in /media/farox/pyra2/arosbuilds/toolchain-core-armhf-build/bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic':
configure: error: C compiler cannot create executables
See config.log' for more details
make[2]: *** [mmakefile:4489: /media/farox/pyra2/arosbuilds/toolchain-core-armhf-build/bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic/.configured] Error 77
[MMAKE] make --no-print-directory TOP=/media/farox/pyra2/arosbuilds/toolchain-core-armhf-build SRCDIR=/media/farox/pyra2/arosbuilds/AROS CURDIR=tools/crosstools/gnu TARGET=tools-crosstools-gcc-libatomic-configure -s --file=mmakefile tools-crosstools-gcc-libatomic-configure failed: 512
[MMAKE] Error: Error while running make in tools/crosstools/gnu: No such file or directory
make[1]: *** [Makefile:361: linklibs-libatomic] Error 10
make: *** [Makefile:183: crosstools] Error 2
</pre>
looking at config.log on arosbuilds/toolchain-core-armhf-build/bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic
found that arosbuilds/toolchain-core-armhf/arm-aros-ld: cannot find -laeabi
so do make linklibs-aeabi-arm-quick
and the missing lib was built.
now the next stop is at
fatal error: bits/libc-header-start.h: No such file or directory
and
fatal error: sys/cdefs.h: No such file or directory
in many places so after checking that have this missing include files i have noted that my include path is a bit different, standard searching path is /usr/arm-linux-gnueabihf but in my system is /usr/include/arm-linux-gnueabihf
so if i add my path to some mmakefiles compilation goes on....but is a better way to add this path to avoid every mmakefiles to be changed?
fixed with adding
-I/usr/include/arm-linux-gnueabihf
to where is missing on mmakefiles like
USER_INCLUDES := -isystem $(GENINCDIR) -I/usr/include/arm-linux-gnueabihf $(KERNEL_INCLUDES)
P.s. I have changed many mmakefiles and have at least compiled (after many hours) the toolchain doing make every time in arosbuilds/toolchain-core-armhf-build (also have to disable making tests under cplusplus but don't remember the directory ...) but ask an help to have an automated way to correctly build without modify mmakefiles.
Last time built armhf target was around 2 years ago. At that point built is via cross-compilation from linux (ubuntu 22.04) using linux armhf crosscompiler (this can explain the path differences you are experiencing) as well as using AROS gcc cross-compiler in version 6.5.0 (build with option 21) in rebuild.sh). Since then AROS GCC has been updated to 10.5.0 and don't believe anyone tried to build the armhf target again.
My suggestion would be to downgrade GCC to 6.5.0 (via editing AROS/config/gcc_def file) and try to first build using cross-compilation from x86_64 linux. Once that works, you will have a "template" to compare to native compilation under arm linux.
Thanks for your suggestion...but think the toolchain with GCC 10.5.0 is compilable if i found a way to pass the path of my system to the script that build (option 21 on rebuild).
The other only changes are (but don't know where to modify...) is to add the build of libaeabi and disable the building of some tests under cplusplus that use exceptions and is not supported under ARM. try to crosscompile with my Linux amd64 PC.
For paths look into core-linux-armhf/bin/linux-armhf/gen/config/target.cfg. A number of build-wide variable is set there containing paths to local build system. These variables and the target.cfg file are generated by AROS ./configure script.
Thanks compilation now go forward...changed target.cfg under "toolchain-core-armhf-build/bin/linux-arm/gen/config" and do make on "toolchain-core-armhf-build" dir.
Need to find where to enable build libaeabi.a so can build the entire toolchain with option 21 of rebuild.sh
Found something that looks like libeabi in AROS/arm-all/arm-aeabi/mmakefile.src. Try adding a third line there:
#MM- linklibs-armhd : libklibs-aeabi-arm
Don't remember needing this library. Possibly the 6.5.0 GCC somehow does this while 10.5.0 is missing this.
Try adding this line (and the variant "linklibs-armhf" instead of hd) but it did not solve the automatic building of the missing lib. I must do "linklibs-aeabi-arm-quick".
Anyway after have build the aeabi lib i succefully built the toolchain (after many hours...). Smile
To test I restarted from selecting option 21 (on rebuild.sh) but after many hours i get the same error of the kernel includes not found...maybe i need to modify the configure script for my case.
With the toolchain built i try to build the core-linux-armhf (DEBUG) (option 22) but after a while it stopped with
"cannot find -laeabi " so i made it built manually...and now i can continue compiling...i'll let you know if all goes ok.
== Hardware ==
===64bit===
====BCM2712====
With the Pi5
Broadcom VideoCore 7 vc7 is an integrated GPU with 12 cores and up to 800 MHz clock. VideoCore VII is capable of OpenGL ES 3.1 and Vulkan 1.2. The driver support for the Raspberry Pi continues to build upon the [https://lore.kernel.org/dri-devel/20230928114532.167854-1-itoral@igalia.com/ open-source V3D driver] stack within [https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25450 Mesa] hopefully be merged for Mesa 23.3. x265 HEVC accelerated untested, x264/h.264 and VP9 cpu only.
*Raspberry Pi M.2 HAT+ Expansion Board
*Geekworm X1001 PCIe to M.2 Key-M NVMe
*Geekworm X1003 PCIe to M.2 HAT NVMe SSD PIP Board for Raspberry Pi 5
*Pineboards Pi Hut HatDrive! M.2 HAT 2024/V4
*Hat+ Gen2 Gen3 Nvme
*GeeekPi 52Pi N04 for Raspberry Pi 5 NVME M.2
*
*2024 RPI AI HAT - Hailo 20TOPs no LLMs
*2026 RPI AI HAT+ 2 - Hailo 40TOPs slightly better?
[https://www.raspberrypi.com/documentation/accessories/camera.html Cameras for Pi]
*Raspberry Pi camera module, the V3 with Sony IMX708 back-illuminated CMOS 12 Megapixel sensor
*Raspberry Pi Camera Module V2 – 8MP Sony IMX219 Sensor
*Raspberry Pi camera Rev 1.3, 5MP 1080P OV5647 image/video module, 2592 x 1944 pixels
====BCM2711====
With the Pi4 an ARM a72 cpu is about x3 times the size of an a53 in the Pi3
the 2711b line used more power when idle, compared to the 2711c
*2018 Raspberry Pi PoE HAT Power Over Ethernet Hat - design issues
*2020 Raspberry Pi PoE+ HAT Power Over Ethernet Hat Pi3b+ Pi4 only - better design
*Waveshare PoE HAT (B) with cooling fan for Raspberry Pi 3B+/4B 802.3af PoE
*[https://github.com/axizo-pi/V3DLib vc6 V3D 4.2] is derived from [https://docs.broadcom.com/doc/12358545 vc4], but it is significantly different
The QPU pipeline stays mostly the same, you still have an add ALU and a multiply ALU and it can issue two ALU OPs per cycle. There is still 4 SIMD lanes, interleaved over 4 cycles.
The instruction encoding for the QPUs is different, but the core instructions are the same.
Instructions for packed 8 bit int math has been dropped, along with most of the pack modes.
Instructions for packed 16bit float math has been added (2 floats at in a single operation)
With vc5/vc6, you write two packed 16f value to the tilebuffer (or four writes of 32f, if you are using the rgba32f framebuffer). And there is a handy vfpack operation which allows you to pack two f32s into a single 32bit value in a single instruction. You can vfpack directly into the tile buffer register.
the multiply ALU can now fadd, so you can issue two fadds per instruction. the add ALU has gained a bunch of new instructions
the A and B register files have been merged. You still only get an A read and a B read per instruction, but they read from one big register file (which means the underlying memory block has gone from two sets of "one read port, one write port" to one "two read ports, one write port" block)
The theoretical max FLOPs per QPU remains the same at two per cycle, other than the bump from 400mhz to 500mhx but it looks like a lot of effort has been put putting those theoretical FLOPs to better use.
*vc4 could run one or two threads per QPU. When you ran in two thread mode, the available register file halfed to 32 registers.
*vc5 added a four thread per QPU mode, with 16 registers per thread.
*vc6 doubled the size of the register file. You could now use all 64 threads in two thread mode and 32 registers in for thread mode. Single thread mode was removed, you always have at least two threads.
With the threading improvements, the QPUs should spent much less time idle waiting NOPs for memory requests. Most of the design changes have gone to improving the fixed function hardware around the QPUs. A fixed function blend unit has been added, which should reduce load on the QPUs when doing alpha blending. hope software blending is still possible
The tile buffer can now store upto 4 render targets (up to 128bits per pixel, so if you are using 4 32bit render targets, you can't have a depth buffer)
A MMU, allowing a much simpler/faster kernel driver.
Many more texture formats, framebuffer formats.
h264/x264 as Pi3
All the features needed for opengl es 3.0
H.265 / HEVC decoder is a HEVCv2 Main 4:4:4 10 design supporting bitstreams up to profile 5.1
HEVC hardware decode supports 4kp60, 10-bit. Audio output is pretty much unchanged, but the HDMI audio channels now support 8x192kHz bitrates
Each ALU typically have 2 floating point operators, and as you pointed out in a earlier post videocore 6 is no exception, with both a multiply and additive floating point operator. Thus theoretical GFLOPs are calculated with both operators in mind. That is what the 2 in my formula represents, and is common across any modern programmable shader, whether you calculate Nvidia, AMD, Intel, Boardcom or any other company's GPUs. Total ALUs * 2 * GHz clock = GFLOPs, In the case of Raspberry Pi 3, it's 24 ALUs * 2 operators * 0.4GHz = 19.2GFLOPs
If the Videocore 6 does indeed only have 16 ALUs (16 * 2 * 0.5GHz), you'd have only 16GFLOPs but they are better utilised
Possible maximum performance
<pre>
VideoCore IV @ 250MHz: 250 [MHz] x 3 [slice] x 4 [qpu/slice] x 4 [processor] x 2 [op/clock] = 24 Gflop/s
VideoCore IV @ 300MHz: 300 [MHz] x 3 [slice] x 4 [qpu/slice] x 4 [processor] x 2 [op/clock] = 28.8 Gflop/s
VideoCore VI @ 500MHz: 500 [MHz] x 2 [slice] x 4 [qpu/slice] x 4 [processor] x 2 [op/clock] = 32 Gflop/s
</pre>
Faster LPDDR4 memory.
====BCM2837====
With the Pi3
* Broadcom BCM43438 chip provides 2.4 GHz 802.11n wireless LAN, Bluetooth Low Energy, and Bluetooth 4.1 Classic radio support, 3B+ [https://github.com/aros-development-team/AROS/commit/afa5bc0bb17d5dd06bcfdbac00853a3799ca8d76 LAN7515]
The overclock ability has diminished with each chip version as the energy usage has increased. BCM2837 is one of the warmest yet and benefits from active fan cooling if all four cpu cores are in use for a short while. Video playback is not affected due to the custom support in the GPU. 5 V / 2.4 or 2.5 amp power supply recommended if all four cpu cores are running, else throttling (cpu slowdown) might occur.
Dual VDP and scalable QPU in VC4 and x.264/h.264 accelerated untested only and VP9 on cpu or neon help
ARMv8-A has [https://developer.arm.com/documentation/102412/0100/Privilege-and-Exception-levels privilege levels] where userspace typically runs at ‘EL0’, the kernel at ‘EL1’ or ‘EL2’ and the firmware at the highest level ‘EL3’.
===32bit===
=== Core Kernel ===
====BCM2708(family)====
which includes the [http://elinux.org/RPi_Hardware BCM2835] (ARM1176JZF-S 700 MHz CPU + VideoCore IV GPU + up to 1GB RAM)
*Framebuffer (fb) using mailbox
*IRQ scheduler, etc
*Arasan based SD Card controller
*Synopsis DesignWare USB 2.0 OTG controller [http://networkdirection.net/index.php?option=com_content&view=article&id=106:rasperry-pi-usb-controller&catid=45:raspberry-pi&Itemid=54 Unofficial DOCS pdf], [dwc_otg.c FreeBSD], [], [https://www.riscosopen.org/viewer/view/mixed/RiscOS/Sources/HWSupport/USB/Controllers/DWCDriver/ RiscOS USB Driver], [https://www.riscosopen.org/forum/forums/5/topics/878 RiscOS USB Discussion], [https://www.riscosopen.org/forum/forums/11/topics/1893 Other USB RiscOS], [http://plan9.bell-labs.com/plan9/index.html Plan9 Miller's usb] http://plan9.bell-labs.com/sources/contrib/miller/, [https://github.com/Chadderz121/csud CSUD driver],
*[http://www.smsc.com/media/Downloads_Public/Data_Sheets/9512.pdf SMSC 9512] USB LAN/Hub chip
*CMOS RAM
*VCHIQ port which sends messages to the GPU e.g. for mouse, keyboard, audio on HDMI, etc
*Audio Driver
*Serial Peripheral Interface Bus (SPI)
*[http://www.susa.net/wordpress/2012/06/raspberry-pi-pcf8563-real-time-clock-rtc/ I2C registers]
*I2S
*Universal Asynchronous Receiver Transmitter (UART)
*[http://elinux.org/RPi_BCM2835_GPIOs GPIOs] and [http://www.adafruit.com/blog/2012/08/17/broadcom-bcm2835-peripheral-memory-map-and-gpio-alternate-use-chart-piday-raspberrypi-raspberry_pi/ Alternative view of GPIO]
BCM2836
* For Pi B+, PI 2 and Pi 3 SMSC LAN9514 chip adding 10/100 Ethernet connectivity and four USB channels to the board
*[http://www.andrewscheller.co.uk/rpi_pcb_modules.html PCB], [http://elinux.org/RPi_Low-level_peripherals Low level features],
Implemented so far...
# Modify the configure system so that it correctly builds for the arm hardware float raspi target.
# Implemented the bootstrap to load the aros modules and prepare the arm to jump into them. Reworked the x86 console support so that parts can be stolen for raspi to use since t has no basic functionality to output to the display.
# Implemented a kernel.resource to prepare the raspi for running aros and provide the low level api calls to expose available resources and allow exec, etc function.
# Implemented serial debug support
# Implemented the exec (and kernel) functionality required to make multitasking work (and interrupts, exceptions, syscalls, etc)
# Implemented a timer.device to utilise the hardware timers.
# Implemented a very basic gfx driver to expose the hardware's framebuffer.
# Implemented an SD-Card driver for AROS which presently only supports the raspi's chipset but can easily be modified to support all sd-card hardware and media.
# Fixed the fat filesystem support in AROS so that it can boot on RasPi's normal SD-Card setup. The "rom" image files needed use a different filename than the default linux, etc images so can be easily installed without harming the existing files - you only need to change the loaded images in the config file to get aros to boot.
# Updated the build scripts to automatically download the necessary raspi firmware files and wrap it all up so that you can simply extract the archive to a fat formatted sdcard and boot it on the raspi without having to get anything else.
# fix everything in contrib and ports to build for raspi (needs proper testing/fixes but allows every component to actually compile at least, including owb) + numerous other fixes to get things working on arm/raspi ..
Improvements...
# Implement a USB chipset driver "OR" finish the existing one [https://github.com/aros-development-team/AROS/commit/c07d13c724f944674be5db54fc6a71ee72a01809 usb otg] - the current code is mostly a skeleton that should initialise the chipset and then needs relevant code to support the different transfer types. It also has the "virtual" hub code in place to represent the raspi's USB port (from poseidons p.o.v)
# Implement a driver for the USB NIC (a few weeks - depends on USB above)
# Write an [https://github.com/aros-development-team/AROS/commit/d55d0f74d20b769bbb8c8d386e5c1d7a9154f05a audio driver] (a few weeks - independent of USB) and [https://github.com/aros-development-team/AROS/commit/e93a4c245f27a87c9c4c1d39206694b39059998a HDMI]
# fix syscall bug in the current raspi kernel code
# Graphics depend on having a decent "bcmdma.resource" implemented as to use the cpu's dma engine. The sd card driver needs to use it for transfers to/from the controller - and the gfx system needs to use it for "blitting".
# [https://github.com/aros-development-team/AROS/commit/4019d84e4975d4dad987a12d57fe108f5ac048e6 Improve the gfx driver], [ vc4gfx HIDD] add [http://dri.freedesktop.org/wiki/VC4/ Gallium3D support]
# [https://github.com/aros-development-team/AROS/commit/b13905b3e8e45b089f520b44692c81affddd066f Improve] the [https://github.com/aros-development-team/AROS/commit/3a876755c070f5c73c4f53c7f4d35b4f923088b9 sdcard] device driver - which is also pretty basic but should work with most cards, rework it to also support pci, etc. sd card interfaces on x86
# The current code using very rudimentary access to the gpio interface - so that should be implemented as some resource for other components to access, as-well as the i2c interface exposed over the gpio interface. that should have a hidd class implemented which uses the gpio resource to communicate.
Boot up typical for most other OSs before the open sourcing of many binary blobs from 2017 onwards
On power-up, the rpi [http://www.open.com.au/mikem/bcm2835/ BCM 2835] [https://github.com/hermanhermitage/videocoreiv VideoCore4] GPU, not the ARM CPU, is in control, and the SD card slot is the only peripheral device with power. The firmware burned into the BCM2835's VideoCoreIV GPU PROM requires a DOS-style partition table; a FAT-formatted first partition; and the freely redistributable but closed sourced Broadcom files “bootcode.bin” and “start.elf” in that partition.
The boot sequence carries out several pre-boot tasks
*On powering of the rpi, the GPU reads and executes bootcode.bin, which then loads start.elf
*The GPU loads the “start.elf” file, eventually, into the L2 cache and then executes it
*configures the memory split for the CPU and GPU
*reads and parses “config.txt” from the same partition on the SD card and applies the settings (like a PC’s BIOS settings)
*loads the “kernel.img” file, again from the same partition
*activates the CPU to begin executing the loaded kernel image
The CPU/GPU memory split is hard-coded into start.elf, so Broadcom provides three start.elf images, to give 32M, 64M, or 128M to the GPU for multimedia performance, and the remainder to the CPU.
RPi uses [https://github.com/raspberrypi/firmware some closed source loaders] and at some point it loads a binary blob named "kernel.img" at 0x8000, at that point there would be a rudimentary Aros alive. If one wants to use the SD-card then there would have to be a driver for the interface and a fat filesystem handler (SD-card has to be formatted to fat filesystem)
Boot code and kernel are now linked together and made into that binary blob, just for starters. Raspberry Pi uses [http://kernelnomicon.org/?p=133 u-boot] and [http://kernelnomicon.org/?p=138 UBoot] as bootloader, there's already some code in the Efika MX port for that. UBoot is a native bootloader and not just for the raspberry pi, it loads after start.elf.
You can find Efika MX port from arch implementations, some hacking is needed for the mmakefile.src'es as iit dates back to before the Aros crosstool era or else you get some weird errors while building. You also need to code the bootstrap and serial handling.
At the moment it seems that a fastest route for the native build would be to make one binary blob without using the package system. Raspberry's memory layout is pretty simple and if the implemented u-boot doesn't support loading other modules
<pre>
? - alias for 'help'
mtest - simple RAM test
autoscr - run script from memory
base - print or set address offset
bbm - BBM sub-system
bdinfo - print Board Info structure
boot - boot default, i.e., run 'bootcmd'
bootd - boot default, i.e., run 'bootcmd'
bootm - boot application image from memory
bootp - boot image via network using BootP/TFTP protocol
cmp - memory compare
coninfo - print console devices and information
cp - memory copy
crc32 - checksum calculation
echo - echo args to console
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls - list files in a directory (default /)
go - start application at address 'addr'
help - print online help
iminfo - print header information for application image
itest - return true/false on integer compare
jade -
loadb - load binary file over serial line (kermit mode)
loads - load S-Record file over serial line
loady - load binary file over serial line (ymodem mode)
loop - infinite loop on address range
md - memory display
mm - memory modify (auto-incrementing)
mtest - simple RAM test
mw - memory write (fill)
nfs - boot image via network using NFS protocol
nm - memory modify (constant address)
pci - list and access PCI Configuration Space
ping - send ICMP ECHO_REQUEST to network host
printenv - print environment variables
rarpboot - boot image via network using RARP/TFTP protocol
reset - Perform RESET of the CPU
run - run commands in an environment variable
saveenv - save environment variables to persistent storage
saves - save S-Record file over serial line
setenv - set environment variables
sleep - delay execution for some time
tftpboot - boot image via network using TFTP protocol
USB - USB sub-system
usbboot - boot from USB device
version - print monitor version
</pre>
And there is one more thing about modular ports. In order to actually implement this, your bootstrapping environment should provide the ability to load several files. On PC this is provided by GRUB2. on CHRP you can read filesystem via OpenFirmware, and Sam's Parthenope relies on modified u-boot. If your bootstrap allows to load only a single file, then you stuck with monolithic kickstart. By the way... u-boot allows not only to boot up a single uImage or zImage, it also allows to write client programs AFAIK. With this approach, you actually can write modular bootstrap for ARM AROS using unmodified u-boot.
Most used [http://www.compulab.co.il/workspace/mediawiki/index.php5/U-Boot_quick_reference uboot options] are fatls usb 0:1,
the reason behind INTB_KERNEL is to allow use of the standard Exec function AddIntServer() to add interrupt handlers for
hardware drivers etc. AmigaOS never used it for abstract hardware drivers. AmigaOS routed only raw hardware IRQs there. Their assignment was hardcoded. As well as number of them. Actually on AmigaOS every bus has its own interrupt subsystem. For example PCI bus. PCI interrupts on Amiga are routed to a single exec interrupt. 1:1 relationship between CPU and hardware interrupts is present only on PC.
IMHO we miss things like AddInterrupt/RemInterrupt methods on our PCI subsystem's device class. PCI bus class should map these methods to whatever is appropriate. This is how it is done on AmigaOS and friends. When these are implemented, raw kernel.resource API will be needed only for several PC-specific drivers with hardwired resources. Exec IRQs are real IRQs only on Amiga hardware. On other machines they can be emulated where appropriate (VBlank is a good example). kernel.resource is meant to be different, its IRQs are hardware-agnostic, they are plain "Hardware IRQ number X, whatever this means". They are low-level actually, and meaningful only in the context of a particular system.
Was that not the transition from irq.hidd to kernel.resource? No. A long time ago there was another hacky bit named INTB_TIMERTICK. It was "abstract timer interrupt", used by timer.device. It was the same as VBlank, but with larger frequency. I removed it, because kernel.resource API was a cleaner way to access this interrupt. Furthermore, there can be more than one timer in the system. Thinking about bringing back timer HIDD definitions again. hpet.resource is a bad idea.
Can someone please enlighten me a little on how the scheduler is meant to work?
Poseidon.library creates its "Poseidon Event Task" during RTF_COLDSTART -> then calls Wait(), and ends up in limbo because wait disables interrupts (used for the scheduler heartbeat), and basically waits forever because the sigbit is never set, since krnSwitch doesn't switch the task unless TF_SWITCH is set, and no codepath run during this seems to set it?? TF_SWITCH does not disable/enable switching. This flag just enables to run user-supplied hook when the task is being switched away. It is completely safe to call Wait() in Disable()d state. Doing this actually temporarily breaks this state. IDNestCnt gets remembered in struct Task, then next task is selected, and its IDNestCnt is restored in sysbase (see kernel_scheduler.c). If there are no other tasks, then your cpu_Dispatch() should enable interrupts on the CPU and enter idle mode. See x86 implementation for good example.
You miss what happens next...
1. KrnSwitch() saves context of your task, saves IDNestCnt (core_Switch() and cpu_Switch()), then drops into cpu_Dispatch().
2. cpu_Dispatch() calls core_Dispatch. Then two cases are possible:
2a. There is a READY task. It is picked up, its IDNestCnt is restored in SysBase, then cpu_Dispatch() needs to restore registers and exit. The next task is run.
2b. There are no READY tasks. core_Dispatch() returns NULL. In this case your cpu_Dispatch() should enter idle loop. It should just enable interrupts on the CPU and put it on halt. This allows it to process hardware interrupts. Eventually some of your interrupt handlers wakes up your task and puts it into READY list.
My heartbeat interrupt has been slowed atm to help debugging - but it never actually gets a chance to fire because of the Wait() disabling interrupts. Perhaps you have forgotten to enable interrupts in your idle loop.
There is a change in the format of AROS executables. Until now we were using Elf RELocable files which are usually used as intermediate object files. We had them for various reasons, one of them was how AROS files were built in the past. That days we had no real aros cross compiler and the option to embed relocation data in unix executables (or in executable files in general) was rather new and not every linux/unix system had it. Therefore we have decided to use intermediate files. Although it was somehow working (and it is still working :-)), it has some drawbacks. Therefore decided to introduce real Elf EXEC types, in first turn implemented on ARM target with option to expand in future to all other AROS architectures.
The first patch was pretty easy and appeared to work somehow. It generated nice executables with embedded relocation info. Not only that, it also removed all global symbols adjusting relocation data to be relative to the beginning of the sections. That move reduced number of symbols in each executable significantly (depending on the file between 20 and 80% of all symbols could be removed). The only symbols that stayed in the file are local ones - due to the nature of the patch wasn't able to remove them since we have not seen them in the symbol hash table.
The patch didn't worked though. The files were relocated, AROS kernel loaded, but it crashed very early. What happened? Well, the nature of ARM relocations happened :)
Most of the relocation data on all machines is rather simple. Relocation can be absolute or pc-relative, sometimes the offset has to be bit shifted. On ARM v7 there is another one. There, when one wants to load an address of function/variable into register a combination of two instructions can be used: movw and movt. The first one loads immediate into lower 16 bits of a register while clearing upper 16 bits. The second one loads immediate into upper 16 bits without touching lower halfword. Loading of a pointer into a register looks like this:
movw r0, #:lower16:label
movt r0, #:upper16:label
In this case there are two relocations - one for lower halfword and another for upper. If an overflow of lower 16 bits occurs during relocation process, the upper one should be updated as well. Unfortunately with current patch and with typical ARM executables there is not enough information to perform the calculations.
There are two options - the first one would be to give up and go back to "fake" executables, another one would be to change from REL to RELA relocation info. The latter contains an addend, extra data which can be used to perform all the relocation calculations I need.
Decided for the second option. The patch is already in the works. There is another function for the binutils' bfd backend to perform the final relocation. There can decide what to do with every reloc info, modify data and eventually strip some symbols. An advantage is - at this stage of the linking process have also full access to all local symbols so can change all relocations section relative and eventually strip all symbols from the files.
GPU
VCore developed by Alphamosaic Ltd and now owned by Broadcom. Most of start.elf runs on the GPU. Placing ALL the userland GPU code in the videocore.hidd isn't going to be a terribly big problem because the code they published is nothing more than a shim that sends data straight to the GPU to execute.
The good news about this is that we only need to write our HIDD using the OpenVG API. The shim is relatively small codewise and lives in the ARM memory (the actual OpenVG code itself lives in the GPU RAM area and its loaded from start.elf). That's also the bad news. Our driver has to translate AROS video calls to OpenVG calls, for most tasks it should be easy, for some, not so much. It's still probably less difficult and less work, than controlling the GPU directly.
The other good news is that anything done through OpenVG happens on the GPU, its truly accelerated. It also has some nice font functions, meaning we can lead into an accelerated text mode later.
Basically, AROS resets or locks up when it tries to use AROS_ATOMIC_INC or DEC. If I comment out the byte/word operations in the header files and use non-atomic operations, the code works as expected.
have read that the L1 cache needs to be enabled to use LDREX and co (which I also read is only meant to be used on multi processor systems with shared memory) - however I am certain this is correctly enabled.
If you are using LREX or STREX, you should have L1 cache enabled, at least on the ARM CPU I work with at work.
L1 cache is enabled by enabling the MMU *AND* setting the C and I bits in the CPU - the C bit is ignored, and the I bit only covers the 16 byte instruction pipeline if the MMU is not enabled.
Can you verify that your assembly is generating LDREX/STREX? From the behavior, it almost sounds like its generating the default Semaphore locked atomics.
Impossible. There are no semaphore-locked atomics. There are Disable()/Enable()-based ones instead. And there's a special #define AROS_NO_ATOMIC_OPERATIONS in this case, which tweaks Disable()/Enable() implementations not to recurse forever.
I have tested this on ARMv5 which does not have ldrex/strex, it works fine. On those ARMs there's no way to have real atomics. On other OSes (like Linux) this is done by introducing things like atomic_t, which appears to be a complex structure, holding the value together with accompanying spinlock (implemented using swp).
#warning "TODO: lookup optimal mmu table settings for raspi memory"
/* Set up an identity-mapping for all 4GB */
for(x = 0; x < 4096; x ++)
{
pagetable[x] = x<<20 | (0x40002|0x80000|0x010000|0x00C00|0x04);
}
Shouldn't there be a second loop that sets the 'C' bit in the descriptor for the RAM pages?
Currently, you have TEX=0, C=0, B=1 for all pages (Shared Device).
You should have TEX=0, C=1, B=0 for RAM (Write-Through, Cached)
So ..
pagetable[x] = x<<20 | 2;
should be enough?
No, for RAM you need to change the '| 0x40' to '| 0x80'
tell dosboot the correct defaults to use
Please don't do this. This bootconfig.c is a deprecated legacy thing. I wanted it to go away completely with time. Instead, display drivers should auto-install themselves during own initialization phase. I. e. detect hardware=>instantiate itself. This should make things way simpler. With this approach you only need to add the driver into KS image to get the device autobooted. No hardcoded stuff.
Currently VESA and VGA drivers do this, look there for examples. never rewrote ATI driver because i don't have any test system for it.
they defined a smaller AROSCPUContext than the ExceptionContext - yet reference it as ExceptionContext in other places, and since it hasn't allocated enough storage for ExceptionContext, are corrupting memory/the structure (since the elements that are there don't map 1 to 1 with the exception context).
AFAIK, AROS has been moving in a different direction to this in recent years. It is the job of graphics HIDDs to allocate bitmaps etc. so that they have the most suitable characteristics, including allocating them from GPU RAM where possible. The concept of chip RAM is only for legacy code, and most if not all non-68k platforms should have all system RAM
marked as chip.
BTW, is the video processing code you mention CPU code or GPU code?
Also, IIRC we have support for "external memory allocators". Perhaps that's what we need for the allocation of GPU RAM through the mailbox.
All hosted and x86 native ports should use proper context formats.
trying to clarify if the vblank handler has to have run by this point to prevent this deadlock. Actually, no. Unless you have installed VBlank handler which should wake up at some point. Without VBlank there will be no quantum count. Consequently, there will be no forced preemption. But the rest will work, and multitasking will be cooperative (switch happens only when current task voluntarily gives up the CPU). Does it depend on the vblank having run before this point? and if yes what does that mean on systems where it might be able to run enough code (e.g. get to this point) before the vblank interrupt has triggered? What is it waiting for? It could wait for timer, in this case you need timer.device working. VBlank is currently needed for exec's quantum counter. In current native ports we have only a single timer, which is served by timer.device. VBlank is simulated by timer.device also. If your machine has two timers, then you can use one of them for VBlank, and another for timer.device, this will simplify things down. VBlank needs to be 50 Hz for historical reasons, many programs use it as cheap timer. I am periodically thinking about making some abstract mechanism to be able to change quantum source (and untie it from 50 Hz), but have no time to come up with something good. Additionally i started disliking timer.device hardcoded design when PC has got many timers (old 8253, APIC, HPET).
Currently i think there should be some low-level entity representing tick source. timer.device should just select the most appropriate source for its units.
The BCM2835 has 4 GPU based timer sources - 2 are used by the GPU, so im using Timer3 for our heartbeat and the remaining one will be free to the system. There is also the less capable ARM timer but that is dependent on the CPU frequency. Very good. You won't need any emulation. Set the heartbeat to 50 Hz and drive VBlank from it. Use other timer for MicroHZ.
Can you use the 'econsole.hook' I make for debugging the Sam460 via the serial port?
It provides a before-anything-else shell prompt on the serial port. You can then do 'NewCLI' to test your graphics, or use any DOS command in shellcommands.resource.
You should just be able to add econsole.hook to your module list, and use 'econsole' in your bootargs.
So long as you have a working Exec/RawMayGetChar and Exec/RawPutChar, it should work.
Also make sure to add shell.resource and shellcommands.resource for this.
That should have done it.
If you set "#define DEBUG 1" in arch/all-native/econsole/econsole.c, do you get any additional serial output?
have added it to the build and added econsole to the command line - and can see the bootloader picks up on the emergency bootconsole tag, but I still only get the insert bootable media display?
Im assuming it exposes a fake filesystem that tricks aros into booting?
The contents of which are: ECON:AROS.boot
Way to handle the scheduling code? The implementations I had been following were causing problems, due to cascading interrupts which I cant handle properly in the asm stubs just now (when they break disable etc.) - since it means detecting the interrupted codes cpu mode and getting the correct sp/lr for it, and that's just too tedious for arm.
To work around this ive added a system idle task which does nothing - and when the scheduling code has no task to run switches this in and lets it run, thereby allowing the interrupts etc to resume until something does need to happen.
Also, by adding accounting code to cpu_Switch() and cpu_Dispatch(), it should allow the system to log idle time correctly (as well as running tasks).
have thought of also adding an additional task that never runs, solely to record time spent in IRQ handlers, but I digress..
was under the impression that kernel.resource should *never* be used outside of exec.library. This is a wrong impression.
Michal started designing it because portable nature of AROS does not fit well into exec's API with all its assumptions. So, he started the new, hardware-agnostic kernel API from scratch. Yes, exec sits on top of it in places. But kernel always meant to be open thing. Otherwise it would not exist.
it wasn't meant to be just used willy nilly by user code - but by lower system components (e.g. exec) so that they could be implemented in a more generic fashion, and the kernel resource itself hide the systems quirks.
Adding new things there perfectly keeps up with our decision to minimize AROS-specific intervention into APIs which can clash with MorphOS or Amiga OS4 extensions. We want at least source-level compatibility there. Binary compatibility on PPC would be extremely cool, but at the other hand we have no maintainer for this, as well as their ABIs splintering.
It depends on what exactly is being implemented - there's no reason we should have everything crammed into kernel.resource if it doesn't need to be (i.e. if its better suited as a separate component/subsystem in its own right)
The _LE versions are for when you have endian swapping taking place. If the graphics are the same endian as the CPU, no swapping should occur. I ran into a similar terminology problem in SDL with a friend insisting that his Radeon 7000 on his PC was big-endian. It is not, it just uses the same endianness for the graphics card and the CPU so no swapping was necessary. They were both little-endian.
The _LE versions are because the PixFmts refer to the bitmap data being in big endian format in memory, for which the normal version would need to do endianness conversion before applying the shifts/masks. on this platform it is in _LE in memory also so we don't need the conversion hence using the _LE version of the call). would use _LE (if it's really little endian 16 bit mode).
What is the bare minimum needed to implement a framebuffer based gfx driver, with our software handling the rest?
Have tried with just a gfx class that only expose new/dispose/newbitmap - and having an onscreenbitmap used only for the framebuffer itself (with all other bitmaps being chunkybm, and the framebuffer's superclass also being chunkybm), but that alone isn't enough it seems?
You can use workbench/hidds/sm502/ as your example - it is as simple as I could make it.
So, AROS creates the framebuffer bitmap (verified this) -> so surely it should be capable of then rendeing into it? I don't actually create the framebuffer "bitmap object" myself - only as a result of being asked to. The code I currently have on SVN seems to create the framebuffers bitmap object fine, but then crashes in intuitions DisplayDriver callback. In particular it crashes performing the getattr on the system default pointer. don't expose MEMF_CHIP in an allocatable form so AllocSpriteData was failing (and other code later doesn't check if the values are valid == illegal memory accesses)
So far have -:
vc_init: queries the gpus memory, and sets up a fake memory handler for it, then adds the bootmode driver and returns saying all is well
vc_gfxhidd:New: sets up some fake syncmodes to test with and creates the real gfx object.
vc_gfxhidd:NewBitmap: checks if its a framebuffer and uses the onbitmap class or uses the chunkybm class otherwise
vc_onbitmap:New; creates a chunkybm object and then pushes the real framebuffer address into it as the buffer,
vc4 had v8adds, v8subs, v8muld, v8min and v8max which operated on four 8bit uint values packed into a 32bit register. Multiplication was in the range 0.0 to 1.0 and addition/subtraction saturated. There were also a range unpacking/packing modes that allowed you to pack and unpack 8bit values into 32bit registers.
RasPi has to speak to the "operating system" which runs on the GPU itself and request/free memory - it cant directly manage it itself, and so the managed functions were used to wrap these calls.
The Arm and GPU share memory space. The framebuffer is shared. The Arm can write a pixel and it will appear on the screen (through GPU hardware) without flushing/copying being required.
The GPU can composite multiple FB's in real time - so you have a number of surfaces defined which are rotated etc and composited in real time to the output. Copying can map from the address space of the Arm to the flat space of the GPU which takes some code, but I don't think whole buffers are copied.
The DMA hardware can also access the whole memory space and can perform 2D fills and blits (no blending). This is documented in the peripheral spec posted. The DMA is just an Arm accessible peripheral and can be set up with low latency (e.g. microseconds).
must use a 0xc0000000-based bus address to access SDRAM, yet non-DMA access should go via a 0x0-based bus address.
For 2D dma, set TDMODE, and the spec says "interpret the TXFR_LEN register as YLENGTH number of transfers each of XLENGTH, and add the strides to the address after each transfer." so set STRIDE to pitch of the image, the width is XLENGTH and height is YLENGTH. You would fill by not setting the SRC_INC and point source to your fill data.
The DMA cannot see the ARM's L1 cache, so you would map the framebuffer with ioremap_nocache. Depending on where the source data comes from, it may need an L1 cache flush. The DMA can see the L2 cache. Use 0xC0000000 bus addresses when L2 is disabled and 0x40000000 bus addresses when L2 is enabled. (actually just call virt_to_bus and you'll get the right address out).
openGLES/openVG has high latency. Writing to framebuffer then reading it back is very inefficient (e.g. milliseconds). If you can drive it a unidirectional way, just streaming commands at then that is efficient. openVG is not implemented on top of openGLES - it uses the same hardware but as a first class interface
To improve the Gfx driver, we will need a DMA resource implemented so can use to perform DMA operations. The Gfx driver will need this to perform blits.
Actually MEMF_CHIP has to present, for historical reasons.
This has been never fully agreed upon, but in ports i wrote i exposed the whole memory as MEMF_CHIP. The idea behind this is that CHIP is originally the memory where graphics and sound data can be put. On non-Amiga platforms there are no restrictions on this, so the whole memory is CHIP.
Yes, many old software can misbehave with CHIP memory size larger than 2MB. But this actually applies only to m68k AROS which is going to run m68k binaries. In other cases it's quite logical to fix the program when porting.
As to original question: yes, it's enough to have a framebuffer bitmap (one with aoHidd_BitMap_FrameBuffer set to TRUE) and PutPixel routine. It framebuffer can be served by chunky bitmap class, then you can simply create chunky bitmap with your own buffer (see how VESA driver does this). Chunky PutPixel is already there.
struggling to determine what is the correct pixfmt to use for the 24/16/15 bit gfx modes on the RasPi. AFAIK it uses RGB565, for 16bit but im unsure what shifts etc should go with it? suffice to say Im getting the wrong colors so far lol.
<pre>
redmask: 0x0000F800
greenmask: 0x000007E0
bluemask: 0x0000001F
alphamask: 0
redshift: 16
greenshift: 21
blueshift: 27
alphashift: 0
</pre>
It should likely be vHidd_StdPixFmt_RGB16_LE
This stuff is a bit confusing. The "names" of the stdpixfmts are based on the layout in memory,
ignoring endianess. So for example:
ARGB32: will be 0xAA 0xRR 0xGG 0xBB in memory on both big endian and little endian machines.
The shifts and masks OTOH are based on pixel access (ULONG in this case), so differ depending
on whether you run on big endian machine or little endian machine (that's why there's stdpixfmt_le.h and
stdpixfmt_be.h in rom/hidds/graphics/).
With the 16 bit pixel format it's even more confusing, as for example it's impossible on little endian machine
to describe RGB16 with shifts/masks alone. That's why there's vHidd_PixFmt_SwapPixelBytes_Flag.
(RGB16 == RRRRRGGG GGGBBBBB in memory, and for pixel (WORD) access on little endian machine it needs to
be accessed as GGGBBBBBRRRRRGGGG).
The shifts btw indicate how much to shift the component to the left (!) so that it is moved to the highest bit (31).
The aHidd_PixFmt_StdPixFmt you specify will be ignored most of the time, because when the pixelfmt is registered,
the gfx hidd checks if there's an identical pixfmt (shifts/masks/etc., but ignoring pixfmt->stdpixfmt) already in the system,
and if so, it uses the already existing one and does not create a new one.
In theory it would be better if gfx drivers could simply/only specify a StdPixFmt without all the shifts/masks stuff when the
gfx driver uses pixfmt which matches one of the stdpixfmts exactly. Another possibility would be for gfx drivers to use
HIDD_Gfx_GetPIxFmt(stdpixfmt_gfx_driver_wants_to_use) and then peek shifts/masks from it and fill out a pixfmt
tag list based on that.
15bit very blue/green: Try to pass same shifts/masks/etc. as in 16 bit pixfmt (maybe you think it's using 15 bit R5G5B5
(or swapped) but it's actually still using 16 bit R5G6B5 (or swapped).
aHidd_PixFmt_StdPixFmt you pass is mostly ignored. It's the shift/masks/etc. that count.
But I would still pass the correct one (_LE) == whatever rom/hidds/graphics/stdpixfmts_??.h uses
in the entry where you have looked up shifts/masks/etc.
Use the shifts/masks/etc. from the entry in stdpixfmt_le.h (if you are running on little endian machine) or stdpixfmt_be.h (if you
are running on little endian machine) that matches the pixfmt that its meant to be.
0xAA,0xRR,0xGG,0xBB on little endian (->entry in stdpixfmt_le.h which says vHidd_StdPixFmt_ARGB32)
0xBB,0xGG,0xRR,0xAA on little endian (->entry in stdpixfmt_le.h which says vHidd_StdPixFmt_BGRA32)
0xAA,0xRR,0xGG,0xBB on big endian (->entry in stdpixfmt_be.h which says vHidd_StdPixFmt_ARGB32)
0xBB,0xGG,0xRR,0xAA on big endian (->entry in stdpixfmt_be.h which says vHidd_StdPixFmt_BGRA32)
it feels like AROS trashes the alpha component, otherwise it should be 8A8R8G8B.
read on the subject suggest its in 1x5r5g5b (x is ignored) to keep 16bit alignment .
Suggests to me that wrong shift/mask are being applied - however going by the 16bit versions it all looks correct to me so I am really confused as to what is happening.
The output image looks to have too much green/blue, and very weak red.
Kickstart
The idea is to minimize amount of archirecture-specific modules to make the user's life easier. So, the kickstart was split into 'base' (which does not contain anything machine-specific) and 'BSP' (Board Support Package) which contains all hardware-specific stuff. This way, for example, distribution makers can save up space on CD and make CDs with multiple platform support. Different configuration would load the same base with different BSP's.
Next there was some part which is entirely missing on hosted. These are filesystems. Hosted ports do not need them to boot up, so on hosted they are left out. At the other hand, they are also architecture-agnostic. So i put them into 'FS' package (standing for 'filesystem').
USB
Poseidon is one more big part. I made it into separate package in order to allow users to omit it if they don't need it (for example, to run on retro PCs without USB). Personally i have one. Again, Poseidon is hardware-agnostic (well, there are USB drivers but HCIs are pretty standard).
AFAIK its HCI 1.0 compliant but not familiar enough with poseidons drivers, nor USB, to just hack away at the existing code. Perhaps once i'm more familiar with the workings I can merge in the changes needed to get it operating but for now I will focus on getting it running. Also our drivers have known issues so perhaps a fresh set of eyes might shed some light on what is going wrong.
Another interesting question is whether Poseidon can operate on device side. Is it flexible enough? How similar is being a USB host and USB device? think it will need a bit of work on Poseidon's side. Until then I will force the driver into Host/Master mode in the init code, but leave open device etc to configure the chipset for either's use - and look at trying to add support for working in Device/Slave mode & switching modes once it's up and running.
Actually USBROMStartup is some kind of kludge. Can there be any alternative? Could device drivers be self-installing, like our HIDDs? This would get rid of need to list them in USBRomStartup.
* Model A and B limited to 150 mA per port.
* Model B+ and Pi 2 introduced configurable 600 mA to 1.2 A support over all ports - anything above that requires a powered USB hub.
Implementing the hardware driver that Poseidon uses to interact with the USB components.
Have code in place to (try) and initialise the USB chipset, and configure host/device mode operation (though AFAICT Poseidon doesn't support device mode). Started to get the "virtual" root hub written for the single USB port so that Poseidon should at least list it correctly in the GUI - and try to interact with it to find peripherals.
The BCM2835 uses a soft IP block from Synopsys’ DesignWare library (DWC), specifically the block is called dwc_usb_2_0_hs_otg_subsystem-ahb_se (“USB 2.0 Hi-Speed OTG Controller Subsystem w/AHB Interface SE”).
There is no public documentation for this, and pretty much zero chance of anyone getting hold of it even with NDA. However, there's a Linux driver written by Synopsys ([https://github.com/raspberrypi/linux dwc_usb]). Specifically directories [https://github.com/raspberrypi/linux/tree/rpi-patches/drivers/usb/host dwc_common_port] and [https://github.com/raspberrypi/linux/tree/rpi-patches/drivers/usb/host dwc_otg].
The Synopsys code is actually under a fairly permissive licence – it's not GPL, it's similar to BSD (’don't sue us if it breaks’ is pretty much the only clause). So this should not be a barrier to porting the code.
The code is really well written, with a nice partition between the work done by the driver (dwc_otg, which is fairly involved, given the host does more work than a conventional EHCI driver), and the interface to Linux (dwc_common_port).
Probably only need provision of relevant changes to dwc_common_port. Other things to consider....
* Provision of necessary headers to get it to compile
* Provision of necessary functions (main issues are wait queues, threads, work queues, tasklets, timers, spinlocks and mutexes (multithreading) )
* Interfacing between USB stack and the driver. dwc_otg/dwc_otg_hcd_linux.c looks like the place to start.
the Linux bits of the headers are only required for the dwc_common_port library. dwc_common_port includes a variety of crypto functions which are not used – it appears to also be used for ultrawideband (UWB) and wireless USB (WUSB) drivers where crypto will be an issue, but it isn't going to be for plain wired USB.
Every USB driver acts as an USB hub as well in order to let Poseidon control the state of USB ports. The code there was reading status of the only USB port in Raspberry's CPU but when changing the status it erroneously deleted some of the status bits, including the port enable one. It was so because those bits in the status register are of a type Read/WriteToClear. It means, if one does not want to change their value from 1 back to 0, one has to actually write the 0 value. Very practical thing e.g. in interrupt handlers, where one reads the interrupt status register to learn what was the interrupt reason, and writes it back to the same register in order to clear the interrupts.
After fixing that code it turned out that the communication was still unsuccessful. Apparently the USB device was not understanding the host for some reason. That should not happen since the request sent was one of the standard ones implemented by virtually anything with an USB connector, assumed that Poseidon clears the data caches before forwarding the work to the USB drivers but that's the responsibility of the driver itself.
The USB device responded and acknowledged the transmission! But why were all the request sent after address change failing with timeout? They should not. Once again, address set is supported just by anything. Tried to contact the device at address 0 once again and there it was, still responding properly. The enlightenment came. The bus address for DMA transmissions was, as it is in many bare metal USB implementations, just the pure memory address of the buffer as seen by the ARM cpu. Have "prefixed" it with the real location of uncached RAM and booted AROS once again.
Trident saw this:
Product : Hub: Vdr=0424/PID=9514
Manufacturer: Standard Microsystems Corp.
SerialNumber: n/a
/Users/michal/git/AROS/rom/USB/poseidon/./poseidon.library.c:psd_20_psdEnumerateDevice/3092: USBVersion: 0200
Class : 9
SubClass : 0
DevProto : 2
VendorID : 1060
ProductID : 38164
DevVers : 0200
and this:
Product : Vendor: Vdr=0424/PID=EC00
Manufacturer: Standard Microsystems Corp.
SerialNumber: n/a
/Users/michal/git/AROS/rom/USB/poseidon/./poseidon.library.c:psd_20_psdEnumerateDevice/3092: USBVersion: 0200
Class : 255
SubClass : 0
DevProto : 1
VendorID : 1060
ProductID : 60416
DevVers : 0200
and even this:
Product : Hub: Vdr=0424/PID=9514
Manufacturer: Standard Microsystems Corp.
SerialNumber: n/a
/Users/michal/git/AROS/rom/USB/poseidon/./poseidon.library.c:psd_20_psdEnumerateDevice/3092: USBVersion: 0200
Class : 9
SubClass : 0
DevProto : 2
VendorID : 1060
ProductID : 38164
DevVers : 0200
What are these things? The first one is USB hub built in the Raspberry. Thanks to this one the Pi machines (with exception of Pi0 and computing modules) have more than just one single USB port. The second one is the network chip in raspberry, the third one is my USB SD card reader which have just connected to see what happens. AROS tried, of course, to boot from it ;)
So, the first step towards working USB is done. The control transfers are working as you can see above. Next step is to implement bulk and interrupt transfers, having the basics in place. Finally some error handling will be added and USB for Pi will be as complete as the PC version.
[http://www.raspyfi.com/raspberry-pi-usb-audio-fix/ Issue with USB Audio]
Audio
The Pi 4B is the only Pi that can output HD Audio as an HD Audio passthrough bitstream, and it does it over HDMI. It's possible to use the two HDMI output for separate HDMI video and HDMI audio outputs to allow UHD HDR video and HD Audio with non-UHD HDR compatible AVRs.
The Pi3B+ and earlier will decode to PCM 5.1/7.1 and output over HDMI. HDMI is the only interconnect that has a standard for carrying Dolby True HD, DTS HD MA etc. as a bitstream - you can't carry it as a bitstream on any other interface.
Pi3 and Pi4 audio jack output derived from 12bit pulse width modulation is relatively poor. For better, choose USB Audio or I2C versions.
[https://github.com/raspberrypi/linux/tree/rpi-patches/sound/arm audio] and its [https://github.com/raspberrypi/firmware/issues/2 very high speed message passing interface type of thing VCHI]
The Model B+ added an additional voltage regulator for the audio output and an additional output driver to drive low-resistance loads like headphones. However it is still using pulse-width modulation (PWM), which has a major impact on sound quality
the old Raspberry Pi used a linear voltage regulator to provide the 3.3V to many of the components on the board while the new one uses a switching regulator. Both can perform reasonably well. However switch mode power supplies often show higher noise figures
Analogue audio
Audio over HDMI rev 1.3 & 1.4
Ethernet
10/100 BaseT Ethernet RJ45 socket
GPIO
GPIO shouldn't be too bad but bear in mind it is already accessed in places so they would need to allocate pins etc through it (e.g. sdcard to flicker the activity light, serial debug to output data on the GPIO pins)
Probably a resource rather than a device...
Started an i2c driver that will need to allocate GPIO pins. Feel free to work on it if you are interested ;p
GPU graphics with 2D and 3D acceleration
Sadly none yet for 32bit but for 64bit...
Miscellanous
hdmi issues
Setting the hdmi_force_hotplug=1 makes sure the Pi believes the monitor/TV is really there.
You might also need to set config_hdmi_boost=4 or even higher (up to 9) if your display needs a stronger signal.
If the display is a computer monitor or newer tv, use hdmi_group=1 (auto HDMI use) and if it is an older TV, try hdmi_group=2 (for DMT formats, i.e. for PC monitors) then you HAVE to "set hdmi_drive = 2 to enable HDMI output as this forces HDMI mode rather than DVI mode
Do not set hdmi_safe=1 as that overrides many of the previous options.
Using a shorter or better quality HDMI cable might help. Make sure your Pi's power supply delivers 1 A and not 500 mA.
If you see a problem with the red colour - either absent, or interference - then try a boost
composite video
changing the RCA cable, then the composite port worked out of the box
Boot it as you are doing, without HDMI. If you now plug in the HDMI, do you get the image? In other words, does the Pi think HDMI is connected even when it isn't?
Rename all the files in the first partion of the card except bootcode.bin, start.elf and fixup.dat What's the result?
Put back config.txt What's the result?
for PAL mode sdtv_mode=2
dmi_ignore_hotplug Pretends HDMI hotplug signal is not asserted so it appears a HDMI display is not attached
hdmi_ignore_hotplug=1 Use composite mode even if HDMI monitor is detected
<pre>
# NOOBS Auto-generated Settings:
#hdmi_force_hotplug=1
#config_hdmi_boost=4
#overscan_left=24
#overscan_right=24
#overscan_top=16
#overscan_bottom=16
#disable_overscan=0
start_x=1
gpu_mem=128
</pre>
tvservice -c "PAL 4:3"
<pre>
/opt/vc/bin/tvservice -s or tvservice -s
state: HPD high|HDMI mode|HDCP off|composite off (0x12001a), 1920x1080 @ 60 Hz, progressive
/opt/vc/bin/tvservice -m CEA
Group CEA has 1 modes:
(native) mode 16: 1920x1080 @ 60 Hz, progressive
/opt/vc/bin/tvservice -m DMT
Group DMT has 0 modes:
</pre>
sudo amixer cset numid=3 1
forces the audio to the headphone jack, even with the HDMI video output plugged in
config.txt
the hdmi_ignore_edid_audio=1 option sems relevant as it should tell ALSA that the only available audio is analog, no matter what the display says
There are several different ways that these 4 pole (ring) composite analog cables can be wired up, so some work great in some applications and can be a waste of time in others.
What is needed for the Raspberry Pi B+ and above, which like many camcorders needs the ring contact next to the base contact to be the ground.
The wiring for the 4 pole are:
TIP (LEFT AUDIO CHANNEL)
RING 1 (RIGHT AUDIO CHANNEL)
RING 2 (GROUND/EARTH)
RING 3 BASE/SLEEVE (VIDEO) YELLOW
Most Apple based Players and the Microsoft Zune (TM) are wired this way.
Most analogue camcorders are wired this way as well, where the ground in on Ring 2 will work with the Pi although you may need to swap your Video plug with the Right Audio plug.
Nearly all other MP3 players are not wired this way, the ground is on another ring ie the wrong one.
External devices
* Camera Module Omnivision ov5647 Sunny 5MP (NoIR version) V1.3 - NoIR at 850 nm, peak at 880 nm and trails off at 940 nm wavelengths
* Camera V2 Sony IMX219 V2.1 8mpixel 8MP 8megapixel - 3280 x 2464 pixels - video at 1080p30, 720p60 and 640x480p90 - wider field of view, 62 vs 54 degrees horizontally -
* Branded WIFI usb BCM43143 dongle
N.B. dreaded error after changing cameras (stupidly without turning off the power first) and lasted through several power cycles. It can be a bad 15-pin FFC ribbon cable, when swapped, camera(s) and the Pi itself are working OK. It can be an instance of a cold solder joint on the CSI connector on the pi board. the camera can be detected (that's done via I2C) but may still not be able to receive image data (done via CSI-2) if something is broken. CSI-2 is uni-directional. Control is generally done via I2C.
The CSI-2 receiver always writes to memory, not direct to the ISP. That's the way the Broadcom architecture works as it allows multipass processing easily. GPU memory is accessible from the ARM. Processing using the QPU graphics processors may be possible. currently the only supported sensor is OV5647 and IMX219. The linux drivers are all in the firmware blob, else you'd be looking at at least a man-month of work in a fully fledged imaging lab to do a decent tuning of the camera modules' ISP parameters.
Static electricity maybe an issue for the camera module and slightly less for the pi board.
== References ==
===Good sites to visit===
*[https://github.com/raspberrypi/firmware/tree/master/ Raspberry Pi Firmware build]
*[https://www.raspberrypi.com/documentation/computers/software-sources.html Documentation]
*[https://rpilocator.com/ RPiLocator]
Linux only
*[https://github.com/raspberrypi/linux Raspberry Pi Linux Build]
*[https://dietpi.com/ DietPi]
*[http://www.tinycorelinux.net/ports.html piCore]
*[https://wiki.alpinelinux.org/wiki/Raspberry_Pi Alpine Linux]
*[https://github.com/armbian/build Armbian]
*[ FydeOS]
*[ TwisterOS based on ChromiumOS]
*[https://note.com/jamesmondo/n/nc76e31402be8?hl=en BSD]
*[https://www.raspberrypi.com/software/operating-systems/ PiOS Lite] and then [https://hstwb.firstrealize.com/ HST]
*[ PiMiga for pi4 and pi5]
*[ amibian for pi2 and pi3]
*[ retropie pi1 and 2]
Other alternative lighter smaller than Pi OS
*[https://aros.sourceforge.io/nightly1.html Aros 64bit ARMV8 single core]
*[https://www.riscosopen.org/wiki/documentation/show/Welcome%20to%20RISC%20OS%20Pi RiscOS on Pi3 and Pi4]
*[https://github.com/michalsc/Emu68 ARM based realtime JIT 68k for amiga computers]
*[https://github.com/JJDSNT/bellatrix/releases/ Alternative use of Emu68 on Pi3b]
*[https://github.com/stevereaver/uaos uaOS with Emu68k]
*[https://github.com/aros-development-team/AROS/commit/f80a268607dfae81b2db94755ab4e4d31ccb72d6 m68kemu library reference]
*[ HaikuOS]
*[https://github.com/raspberrypi/noobs NOOBS] os loader with successor [https://github.com/procount/pinn PINN]
*[https://github.com/maxnet/berryboot berryboot]
*[https://github.com/brianwiddas/pi-baremetal Bare Metal Access on Pi 32bit]
Testing procedure is put sd card in, connect board to board if necessary, plug in hdmi and then power nothing else is done especially CSI DSI etc
[https://www.raspberrypi.com/documentation/computers/compute-module.html CM5] has the same 55mm x 40mm 2x100pin connectors form factor as the CM4 but [https://www.epdtonthenet.net/article/214508/Key-Considerations-When-Migrating-from-Raspberry-Pi-CM4-to-CM5.aspx some pins and other small things] have changed. Will need the [https://raspipcb.com/tech-blog/raspberry-pi-cm4-vs-cm5-difference-in-booting-from-sd-card/ right IO board to suit]
*Green [ Raspberry Pi Compute Module 5 IO Board REV2 [https://pip.raspberrypi.com/categories/1097-raspberry-pi-compute-module-5-io-board SC1967]] - untested
*Green [ RPi Compute Module 5 IO board REV1 [https://pip.raspberrypi.com/categories/1097-raspberry-pi-compute-module-5-io-board SC1751]] - untested
*Black SupTronics Geekbord X1500 CM5 IO Carrier Board - untested
*Black DeskPi Super6C Cluster Mini-ITX Board - untested
*[https://sipeed.com/nanocluster Sipeed NanoCluster] - untested up to 7 CM5
*Green BentoIO CMX0 - untested
*Box EDATec ED-CLAWBOX - untested
*Home Assistant Yellow - Kit with PoE with Raspberry Pi Compute Module 5 - untested
*Blue [https://www.waveshare.com/wiki/CM5_PoE_BASE_A Waveshare CM5-PoE-BASE-A] - untested
*Box Waveshare [ CM5-POE-BOX-A] - untested
*Blue [https://www.waveshare.com/wiki/CM5-IO-BASE-B Waveshare CM5-IO-BASE-B] - untested
*Blue [https://www.waveshare.com/wiki/CM5-IO-BASE-A Waveshare CM5-IO-BASE-A] - untested
*Blue Waveshare [https://www.waveshare.com/wiki/CM5-NANO-B CM5-NANO-B] - untested
*[https://carboncomputers.us/products/pi-flux piFlux]
*[https://carboncomputers.us/products/ Zitaotech Hackberry] CM5 lite only -
*Portable [https://www.waveshare.com/pocketterm35.htm Waveshare PocketTerm35] with Pi4B or Pi5 - untested
*Box [https://www.clockworkpi.com/uconsole ClockworkPi uConsole][https://www.youtube.com/watch?v=EtI_bAahbR8 CM4 into an adapter or CM3 into so-dimm - Cyberdeck] - untested
*Green RPi [https://datasheets.raspberrypi.com/cm4io/CM4IO-KiCAD.zip Compute Module 4] [https://datasheets.raspberrypi.com/cm4io/cm4io-datasheet.pdf IO board] V1.4 [https://datasheets.raspberrypi.com/cm4io/CM4IOUSB3-KiCAD.zip USB3] [https://datasheets.raspberrypi.com/cm4io/cm4iousb3-appnote.pdf CM4ISO] [https://datasheets.raspberrypi.com/cm4/cm4-datasheet.pdf Dual100pin] (2020) aka Development Platform Board - untested
*Purple Pi Hut Cytron CM4 Maker Board - untested
*Black DeskPi Super6C Cluster Mini-ITX Board - untested
*[ KubeSail PiBox mini 2]
*Home Assistant Yellow with Raspberry Pi Compute Module 4 - untested
*[ Turing Pi V2] - untested CM4 with 260-pin SO-DIMM socket adapters and/or nvidia jetson nanos - untested
*Blue [https://www.waveshare.com/wiki/CM4-IO-BASE-C Waveshare CM4-IO-BASE-C] - untested but binary blobs Rev01 Rev02
*Blue [https://www.waveshare.com/wiki/CM4-IO-BASE-B Waveshare CM4-IO-BASE-B] - untested but binary blobs
*Blue [https://www.waveshare.com/wiki/CM4-IO-BASE-A Waveshare CM4-IO-BASE-A] - untested but binary blobs
*Blue [https://www.waveshare.com/wiki/CM4-NANO-B Waveshare CM4-NANO] - untested but usb and audio turned off or rerouted
*Black [ Seeed Studio with BigTreeTech BTT pad 7] - bin blobs?
CM3 has a 200 pin sodimm ddr2 connector form factor but not electrically SC0028, SC0029
*Blue [https://wiki.geekworm.com/CM_IO_Board Geekworm RPi Compute Module IO Board] [https://github.com/geekworm-com/cm-io-board CSI DSI] with CM3 in ddr2 slot underside - '''works''' if SW1 on but CM3+ '''does not'''
*Green [https://cdn-shop.adafruit.com/product-files/3442/CMIO_schematic.pdf RPi V3 IO board CM3IO] and CM3 Lite - untested
*Green [https://turingpi.com/ turingpi v1 cluster] - untested up to 7 cm3 7xlan9514 12V discontinued, 3 x Pi4 homelab maybe better
*Blue [https://www.waveshare.com/wiki/Compute_Module_PoE_Board Waveshare Compute Module PoE Board] and CM3 lite (if not lite, write files to internal eMMC fat32) '''AVOID''' bin blobs
*Blue [https://www.waveshare.com/compute-module-io-board-plus.htm Waveshare Compute Module IO Board Plus] [https://www.waveshare.com/wiki/Compute_Module_IO_Board_Plus wiki] [https://forums.raspberrypi.com/viewtopic.php?t=235695 pin settings] with CM3+ Lite - '''AVOID''' binary blob
*[ Pi02w on Geekworm SupTronics X305 Raspberry Pi Zero IO Baseboard] - untested
*[ Spotpear Pi Zero 2w to Pi3b format-ish] - untested
*[ pi-top v4] box has 128x64 oled display, micro hdmi, 19Whr battery with pi4 and 15V PD 36W min needed
*[ pi-top v3] three green pieces, heatsink covers most of the base tray, pi-top hub mk1 lhs and Pi1B Pi2b Pi3b rhs secured from below, black rounded strip with pi-top above keyboard, 13.3" HD 1366 x 768 display, small touchpad,
*[ pi-top Model 2.0] pi-top on bottom bezel of 14-inch green laptop, large trackpad, keyboard slide down to reveal main system hub on slide rails moved to the right, Raspberry Pi3b screws down, hub slides in, 18V 2.5A 45W charger brick, battery 11.1V 3500mAh 38.85Wh and storage PiTopOS
*[ Pi-Top CEED Raspberry Pi Modular Educational Desktop with RPI3] monitor
*[https://www.indiegogo.com/en/projects/jesselozano/pi-top-a-raspberry-pi-laptop-you-build-yourself Pi-Top v1] wedge laptop with RPi2
<pre>
2008 Trustees collected for Foundation
2009 Pi Foundation charity status gained
2010
2011 First Raspberry prototypes
2012 First boards go on sale at CPC and RS. The Model A and B 700 MHz Arm11 - February 29th BCM 2835
2012 First million sold - more than the 10,000 original planned and anticipated
2013 First Alpha Experimental builds of AROS Native for the 32bit Pi
2013 Pi Trading launched making grants available, providing in house educational resources and Pi Academy for teacher training
2013 Over two million sold
2014 Over three million sold
2014 Pi 1 Model B+ introduced that moved composite video to audio jack and same half gig of memory
2014 Pi Model A+ v1.1 no ethernet and 1 usb - a little smaller -
2015 Over four million first gen pis sold
2015 Pi Zero 1.2 BCM2835 first production revision released with no camera port
2016 Pi0 1.3 released with camera csi connector
2017 Pi Zero W v1.1 1GHz Pi0W, single-core 32bit CPU BCM2835 released with Cypress CYW43438 wireless
2020 Raspberry Pi Pico SC0919 with RP2040 32-bit 2Core ARM Cortex-M0+ up to 133 MHz - 264KB of SRAM and 2MB of on-board QSPI Flash -
2024 Raspberry Pi Pico 2 with RP2350 2Core 32bit Arm Cortex-M33 and 2core open-hardware [https://github.com/wren6991/hazard3 Hazard3 RISC-V]
2015 Pi 2 Model B v1.1 BCM2836 900/600 MHz ARM Cortex-A7 Armv7 quad 32bit, 32bit VideoCore IV GPU - 1Gb RAM - 5V 2A micro usb - SMSC LAN9514 chip -
2015 Over a million pi2s sold
2015 Raspberry Pi 2 Model B version 1.2 Pi2bv1.2, aka Pi2B2 has armv8 BCM2837 underclocked to 900Mhz without wifi/bluetooth module
2016 Pi 3 Model B - Broadcom BCM2837 SOC four 64bit ARMv8 Cortex-A53 1.2GHz 32bit 1080p VideoCore IV GPU - 1Gb DDR2 - bluetooth 4.1, Cypress CYW43438 wireless 802.11n - 4 x USB2.0 ports - 5.1V 2.5A - SMSC LAN9514 chip
2016 PIs total over 10 million worldwide
2017 Compute Module 3 CM3 with BCM2837B0 armv8 Quad 64-bit - small 67.6mm x 31mm board which fits DDR2 SODIMM connector but not electrically compatible which plugs into needed IO board - beware of the I2C protocol issue
1Gb LPDDR2 RAM - Lite or 4Gb Emmc storage
2017 12 million pis sold in total
2018 Pi 3 Model B+ - 4c A53 BCM2837B0 1.4Ghz - 1Gb, wireless 802.11ac, gigabit ethernet (300Mbit/s) and bluetooth 4.2 - power over ethernet - 4 x USB2.0 ports - Microchip LAN7515 chip
2019 Over 15 million sold
2019 Pi 3 Model A+ with BCM2837b0 Cortex-A53 64-bit SoC @ 1.4 GHz with 512Mb LPDDR2, 1 usb2, 1 hdmi, 1 micro usb 5V 2A - no ethernet -
2019 Raspberry Pi Compute Module 3+ CM3+ - Broadcom BCM2837B0 1.2Ghz, Cortex-A53 (ARMv8) 64-bit SoC on DDR2 SODIMM mechanically compatible only factor - IO board required
1Gb DDR2 and 8GB, 16GB, 32GB or a Lite variant without eMMC
2021 Pi zero 2 (w or no W) RP3A0 quad 1GHz Cortex-A53 64bit BCM2710A1 512mB SDRam
2025 edaTEC CM0 ED-CM0NANA with additional dev board with quad 1Ghz A53 with 512Mb Raysan RAM, 2 USB2 and 10/100 ethernet - pico castellated edge
2019 Pi 4 Model B RPI4B - BCM2711B0T quad 64bit A72 1.5GHz, 4K VideoCore VI, AC wifi, Bluetooth 5.0, GbE Broadcom BCM54213PE (PHY ID 0x600d84a2), 2 micro hdmi decode up to 4K, USB-C 5.1V 3A power, 2xVLI VL805 USB 3, 2xUSB 2.0, 2GB 9LDWW D9WHZ or 4GB 9FDWW D9WHV, 8GB 0AA47 D9ZCL ddr4 ram
2020 Silent Pi 4 v1.2 upgrade with more USB-c psu support
2020 PI400 BCM2711C0T 1.8GHz 4Gb DDR4 inside keyboard, 5.1V 5A 27W usb-c psu, 2 micro hdmi, external ide style 40pin gpio, no audio port -
2020 Raspberry Pi Compute Module 4 BCM2711B0T on new 55mm x 40mm 2x100 pin form factor with extra breakout IO board
CM4101000 1Gb RAM Lite SOM
CM4102000 2GB RAM Lite
CM4104000 4GB RAM Lite
CM4004008-4GB-RAM 8GB-EMMC SOM System on Modules
CM4104032 4GB RAM 32GB emmc
CM4108000 8GB RAM Lite
CM4008016 8GB RAM 16Gb eMMc
2021 Raspberry Pi SC0763 Compute Module 4S CM4S with ddr2 sodimm pinouts but not electrically the same with suitable IO board extra cost -
CM4S01000 1GB RAM Lite
CM4S01008 1GB RAM 8GB eMMC Flash
CM4S02000 2GB RAM Lite
CM4S04000 4GB RAM Lite
CM4S04016 4GB RAM 16Gb KLMAG1JETD-B041
CM4S08000 8GB RAM Lite
2021 Pi 4 v1.4 BCM2711B1 upgraded power regulator, to deal with 8gig of ram being more power hungry -
2021-48 Raspberry Pi 4 model B v1.5 2GB
2023 Pi 5 v1.0 BCM2712 Quad A76 @2.4Ghz - VideoCore VII - no audio socket - dual 4k from mini hdmi - fan connector - 5.1V 5A psu
2024 Pi 5 2GB DDR4 version uses BCM2712D0
2024 Pi-500 with 8Gb LPDDR5 and membrane keyboard
2024 Pi 5 v1.1
2024 Raspberry Pi Compute Module 5 CM5 BCM2712 55mm x 40mm form factor with additional IO board
CM5004000 04GB RAM 0GB eMMC Lite
CM5008000 08GB RAM 0GB eMMC Lite
CM5016000 16GB RAM 0GB eMMC Lite
2025 Pi-500+ with 256GB NVMe storage, 16GB LPDDR4 RAM, and Gateron KS-33 Low Profile Blue mechanical keyboard switches
2025 Pi5 1GB DDR4 announced
2022 PiOS linux goes 64bit
2024 Pi Trading IPO stockmarket stock exchange listing
2026 April and May Aros 64bit fixed, added AHI audio, VC4 gfx started, usb functions added to rom
2026 June and July Aros 64bit usb2otg started, dma.resource, sdio.resource, bwfm.device wifi added
2026 Late July daily 64bit Pi3 LE little endian builds start
2026 August Pi 4, 400, 5 and 500 DTBs added, expanding existing support and wifi for Pi4 and Pi5
2026 August Pi5 HAT+ nvme and HDMI, AHI RPiI2S added, Pi4 HVS5 video scaler started,
2026
2027
2028 Pi 6
</pre>
The vcgencmd can be used to inspect and dump the current system configuration.
vcgencmd runs on top of VCHIQ as an RPC. The mailbox interface is an alternate but much simpler RPC.
VCHIQ is a bridge (queue) between the CPU and the GPU so they can communicate with the firmware.
Loads of [https://github.com/6by9/rpi3-gpiovirtbuf/blob/master/rpi3-gpiovirtbuf.c mailbox] which uses the GPIO control calls. [https://github.com/raspberrypi/firmware/wiki/Mailboxes may also be of interest]
A fair number of vcgencmd examples (search for vc_vchi_gencmd_init). [https://www.raspberrypi.org/forums/viewtopic.php?t=229203#p1406112 sends the relevant vcgencmd commands] to update the scaling kernel, but the [https://github.com/raspberrypi/userland/blob/master/host_applications/linux/apps/gencmd/gencmd.c command] is just a text string. Parsing and execution of the instructions is performed by the VideoCore firmware.
The Raspberry Pi runs two separate operating systems: Linux/Aros on the ARM, and a threedx RTOS called vcos running on the Videocore 4 VPU: vcos is commonly called "the firmware". Vcos is tasked with performing certain system services, for example running the display and audio outputs. The VCHI driver provides an interface to allow drivers to talk to vcos.
Doubtful, on any [https://www.web3d.org/ Web3d] [https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API WebGL] or [https://github.com/immersive-web/webxr WebXR] [https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API Device API] [https://developer.mozilla.org/en-US/docs/Web/API/XRInputSource XRInputSource] support. Hopefully, never/limited support features like location, peer-to-peer, invasive web apps, unwarranted storage, payments, proprietary video streaming etc
*spreadsheet [https://git.sheetjs.com/sheetjs/sheetjs sheetjs] [https://github.com/mleibman/SlickGrid SlickGrid] [https://github.com/6pac/SlickGrid SlickGrid] [https://github.com/jspreadsheet/ce jspreadsheet ce] [https://github.com/dream-num/Luckysheet Luckysheet] [https://github.com/ruilisi/fortune-sheet fortune-sheet] [https://github.com/dream-num/univer/ univer] probably without xlsx support
*presentations [https://github.com/impress/impress.js/ impress.js simplified] [https://github.com/bwlewis/slides slides] [https://zenomt.github.io/mdslides/ github markdown slides] [https://github.com/Patternslib/slides Patternslib slides markdown] probably without pptx support
*weather [https://github.com/kaushalsahu07/weather weather], [https://github.com/Himanshu3412/Weather-Forecast Weather Forecast],
==Future==
[https://github.com/ARMSX2/ARMSX2 Arm pi of pcsx2]
[https://tube.cadence.moe/ Cloudtube], [https://github.com/TeamPiped/documentation/blob/main/content/docs/public-instances/index.md TeamPiped], [], [], [],
[https://hyperpipe.codeberg.page/ hyperpipe], [https://ytify.pp.ua/ ytify], [], [],
[ ytdl], [https://github.com/golddominik893/liberatube liberatube]
[https://git.lolcat.ca/lolcat/4get 4get], [https://github.com/hnhx/librex librex], [], [],
{{BookCat}}
1frsem3cu8sabhhf1lc9uopczvcge67
4676024
4675837
2026-10-14T11:34:18Z
Jeff1138
301139
4676024
wikitext
text/x-wiki
{{ArosNav}}
[[#Native]]
[[#Hosted]]
[[#Build]]
[[#Hardware]]
[[#References]]
[[#Future]]
==Introduction==
[[File:Scalos00.png|thumb|Scalos on Aros Pi3b]]
Aros aims to cover Pi 3 to 5 512Mb+ RAM
Options to boot from using a good power source to prevent the yellow lightning symbol.
*With Pi3b+ the max you can get is 5.1V 2.5A with micro usb.
*With Pi4 5.1V 3A with usb-c
*With Pi5 5.1V 5A, the amps went ever upwards, even to 5.1V 9A with usb-c
* Pi500+ keyboard wedge - working
* Pi500 wedge with up to date bootloader via PiOS - working
* Pi 5 - Quad A76 64bit ARMv8 and RP1 "southbridge" with VideoCore 7 D0 (rev1.1) - untested
* Pi 5 - Quad A76 64bit ARMv8 and RP1 "southbridge" with VideoCore 7 Pre-D0 C1 (Rev1.0) - untested
* Pi400 RPI-400 keyboard wedge - resolution changing and audio from micro hdmi0 (near 40pin) and micro hdmi1 (near usb-c psu) - Fn F10 0x5e power on and off works or held down for over 7 seconds auto shutdown - keyboard ok - wifi and lan ethernet testing -
* Pi 4 - Quad A72 64bit ARMv8 with VideoCore 6
* Pi 3 - Quad A53 [https://www.raspberrypi.com/documentation/computers/processors.html 64 bit] ARMv8 with VideoCore 4 with '''fan''' to prevent overheating cpu 82C+ throttling
* Pi02W - Quad A53 64bit - boots but [https://forums.raspberrypi.com/viewtopic.php?p=2387984#p2387984 usb not working but did in the past],
* Pi 2 - Quad 32bit ARMv6 with VideoCore 4 - mostly not 64bit compatible
* Pi Model B+ 32bit ARMv6 with VideoCore 4 - not 64bit compatible
* Pi Model A and B 32bit ARMv6 with VideoCore 4 - not 64bit compatible
===Native===
* 2013-03 Kalamatee starts work
* 2015-04 Work continues with mschulz on the kernel and Kalamatee (NicJA) on gpio and usb
* 2018 [https://www.patreon.com/posts/i-owe-you-some-20956961 mschulz resume adding BE big endian support], [https://www.patreon.com/michal_schulz/posts Big endian on Pi]
* 2026 [https://github.com/aros-development-team/AROS/commits?author=bsek latest commits for pi 3b, 4 and 5 64bit]
* 2026 [https://github.com/aros-development-team/AROS/commits?author=metaneutrons latest commits for Pi5]
* 2026 [https://github.com/aros-development-team/AROS/commits?author=bitplane latest commits for ARM]
====64bit====
'''Download''' A [https://archive.org/details/piAROS Pi Distribution (Distro) has started] and the contents copied to fat32 8GB+ microSD card (there will be drawers/folders - boot c Classes Demos Developer Devs Extras etc only showing). The SD can be plugged in to the Pi. And power on. [https://pi.amiga.icu/ Repository]
[https://aros.sourceforge.io/nightly1.html RaspberryPi 3, 3+, 4 and 5 64bit ArmV8 nightly builds] [https://sourceforge.net/projects/aros/files/ Alternative site and nightly2] which is a test beta limited apps version with both raspi-aarch64-system and raspi-aarch64-contrib can be unbz2'd to a SD or SSD as appropriate.
64bit build works well on a single core LE little endian. Multicore [https://github.com/aros-development-team/AROS/commit/1df0747c2bda3523a43029725a709b1f377d84ec may follow]. Any issues booting could be down to the SD card so please use another SD to see if it is resolved. Remember Aros Arm uses FAT32 and Aros can detect issues with this format very acutely (once fault found, FAT 0x0FFFFFF7 bad cluster so no files written after that, no repair). Please report your experiences in the [https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2138&pid=15057#post_15057 Aros forum thread], [https://forums.raspberrypi.com/viewforum.php?f=179 Raspberry Pi Aros Dev and User forums], [https://forums.raspberrypi.com/viewtopic.php?p=2387984#p2387984 previous Raspberry Pi forum thread]. Any bugs or issues can be [https://github.com/aros-development-team/AROS/issues described here to fix]
Boots with '''USB3''' port based sata3 ssd on Pi400 but untested on Pi4 (may need eeprom update from PiOS or Pi SD Imager) and Pi5
Pi 3 B+ is pre-configured for USB sata3 boot - untested
Pi 3 B may need [https://www.youtube.com/watch?v=ubnwvxF3Klc PiOS to set OTP to boot from usb - do so at your own risk] - if OTP set to usb, boot works but slower than SD card
Speed write wise (top faster)
<pre>
*NVME Pi5 untested >1000MB/sec or faster if matched correctly
*Sata3 ssd 500MB/sec
*SD V90 90MB/sec 4K maybe 8K
*SD V60 60MB/sec 1080p
*SD U3 V30 30MB/sec 720p
*SD C10 U1 V10 A1 A2 10MB/sec minimum should be used now
*SD C06 6MB/sec
*SD C04 4MB/sec
</pre>
As a homage to the past, Aros shows a reduced number of icons but this can be changed by left mouse click in the window and then right click down to Window -> View -> All files
Windows can be manipulated by the top (moving) and the bottom right corner (resizing) only.
Zune like MUI gui interface, has a unique quirk in that after changing a setting in a text box, you may sometimes need to press Enter/Return before clicking OK, Save, etc
Double left mouse click on most picture (Developer/Debug/Tests/Datatypes), audio and video files are supported, via datatypes, by the multiview application.
Esc escape key usually closes open windows even the desktop
In Prefs/Appearance some decorative theming elements need work. There is a few Mason icons in /Prefs/Presets/Icons/Mason/ and the ever present default Gorilla - Icon exchange in works
For more intensive graphics applications, you may need to edit config.txt in the root folder and change 128M to 256M to adjust more memory to graphics usage
If your cursor should '''appear''' to vanish, fear not it is still there. Please head to the top of the screen i.e. the title bar, hold down the left click mouse and drag the screen down a little and the cursor will appear again. Then you can drag the screen up again.
Like most amiga like OSs the audio and networking need to be setup manually
Audio AHI prefs - Mode settings tab - needs both Music unit and Unit 0 set to RPiHDMI:16 bit stereo++ or RPiPWM:16 bit stereo++ at 44100Hz. Press '''Save or Use''' button after each choice
For wireless, please use the Wifi prefs and already selected device bwfm.device. Press Scan and double right click on the router and enter password. You may need to setup after every power off
*if asking for password again - press cancel and go to Network Prefs, Wireless Networks tab and highlight the router line and hit the remove button and press the cancel button. Retry with Wifi prefs again
*...waiting for an address - Disconnect and try Connect
Until, Connected to <router> - 192.168.x.x
For lan ethernet port, please use Network prefs and the following hardware is
*lan9514 Pi3b Pi2 not supported at the moment
*lan7515 Pi3b+ type into Device usblan78xx.device as net0: remove other device(s)
*bcmgenet Pi4 Pi400 choose for Device bcmgenet.device
* Pi5 Pi500 Pi500+ RP1 i/o
(network prefs may forget random information when rebooted)
Summary
<pre>
*3b ethernet not supported, usb ethernet not working but wifi prefs setup works
*3b+ wifi working and ethernet works
*4 untested
*400 wifi and ethernet untested
*5 wifi and ethernet untested
*500 wifi and ethernet untested
*500+ wifi works
</pre>
Type in 'aarch64' in the [https://archives.arosworld.org/index.php?function=search&tool=simple search box] and you will see available software packages / apps. apkg can be used to inspect and install applications.
[http://archives.arosworld.org/index.php?function=browse&cat=network/browser amelinium web browser (JS 1.6 ES9 ECMASCript 2018)] is available with an [https://eab.abime.net/showthread.php?t=122494&page=51 eab thread] reminiscent of [https://github.com/zapek/Voyager Voyager] and to a lesser extent [https://github.com/amigazen/aweb3/ Aweb JavaScript 1.5 (ECMAScript 3)] as css and javascript websites can be slow to load or resolve (no JIT) and nothing from facebook, reddit etc.
Press Cancel at screenmode selector or -wb argument to get windowed version. You could use the Shift + Del shortcut or mouse wheel should work to delete all text at once. To view wikibooks set Agent to Android (telefon) aka Google Chrome 126 or iPhone aka Safari 17 setting in menus. Html5test gives 189 (1.29), 300 (1.31), 311 (1.33) out of 555, some bigger Amiga like browsers are around 370+ but it does less better.
You may have to delete the cache (Menu -> Page -> Delete cache) to fully retest big Amelinium updates or free up space.
Be aware [https://pianetaamiga.it/en/reportage-pianeta-amiga-2026/ some site pages] can use up hundreds of MBs of cache very quickly
DNS lookup failed... close browser and reboot and setup wifi again - repeat until it works again
youtube video and audio - js button for javascript must be on/shaded - Settings -> Soundoutput - AHI
Usually restricted to lower resolutions due to [https://docs.invidious.io/faq/#q-where-are-the-360p480p1080p-quality-options bandwidth]. You can always [https://docs.invidious.io/installation/#install-the-dependencies self host] for better or wait for the newest version of Odyssey OWB (webkit browser).
Telegram https://t.me/s/channel_name for public messages from vamped_amiga chatamigagames demoscenecracktros
*art local js apps like dpaint.js
There is normally no Bluetooth support for most amiga like OSs but Aros has one [https://github.com/aros-development-team/AROS/commit/6942cbfbf66426d21963a7fcd8aba6aff611a9e0 work in progress] [https://forums.raspberrypi.com/viewtopic.php?t=338466 firmware]
*Bluetooth 4.1 BCM43430A1.hcd Pi3B, Pi3A, Zero 2W
*Bluetooth 4.2 BCM4345C0.hcd Pi3B+, Pi4
*Bluetooth 5.0 BCM4345C5.hcd Pi4B rev, CM4 and maybe Pi5 and CM5
<pre>
*bthid keyboard mouse support
*btserial serial
*btpan short range wireless connecting devices
</pre>
Only the Pi5 has a RTC real time clock, the other Pis will need to use ntp services [https://github.com/aros-development-team/AROS/commit/29cd4116330dc7f692d90757eacc59fb3f31ae70 sntp] with time.cloudflare.com pool.ntp.org or Cloudflare 162.159.200.1, 162.159.200.123, 2606:4700:f1::1, 2606:4700:f1::123 or [https://github.com/bohunamiga/PiNTP PiNTP -s goodtime.ijs.si or ntp1.ptb.de] to get the date and time from the internet. Can use date in a shell e.g. date 24-Dec-2026 23:59:59 but this will need to be done again after every reset/power off. Maybe [https://github.com/aros-development-team/AROS/commit/28674a157bc56175aa668e7b62dca6fa740578dc ds3231 rtc with dtoverlay=i2c-rtc,ds3231 in config.txt]
It helps to have all usb devices already plugged in before power on to detect at the moment. Even then some usb devices will freeze the mouse cursor and the only resolution is to remove the offending usb device and reinsert. Sometimes, the reinsert leads to the mouse cursor vanishing, it is still there and responds to left mouse clicks, top of the screen and pull down the screen.
USB classes support from Prefs/Trident is still work in process
*usbaudio working on usb3 port (blue) on pi4, 400 but not working (no rt isochronous) on usb2otg (white or black) for pi3b, zero 2w
*[https://aminet.net/package/mus/midi/camd camdusbmidi] detects midi devices without a preferences file (Prefs/Env-Archive/sys/midi.prefs) as [https://www.youtube.com/watch?v=RBxHkwy4Nrw auto setup now] possibly with [https://github.com/metaneutrons/mt32-pi metaneutrons mt32-pi] [https://github.com/rtzor/mt32-pi mt32-pi fork] [https://github.com/ahmadexp/mt32-pi fork] [https://github.com/gmcn42/mt32-pi-control control of] [https://github.com/dwhinham/mt32-pi mt32-pi pi3+]. Alternative of [https://homspace.nl/samplerbox/ SamplerBox].
Will need developer clang gcc tools to look at 64bit ports of [https://archives.arosworld.org/?function=showfile&file=driver/audio/usbmidi.i386-aros.lha usbmidi], [https://aminet.net/package/mus/midi/CAMD_Toolkit CAMD_Toolkit], [https://aminet.net/package/mus/midi/camdtools camdtools], [https://github.com/cnvogelg/amiditools amiditools], [https://github.com/timoinutilis/midi-sequencer-amigaos horny src], [https://aminet.net/package/mus/midi/horny-base horny-base], [http://bnp.hansfaust.de/index.html BnP], [https://arosarchives.os4depot.net/?function=showfile&file=audio/misc/timidity.lha timidity],
Regarding 680x0 emulation, there are several options (not implemented yet) that could be considered
*[https://github.com/aros-development-team/AROS/blob/6722a0ae9e03fe5d26e32703360bd2059e0864cc/rom/m68kemu/README.md?plain=1#L424 m68kemu.library] for some Amiga productivity where the cpu is emulated and the system calls are redirected to Aros ones
*[https://github.com/BlitterStudio/amiberry amiberry] (winuae) for everything else like games
*[https://github.com/jonx/AROS/tree/aarch64-darwin-graft/arch/all-darwin/libs/emu68k emu68k]
*[https://scriptedamigaemulator.net/ Scripted Amiga] with [https://github.com/naTmeg/ScriptedAmigaEmulator ScriptedAmigaEmulator] or older [https://github.com/gbraad-amiga/ScriptedAmigaEmulator2 ScriptedAmigaEmulator2]
Hopefully getting Pi3 up to 25Mhz 68040 (non JIT) and 75Mhz 68040 (JIT)
Pi4 getting up to 50Mhz 68040 (no JIT) and 150Mhz 68040 (JIT)
[https://pinout.xyz/ GPIO 40 pins] [https://learn.sparkfun.com/tutorials/raspberry-gpio/gpio-pinout pinout]
Some exceptions:
*Physical pins 27, 28 (GPIO0, 1) are an internal I2C bus and should not be used
*The other I2C on pins 3, 5 (GPIO 2, 3) can be used generally, but be aware they have permanent pull-up resistors to 3.3V
*For MIDI use USB but there are dedicated UART pins 8, 10 (GPIO 14, 15).
With a HAT it's more awkward -- you need to know which pins are used by the HAT and avoid them. Hopefully this will be documented.
Remember all GPIOs are 3.3V (not 5V tolerant), floating/noisy inputs can cause odd behavior, and that shorting the power supplies can cause instant death of the Pi.
In the shell (Cntrl + C to end)
GPIO PIN/A/N,SET/N,GET/S,MODE/K,PULL/K
Controls and queries hardware GPIO pins via gpio.resource which is stored in the rom or Devs/ '''please test'''
*PIN -- (Required) Target GPIO pin number (e.g. 12).
*SET -- Set pin output value to 0 (LOW) or 1 (HIGH).
*GET -- Read and print current digital input level (0 or 1).
*MODE -- Configure pin mode: IN (Input), OUT (Output), ALT (Alternate).
*PULL -- Configure pull resistor: NONE, UP, DOWN.
EXAMPLES
<pre>
GPIO 12 MODE OUT
GPIO 12 SET 1
GPIO 12 GET
GPIO 13 PULL UP
</pre>
[https://gpiozero.readthedocs.io/en/stable/installing.html Current] [https://gpiozero.readthedocs.io/en/v1.2.0/api_boards.html old support for gpiozero is unknown at present] [https://energenie4u.co.uk/res/pdfs/ENER314%20UM.pdf and associated 433MHz equipment] [ USA X10 security and lights via USB] [ OpenHab with Shelly Smart Plug connected over Wi-Fi, controlled by MQTT or HTTP]
Printing only with Postscript but [https://github.com/bohunamiga/MintPRINT one] of [https://github.com/boingball/MintPRINT two] [https://github.com/Andiweli/AmiAirPrint/tree/main AirPrint] IPP has been attempted with [https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2061&pid=13954#post_13954 discussion]
Youtube
[], [], [https://www.youtube.com/watch?v=X4fmWAIv7FE Aros native on Pi3b],
[], [], [https://www.youtube.com/watch?v=TSxlYb1eQWU Installed on Pi3b+],
[], [], [https://www.youtube.com/watch?v=NFF1H3jCoz8 testing Aros native on Pi400],
[], [], [https://www.youtube.com/watch?v=nIVx7mh1E1Q&pp=ygUHYXJvcyBwadIHCQkTDAGHKiGM7w%3D%3D Aros on Thumb 2 based 32bit-ish ARM STM32H743 board],
[https://www.youtube.com/watch?v=zQM4CD64xDE&t=612s&pp=ugUEEgJlbg%3D%3D Performance under Linux] but on Aros...
{| class="wikitable sortable" width="90%"
! width="10%" |Pi
! width="10%" |Single Core 2D
! width="10%" |Single Core 3D
! width="10%" |Single Core 3D
! width="10%" |SMP 2D
! width="10%" |SMP 3D
! width="10%" |SMP 3D
! width="35%" |Comments
|-
| <!--Pi-->Pi3
| <!--Single Core 2D-->
| <!--Single Core 3D-->
| <!--Single Core 3D-->
| <!--SMP 2D-->
| <!--SMP 3D-->
| <!--SMP 3D-->
| <!--Comments-->
|-
|}
==== 32bit ====
For the Pi1 Pi2 Pi2B the status of AROS native ARMv6 for 32bit RasPi was OK. System booting, USB working (although with some issues but plans to fix them). 32bit native [http://www.aros.org/nightly1.html ARMv6 32bit nightlys] raspi-armhf-system raspi-armhf-contrib unbz2'd to fat32 microSD
===Hosted===
AArch64 CPU backend for AROS, a Cocoa/Metal display, clipboard / host-volume / CoreAudio / BSD-sockets bridges, GPU 2D via gpufx.library, a 68k→AArch64 JIT (run68k), and a full Rust std port. On [https://www.jkn.me/blog/macaros-aros-on-apple-silicon/ latest Apple Silicon] [https://github.com/jonx/Macaros early buggy alpha version of hosted Aros .dmg on MacOS12+]. Please use [https://github.com/jonx/Macaros/issues MACAros github] for issues, features etc and possibly [https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2030&pid=13910#post_13910 here]
[http://www.aros.org/snapshots1.html old linux and android hosted 32bit]
==== Hosted ====
=====64bit=====
[https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2019&rowstart=80&pid=13667#post_13667 Ubuntu Linux PC hosted Pi compiler build]
[https://github.com/BlitterStudio/aros-compiler-docker Docker based cross compiler for various Aros systems],
[https://www.arosworld.org/infusions/forum/viewthread.php?thread_id=2019&rowstart=80 From the Aros Raspberry pi 3 64bit thread]
Instructions on building 64-bit Raspberry Pi AROS and cross-compiler from sources.
You will need:
- Ubuntu 24.04 or 26.04
- qemu-system-aarch64 installed
- Internet connection
- rpi-scripts.tar.gz downloaded (https://axrt.org/download/aros/rpi/rpi-scripts.tar.gz)
1) Install prerequisites:
sudo apt install git gcc g++ make gawk bison flex bzip2 netpbm autoconf automake libc6-dev liblzo2-dev libpng-dev gcc-multilib byacc python3-mako cmake yasm curl nasm
2) Clone sources
cd <project-directory>
git clone https://github.com/aros-development-team/AROS.git --recurse-submodules
3) Extract rpi-scripts.tar.gz. Copy all files into your project directory so that you have:
AROS (the directory with cloned sources)
fix-dotdot.py
rebuild.sh
recreate-sdcard.sh
run-qemu.sh
update-sdcard.sh
4) Run ./rebuild.sh. Select option 1) toolchain-core-aarch64
This will execute process of building a cross-compiler. During this process packages will be downloaded from Internet. This process can take up to 2 hours. If there are some missing dependencies, install them with 'sudo apt install' and restart this step.
5) Run ./rebuild.sh again. Select option 2) core-raspi-aarch64
This will build system files for 64-bit Raspberry Pi AROS. This process can take around an hour.
6) Run ./recreate-sdcard.sh
This will create an sdcard.img file with contents of previous step.
7) Run ./run-qemu.sh
This will start QEMU with SD card image and ROM images. It will boot into AROS.
=====32bit=====
Ubuntu VM approach to compiling [http://lallafa.de/blog/2013/06/building-aros-hosted-for-raspbian/ Linux hosted AROS June 04, 2013]
../AROS/configure --target=linux-armhf --enable-includes=/usr/arm-linux-gnueabihf/include --x-includes=/usr/arm-linux-gnueabihf/include --x-libraries=/usr/arm-linux-gnueabihf/lib
arm-elf- is symbol-linked to arm-linux-gnueabi- (arm-linux-gnueabi- is more correct in this case, because it's going to be compiling the ARM AROSBootstrap for ARM Linux)
*armel - many of the "android" machines require since the entire OS is made for soft float VFP.
*armfp - Efika MX target, Raspberry PI, EfikaMX, Pandora and virtually everything (VFP)
Keep in mind it's possible to start hardfp AROS hosted on softfp system, though, as long as no calls between AROS and host require floating point parameters. NOTE: hardfloat objects *cannot* be linked with softfloat objects - they have a different ABI.
Just keep in mind the arm nightly build machine is quite complex beast. It needs the x86_64 host compiler to compile AROS tools. The arm version is built every night using gcc-4.6.2 crosscompiler (built together with AROS) and successfully builds armel and armhf linux hosted targets.
*needs an AROS code compiler for ARM target
*as well as unix compiler for ARM linux host (would be best to have both softfp and armhf, we have softfp only now) with full set of libraries and includes.
with—disable-crosstools $AROS_CC is always a wrapper around $KERNEL_CC ? If so, this is wrong for some ports. This can break Darwin, Windows and Android port.
Yes, Android port will build. And even work. But it's not good because the port will not be ABI-compatible with other ARM ports. Android's ABI is different from GNUEABI. For example:
<pre>
enum test {foo, bar};
enum test testvar;
</pre>
sizeof(testvar) will be equal to sizeof(int) in GNUEABI (Linux and AROS) and sizeof(short) on Android. This affects linking objects from static linklibs, for example.
Previously everything worked because $AROS_CC was a wrapper on top of $HOST_CC. And a real crosscompiler was used on non-ELF hosts.
Android is the same. $KERNEL_CC is incompatible with AROS.
compiler=kernel is appropriate _ONLY FOR CODE WHICH RUNS ON HOST OS_ (or barebone hardware, if we talk about native). This includes bootstraps, their linklibs, and host-side dynamic libraries (Windows makes extensive use of them because of architectural considerations.
No single AROS object should be compiled with this setting. $KERNEL_CC is really compatible with AROS *ONLY IN LINUX-HOSTED* and no more. On other systems (Darwin, Windows, Android) this is not true any more, and compiler=kernel is never going to work.
If you want to compile your AROS module against host OS includes, append the following to USER_INCLUDES (or USER_CFLAGS, this is effectively the same):
-isystem $(GENINCDIR) $(KERNEL_INCLUDES)
$(KERNEL_INCLUDES) expands to:
-isystem <your_os_includes> -isystem <host_OS_gcc_private_includes>
-nostdinc
This makes AROS compiler adhering to host OS APIs.
If you want some preprocessor symbols based on what your host OS actually is, add something like -DHOST_OS_$(AROS_HOST_ARCH).
Why is there $(GENINCDIR) at all? Because host OS has its own libc includes, which would conflict with AROS ones. And the host OS libc is not binary-compatible with AROS one.
Why doesn't Windows-hosted port use $(KERNEL_INCLUDES) ? Because WinAPI includes conflict with AROS ones in fundamental typedefs, like WORD, BYTE and BOOL. It's almost impossible to deal with this in any other way than rewriting WinAPI definitions using AROS types.
Building under centos 6.3 (i386) currently, and AROS creates the toolchain itself. haven't yet committed the necessary changes but "./configure --target=raspi-armhf" is enough to start, then "make arosboot-raspi" will generate arosraspi.img (containing the bootstrap, kernel.resource, and exec.library) as well as arosraspi.rom (containing all the other essentials components such as dos, graphics etc). It will also copy over a config.txt file to make the raspi bootstrap code load the correct kernel, and a cmdline.txt that enables exec debug output.
*armel = typically Debian 6, Ubuntu Maverick, Android,
*armhf = typically Debian 7, Debian 8, Ubuntu Precise,
Cross-compiling Ubuntu ARM softfp
<pre>
sudo sh
echo 'foreign-architecture armel' >>/etc/dpkg/dpkg.cfg.d/multiarch
echo 'deb [arch=armel] http://ports.ubuntu.com/ precise main universe' >/etc/apt/sources.list.d/armel.list
apt-get update
apt-get install gcc-arm-linux-gnueabi libx11-dev:armel libsdl-dev:armel
</pre>
<pre>
./configure --target=linux-arm --x-includes=/usr/include \
--enable-includes=/usr/arm-linux-gnueabi/include
</pre>
Cross-compiling Ubuntu ARM hard-float
<pre>
sudo sh
echo 'foreign-architecture armhf' >>/etc/dpkg/dpkg.cfg.d/multiarch
echo 'deb [arch=armhf] http://ports.ubuntu.com/ precise main universe' >/etc/apt/sources.list.d/armhf.list
apt-get update
apt-get install gcc-arm-linux-gnueabihf libx11-dev:armhf libsdl-dev:armhf
</pre>
<pre>
./configure --target=linux-armhf --x-includes=/usr/include \
--enable-includes=/usr/arm-linux-gnueabihf/include
</pre>
Now, the AROS build is configured properly and all you need to do is:
make
==Build==
===64bit===
===32bit===
# download/checkout the source someplace, e.g. /build/AROS-Src/
# make a directory to store external sources AROS downloads, e.g. /build/Ports
# make a build directory, e.g. /build/aros-raspi-armhf
# cd into the build dir, configure, and then run make -:
<pre>
>cd /build/aros-raspi-armhf
>/build/AROS-Src/configure --target=raspberrypi-armhf --with-serial-debug --enable-ccache --with-portssources=/build/Ports
>make
>make arosboot-raspi
</pre>
then copy the files from /build/aros-raspi-armhf/bin/raspi-armhf/AROS/ onto an sdcard, and download/copy the Raspi firmware files onto it.
You should then be able to boot the sdcard on your RasPi.
The current W.I.P tree to svn. it can be built as follows ..
<pre>
./configure --target=raspi-armhf
make arosboot-raspi
</pre>
That will generate arosraspi.img, arosraspi.rom and config.txt in bin/raspi-arm/AROS - so either copy just those files to a fat formatted SD card (with the firmware files on), or copy the whole contents of the AROS folder.
NB - if you have a Linux/other install, backup the existing config.txt first
arosraspi.img contains the bootstrap (which has very basic mailbox code, framebuffer/gpio init, and console "emulation" via code pinched from our libbootconsole), kernel.resource, and exec.library
arosraspi.rom contains all the other components needed to boot AROS.
The config.txt file will tell the RasPI bootstrap to load the arosraspi kernel and ramdisk (rom).
the bootstrap has minimal mailbox code, planning on adding either a resource or library that driver/app code will use to access it (likewise for GPIO)
Help building AROS hosted on Linux ARM
Was looking a way to use more my Handheld ARM based called Pyra (Dragonbox Pyra) an ARM (Omap5 cpu with 4GB ram) linux based machine (Debian Buster v10 with kernel 5.6.19 adapted) and have a try to compile the latest Aros sources by Deadwood directly on this device.
Compilation stops after build libpopupmenu.a and trying to build libatomic have this error:
<pre>
Configuring build in bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic
configure: WARNING: unrecognized options: --disable-nls, --without-x
checking for --enable-version-specific-runtime-libs... no
checking for --enable-generated-files-in-srcdir... no
checking build system type... arm-unknown-linux-gnu
checking host system type... arm-unknown-aros
checking target system type... arm-unknown-aros
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for arm-aros-strip... /media/farox/pyra2/arosbuilds/toolchain-core-armhf/arm-aros-strip
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for arm-aros-gcc... /media/farox/pyra2/arosbuilds/toolchain-core-armhf/arm-aros-gcc
checking whether the C compiler works... no
configure: error: in /media/farox/pyra2/arosbuilds/toolchain-core-armhf-build/bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic':
configure: error: C compiler cannot create executables
See config.log' for more details
make[2]: *** [mmakefile:4489: /media/farox/pyra2/arosbuilds/toolchain-core-armhf-build/bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic/.configured] Error 77
[MMAKE] make --no-print-directory TOP=/media/farox/pyra2/arosbuilds/toolchain-core-armhf-build SRCDIR=/media/farox/pyra2/arosbuilds/AROS CURDIR=tools/crosstools/gnu TARGET=tools-crosstools-gcc-libatomic-configure -s --file=mmakefile tools-crosstools-gcc-libatomic-configure failed: 512
[MMAKE] Error: Error while running make in tools/crosstools/gnu: No such file or directory
make[1]: *** [Makefile:361: linklibs-libatomic] Error 10
make: *** [Makefile:183: crosstools] Error 2
</pre>
looking at config.log on arosbuilds/toolchain-core-armhf-build/bin/linux-arm/gen/host/tools/crosstools/gnu/gcc/arm-aros/libatomic
found that arosbuilds/toolchain-core-armhf/arm-aros-ld: cannot find -laeabi
so do make linklibs-aeabi-arm-quick
and the missing lib was built.
now the next stop is at
fatal error: bits/libc-header-start.h: No such file or directory
and
fatal error: sys/cdefs.h: No such file or directory
in many places so after checking that have this missing include files i have noted that my include path is a bit different, standard searching path is /usr/arm-linux-gnueabihf but in my system is /usr/include/arm-linux-gnueabihf
so if i add my path to some mmakefiles compilation goes on....but is a better way to add this path to avoid every mmakefiles to be changed?
fixed with adding
-I/usr/include/arm-linux-gnueabihf
to where is missing on mmakefiles like
USER_INCLUDES := -isystem $(GENINCDIR) -I/usr/include/arm-linux-gnueabihf $(KERNEL_INCLUDES)
P.s. I have changed many mmakefiles and have at least compiled (after many hours) the toolchain doing make every time in arosbuilds/toolchain-core-armhf-build (also have to disable making tests under cplusplus but don't remember the directory ...) but ask an help to have an automated way to correctly build without modify mmakefiles.
Last time built armhf target was around 2 years ago. At that point built is via cross-compilation from linux (ubuntu 22.04) using linux armhf crosscompiler (this can explain the path differences you are experiencing) as well as using AROS gcc cross-compiler in version 6.5.0 (build with option 21) in rebuild.sh). Since then AROS GCC has been updated to 10.5.0 and don't believe anyone tried to build the armhf target again.
My suggestion would be to downgrade GCC to 6.5.0 (via editing AROS/config/gcc_def file) and try to first build using cross-compilation from x86_64 linux. Once that works, you will have a "template" to compare to native compilation under arm linux.
Thanks for your suggestion...but think the toolchain with GCC 10.5.0 is compilable if i found a way to pass the path of my system to the script that build (option 21 on rebuild).
The other only changes are (but don't know where to modify...) is to add the build of libaeabi and disable the building of some tests under cplusplus that use exceptions and is not supported under ARM. try to crosscompile with my Linux amd64 PC.
For paths look into core-linux-armhf/bin/linux-armhf/gen/config/target.cfg. A number of build-wide variable is set there containing paths to local build system. These variables and the target.cfg file are generated by AROS ./configure script.
Thanks compilation now go forward...changed target.cfg under "toolchain-core-armhf-build/bin/linux-arm/gen/config" and do make on "toolchain-core-armhf-build" dir.
Need to find where to enable build libaeabi.a so can build the entire toolchain with option 21 of rebuild.sh
Found something that looks like libeabi in AROS/arm-all/arm-aeabi/mmakefile.src. Try adding a third line there:
#MM- linklibs-armhd : libklibs-aeabi-arm
Don't remember needing this library. Possibly the 6.5.0 GCC somehow does this while 10.5.0 is missing this.
Try adding this line (and the variant "linklibs-armhf" instead of hd) but it did not solve the automatic building of the missing lib. I must do "linklibs-aeabi-arm-quick".
Anyway after have build the aeabi lib i succefully built the toolchain (after many hours...). Smile
To test I restarted from selecting option 21 (on rebuild.sh) but after many hours i get the same error of the kernel includes not found...maybe i need to modify the configure script for my case.
With the toolchain built i try to build the core-linux-armhf (DEBUG) (option 22) but after a while it stopped with
"cannot find -laeabi " so i made it built manually...and now i can continue compiling...i'll let you know if all goes ok.
== Hardware ==
===64bit===
====BCM2712====
With the Pi5
Broadcom VideoCore 7 vc7 is an integrated GPU with 12 cores and up to 800 MHz clock. VideoCore VII is capable of OpenGL ES 3.1 and Vulkan 1.2. The driver support for the Raspberry Pi continues to build upon the [https://lore.kernel.org/dri-devel/20230928114532.167854-1-itoral@igalia.com/ open-source V3D driver] stack within [https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25450 Mesa] hopefully be merged for Mesa 23.3. x265 HEVC accelerated untested, x264/h.264 and VP9 cpu only.
*Raspberry Pi M.2 HAT+ Expansion Board
*Geekworm X1001 PCIe to M.2 Key-M NVMe
*Geekworm X1003 PCIe to M.2 HAT NVMe SSD PIP Board for Raspberry Pi 5
*Pineboards Pi Hut HatDrive! M.2 HAT 2024/V4
*Hat+ Gen2 Gen3 Nvme
*GeeekPi 52Pi N04 for Raspberry Pi 5 NVME M.2
*
*2024 RPI AI HAT - Hailo 20TOPs no LLMs
*2026 RPI AI HAT+ 2 - Hailo 40TOPs slightly better?
[https://www.raspberrypi.com/documentation/accessories/camera.html Cameras for Pi]
*Raspberry Pi camera module, the V3 with Sony IMX708 back-illuminated CMOS 12 Megapixel sensor
*Raspberry Pi Camera Module V2 – 8MP Sony IMX219 Sensor
*Raspberry Pi camera Rev 1.3, 5MP 1080P OV5647 image/video module, 2592 x 1944 pixels
====BCM2711====
With the Pi4 an ARM a72 cpu is about x3 times the size of an a53 in the Pi3
the 2711b line used more power when idle, compared to the 2711c
*2018 Raspberry Pi PoE HAT Power Over Ethernet Hat - design issues
*2020 Raspberry Pi PoE+ HAT Power Over Ethernet Hat Pi3b+ Pi4 only - better design
*Waveshare PoE HAT (B) with cooling fan for Raspberry Pi 3B+/4B 802.3af PoE
*[https://github.com/axizo-pi/V3DLib vc6 V3D 4.2] is derived from [https://docs.broadcom.com/doc/12358545 vc4], but it is [https://docs.mesa3d.org/drivers/v3d.html significantly different]
The QPU pipeline stays mostly the same, you still have an add ALU and a multiply ALU and it can issue two ALU OPs per cycle. There is still 4 SIMD lanes, interleaved over 4 cycles.
The instruction encoding for the QPUs is different, but the core instructions are the same.
Instructions for packed 8 bit int math has been dropped, along with most of the pack modes.
Instructions for packed 16bit float math has been added (2 floats at in a single operation)
With vc5/vc6, you write two packed 16f value to the tilebuffer (or four writes of 32f, if you are using the rgba32f framebuffer). And there is a handy vfpack operation which allows you to pack two f32s into a single 32bit value in a single instruction. You can vfpack directly into the tile buffer register.
the multiply ALU can now fadd, so you can issue two fadds per instruction. the add ALU has gained a bunch of new instructions
the A and B register files have been merged. You still only get an A read and a B read per instruction, but they read from one big register file (which means the underlying memory block has gone from two sets of "one read port, one write port" to one "two read ports, one write port" block)
The theoretical max FLOPs per QPU remains the same at two per cycle, other than the bump from 400mhz to 500mhx but it looks like a lot of effort has been put putting those theoretical FLOPs to better use.
*vc4 could run one or two threads per QPU. When you ran in two thread mode, the available register file halfed to 32 registers.
*vc5 added a four thread per QPU mode, with 16 registers per thread.
*vc6 doubled the size of the register file. You could now use all 64 threads in two thread mode and 32 registers in for thread mode. Single thread mode was removed, you always have at least two threads.
With the threading improvements, the QPUs should spent much less time idle waiting NOPs for memory requests. Most of the design changes have gone to improving the fixed function hardware around the QPUs. A fixed function blend unit has been added, which should reduce load on the QPUs when doing alpha blending. hope software blending is still possible
The tile buffer can now store upto 4 render targets (up to 128bits per pixel, so if you are using 4 32bit render targets, you can't have a depth buffer)
A MMU, allowing a much simpler/faster kernel driver.
Many more texture formats, framebuffer formats.
h264/x264 as Pi3
All the features needed for opengl es 3.0
H.265 / HEVC decoder is a HEVCv2 Main 4:4:4 10 design supporting bitstreams up to profile 5.1
HEVC hardware decode supports 4kp60, 10-bit. Audio output is pretty much unchanged, but the HDMI audio channels now support 8x192kHz bitrates
Each ALU typically have 2 floating point operators, and as you pointed out in a earlier post videocore 6 is no exception, with both a multiply and additive floating point operator. Thus theoretical GFLOPs are calculated with both operators in mind. That is what the 2 in my formula represents, and is common across any modern programmable shader, whether you calculate Nvidia, AMD, Intel, Boardcom or any other company's GPUs. Total ALUs * 2 * GHz clock = GFLOPs, In the case of Raspberry Pi 3, it's 24 ALUs * 2 operators * 0.4GHz = 19.2GFLOPs
If the Videocore 6 does indeed only have 16 ALUs (16 * 2 * 0.5GHz), you'd have only 16GFLOPs but they are better utilised
Possible maximum performance
<pre>
VideoCore IV @ 250MHz: 250 [MHz] x 3 [slice] x 4 [qpu/slice] x 4 [processor] x 2 [op/clock] = 24 Gflop/s
VideoCore IV @ 300MHz: 300 [MHz] x 3 [slice] x 4 [qpu/slice] x 4 [processor] x 2 [op/clock] = 28.8 Gflop/s
VideoCore VI @ 500MHz: 500 [MHz] x 2 [slice] x 4 [qpu/slice] x 4 [processor] x 2 [op/clock] = 32 Gflop/s
</pre>
Faster LPDDR4 memory.
====BCM2837====
With the Pi3
* Broadcom BCM43438 chip provides 2.4 GHz 802.11n wireless LAN, Bluetooth Low Energy, and Bluetooth 4.1 Classic radio support, 3B+ [https://github.com/aros-development-team/AROS/commit/afa5bc0bb17d5dd06bcfdbac00853a3799ca8d76 LAN7515]
The overclock ability has diminished with each chip version as the energy usage has increased. BCM2837 is one of the warmest yet and benefits from active fan cooling if all four cpu cores are in use for a short while. Video playback maybe affected due to the lack of custom support in the GPU with Aros. 5 V / 2.4 or 2.5 amp power supply recommended if all four cpu cores are running, else throttling (cpu slowdown) might occur.
[https://github.com/hermanhermitage/videocoreiv/wiki/VideoCore-IV-Programmers-Manual Dual VDP] and scalable QPU in [https://docs.mesa3d.org/drivers/vc4.html VC4] and x.264/h.264 accelerated untested only and VP9 on cpu or neon help
ARMv8-A has [https://developer.arm.com/documentation/102412/0100/Privilege-and-Exception-levels privilege levels] where userspace typically runs at ‘EL0’, the kernel at ‘EL1’ or ‘EL2’ and the firmware at the highest level ‘EL3’.
===32bit===
=== Core Kernel ===
====BCM2708(family)====
which includes the [http://elinux.org/RPi_Hardware BCM2835] (ARM1176JZF-S 700 MHz CPU + VideoCore IV GPU + up to 1GB RAM)
*Framebuffer (fb) using mailbox
*IRQ scheduler, etc
*Arasan based SD Card controller
*Synopsis DesignWare USB 2.0 OTG controller [http://networkdirection.net/index.php?option=com_content&view=article&id=106:rasperry-pi-usb-controller&catid=45:raspberry-pi&Itemid=54 Unofficial DOCS pdf], [dwc_otg.c FreeBSD], [], [https://www.riscosopen.org/viewer/view/mixed/RiscOS/Sources/HWSupport/USB/Controllers/DWCDriver/ RiscOS USB Driver], [https://www.riscosopen.org/forum/forums/5/topics/878 RiscOS USB Discussion], [https://www.riscosopen.org/forum/forums/11/topics/1893 Other USB RiscOS], [http://plan9.bell-labs.com/plan9/index.html Plan9 Miller's usb] http://plan9.bell-labs.com/sources/contrib/miller/, [https://github.com/Chadderz121/csud CSUD driver],
*[http://www.smsc.com/media/Downloads_Public/Data_Sheets/9512.pdf SMSC 9512] USB LAN/Hub chip
*CMOS RAM
*VCHIQ port which sends messages to the GPU e.g. for mouse, keyboard, audio on HDMI, etc
*Audio Driver
*Serial Peripheral Interface Bus (SPI)
*[http://www.susa.net/wordpress/2012/06/raspberry-pi-pcf8563-real-time-clock-rtc/ I2C registers]
*I2S
*Universal Asynchronous Receiver Transmitter (UART)
*[http://elinux.org/RPi_BCM2835_GPIOs GPIOs] and [http://www.adafruit.com/blog/2012/08/17/broadcom-bcm2835-peripheral-memory-map-and-gpio-alternate-use-chart-piday-raspberrypi-raspberry_pi/ Alternative view of GPIO]
BCM2836
* For Pi B+, PI 2 and Pi 3 SMSC LAN9514 chip adding 10/100 Ethernet connectivity and four USB channels to the board
*[http://www.andrewscheller.co.uk/rpi_pcb_modules.html PCB], [http://elinux.org/RPi_Low-level_peripherals Low level features],
Implemented so far...
# Modify the configure system so that it correctly builds for the arm hardware float raspi target.
# Implemented the bootstrap to load the aros modules and prepare the arm to jump into them. Reworked the x86 console support so that parts can be stolen for raspi to use since t has no basic functionality to output to the display.
# Implemented a kernel.resource to prepare the raspi for running aros and provide the low level api calls to expose available resources and allow exec, etc function.
# Implemented serial debug support
# Implemented the exec (and kernel) functionality required to make multitasking work (and interrupts, exceptions, syscalls, etc)
# Implemented a timer.device to utilise the hardware timers.
# Implemented a very basic gfx driver to expose the hardware's framebuffer.
# Implemented an SD-Card driver for AROS which presently only supports the raspi's chipset but can easily be modified to support all sd-card hardware and media.
# Fixed the fat filesystem support in AROS so that it can boot on RasPi's normal SD-Card setup. The "rom" image files needed use a different filename than the default linux, etc images so can be easily installed without harming the existing files - you only need to change the loaded images in the config file to get aros to boot.
# Updated the build scripts to automatically download the necessary raspi firmware files and wrap it all up so that you can simply extract the archive to a fat formatted sdcard and boot it on the raspi without having to get anything else.
# fix everything in contrib and ports to build for raspi (needs proper testing/fixes but allows every component to actually compile at least, including owb) + numerous other fixes to get things working on arm/raspi ..
Improvements...
# Implement a USB chipset driver "OR" finish the existing one [https://github.com/aros-development-team/AROS/commit/c07d13c724f944674be5db54fc6a71ee72a01809 usb otg] - the current code is mostly a skeleton that should initialise the chipset and then needs relevant code to support the different transfer types. It also has the "virtual" hub code in place to represent the raspi's USB port (from poseidons p.o.v)
# Implement a driver for the USB NIC (a few weeks - depends on USB above)
# Write an [https://github.com/aros-development-team/AROS/commit/d55d0f74d20b769bbb8c8d386e5c1d7a9154f05a audio driver] (a few weeks - independent of USB) and [https://github.com/aros-development-team/AROS/commit/e93a4c245f27a87c9c4c1d39206694b39059998a HDMI]
# fix syscall bug in the current raspi kernel code
# Graphics depend on having a decent "bcmdma.resource" implemented as to use the cpu's dma engine. The sd card driver needs to use it for transfers to/from the controller - and the gfx system needs to use it for "blitting".
# [https://github.com/aros-development-team/AROS/commit/4019d84e4975d4dad987a12d57fe108f5ac048e6 Improve the gfx driver], [ vc4gfx HIDD] add [http://dri.freedesktop.org/wiki/VC4/ Gallium3D support]
# [https://github.com/aros-development-team/AROS/commit/b13905b3e8e45b089f520b44692c81affddd066f Improve] the [https://github.com/aros-development-team/AROS/commit/3a876755c070f5c73c4f53c7f4d35b4f923088b9 sdcard] device driver - which is also pretty basic but should work with most cards, rework it to also support pci, etc. sd card interfaces on x86
# The current code using very rudimentary access to the gpio interface - so that should be implemented as some resource for other components to access, as-well as the i2c interface exposed over the gpio interface. that should have a hidd class implemented which uses the gpio resource to communicate.
Boot up typical for most other OSs before the open sourcing of many binary blobs from 2017 onwards
On power-up, the rpi [http://www.open.com.au/mikem/bcm2835/ BCM 2835] [https://github.com/hermanhermitage/videocoreiv VideoCore4] GPU, not the ARM CPU, is in control, and the SD card slot is the only peripheral device with power. The firmware burned into the BCM2835's VideoCoreIV GPU PROM requires a DOS-style partition table; a FAT-formatted first partition; and the freely redistributable but closed sourced Broadcom files “bootcode.bin” and “start.elf” in that partition.
The boot sequence carries out several pre-boot tasks
*On powering of the rpi, the GPU reads and executes bootcode.bin, which then loads start.elf
*The GPU loads the “start.elf” file, eventually, into the L2 cache and then executes it
*configures the memory split for the CPU and GPU
*reads and parses “config.txt” from the same partition on the SD card and applies the settings (like a PC’s BIOS settings)
*loads the “kernel.img” file, again from the same partition
*activates the CPU to begin executing the loaded kernel image
The CPU/GPU memory split is hard-coded into start.elf, so Broadcom provides three start.elf images, to give 32M, 64M, or 128M to the GPU for multimedia performance, and the remainder to the CPU.
RPi uses [https://github.com/raspberrypi/firmware some closed source loaders] and at some point it loads a binary blob named "kernel.img" at 0x8000, at that point there would be a rudimentary Aros alive. If one wants to use the SD-card then there would have to be a driver for the interface and a fat filesystem handler (SD-card has to be formatted to fat filesystem)
Boot code and kernel are now linked together and made into that binary blob, just for starters. Raspberry Pi uses [http://kernelnomicon.org/?p=133 u-boot] and [http://kernelnomicon.org/?p=138 UBoot] as bootloader, there's already some code in the Efika MX port for that. UBoot is a native bootloader and not just for the raspberry pi, it loads after start.elf.
You can find Efika MX port from arch implementations, some hacking is needed for the mmakefile.src'es as iit dates back to before the Aros crosstool era or else you get some weird errors while building. You also need to code the bootstrap and serial handling.
At the moment it seems that a fastest route for the native build would be to make one binary blob without using the package system. Raspberry's memory layout is pretty simple and if the implemented u-boot doesn't support loading other modules
<pre>
? - alias for 'help'
mtest - simple RAM test
autoscr - run script from memory
base - print or set address offset
bbm - BBM sub-system
bdinfo - print Board Info structure
boot - boot default, i.e., run 'bootcmd'
bootd - boot default, i.e., run 'bootcmd'
bootm - boot application image from memory
bootp - boot image via network using BootP/TFTP protocol
cmp - memory compare
coninfo - print console devices and information
cp - memory copy
crc32 - checksum calculation
echo - echo args to console
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls - list files in a directory (default /)
go - start application at address 'addr'
help - print online help
iminfo - print header information for application image
itest - return true/false on integer compare
jade -
loadb - load binary file over serial line (kermit mode)
loads - load S-Record file over serial line
loady - load binary file over serial line (ymodem mode)
loop - infinite loop on address range
md - memory display
mm - memory modify (auto-incrementing)
mtest - simple RAM test
mw - memory write (fill)
nfs - boot image via network using NFS protocol
nm - memory modify (constant address)
pci - list and access PCI Configuration Space
ping - send ICMP ECHO_REQUEST to network host
printenv - print environment variables
rarpboot - boot image via network using RARP/TFTP protocol
reset - Perform RESET of the CPU
run - run commands in an environment variable
saveenv - save environment variables to persistent storage
saves - save S-Record file over serial line
setenv - set environment variables
sleep - delay execution for some time
tftpboot - boot image via network using TFTP protocol
USB - USB sub-system
usbboot - boot from USB device
version - print monitor version
</pre>
And there is one more thing about modular ports. In order to actually implement this, your bootstrapping environment should provide the ability to load several files. On PC this is provided by GRUB2. on CHRP you can read filesystem via OpenFirmware, and Sam's Parthenope relies on modified u-boot. If your bootstrap allows to load only a single file, then you stuck with monolithic kickstart. By the way... u-boot allows not only to boot up a single uImage or zImage, it also allows to write client programs AFAIK. With this approach, you actually can write modular bootstrap for ARM AROS using unmodified u-boot.
Most used [http://www.compulab.co.il/workspace/mediawiki/index.php5/U-Boot_quick_reference uboot options] are fatls usb 0:1,
the reason behind INTB_KERNEL is to allow use of the standard Exec function AddIntServer() to add interrupt handlers for
hardware drivers etc. AmigaOS never used it for abstract hardware drivers. AmigaOS routed only raw hardware IRQs there. Their assignment was hardcoded. As well as number of them. Actually on AmigaOS every bus has its own interrupt subsystem. For example PCI bus. PCI interrupts on Amiga are routed to a single exec interrupt. 1:1 relationship between CPU and hardware interrupts is present only on PC.
IMHO we miss things like AddInterrupt/RemInterrupt methods on our PCI subsystem's device class. PCI bus class should map these methods to whatever is appropriate. This is how it is done on AmigaOS and friends. When these are implemented, raw kernel.resource API will be needed only for several PC-specific drivers with hardwired resources. Exec IRQs are real IRQs only on Amiga hardware. On other machines they can be emulated where appropriate (VBlank is a good example). kernel.resource is meant to be different, its IRQs are hardware-agnostic, they are plain "Hardware IRQ number X, whatever this means". They are low-level actually, and meaningful only in the context of a particular system.
Was that not the transition from irq.hidd to kernel.resource? No. A long time ago there was another hacky bit named INTB_TIMERTICK. It was "abstract timer interrupt", used by timer.device. It was the same as VBlank, but with larger frequency. I removed it, because kernel.resource API was a cleaner way to access this interrupt. Furthermore, there can be more than one timer in the system. Thinking about bringing back timer HIDD definitions again. hpet.resource is a bad idea.
Can someone please enlighten me a little on how the scheduler is meant to work?
Poseidon.library creates its "Poseidon Event Task" during RTF_COLDSTART -> then calls Wait(), and ends up in limbo because wait disables interrupts (used for the scheduler heartbeat), and basically waits forever because the sigbit is never set, since krnSwitch doesn't switch the task unless TF_SWITCH is set, and no codepath run during this seems to set it?? TF_SWITCH does not disable/enable switching. This flag just enables to run user-supplied hook when the task is being switched away. It is completely safe to call Wait() in Disable()d state. Doing this actually temporarily breaks this state. IDNestCnt gets remembered in struct Task, then next task is selected, and its IDNestCnt is restored in sysbase (see kernel_scheduler.c). If there are no other tasks, then your cpu_Dispatch() should enable interrupts on the CPU and enter idle mode. See x86 implementation for good example.
You miss what happens next...
1. KrnSwitch() saves context of your task, saves IDNestCnt (core_Switch() and cpu_Switch()), then drops into cpu_Dispatch().
2. cpu_Dispatch() calls core_Dispatch. Then two cases are possible:
2a. There is a READY task. It is picked up, its IDNestCnt is restored in SysBase, then cpu_Dispatch() needs to restore registers and exit. The next task is run.
2b. There are no READY tasks. core_Dispatch() returns NULL. In this case your cpu_Dispatch() should enter idle loop. It should just enable interrupts on the CPU and put it on halt. This allows it to process hardware interrupts. Eventually some of your interrupt handlers wakes up your task and puts it into READY list.
My heartbeat interrupt has been slowed atm to help debugging - but it never actually gets a chance to fire because of the Wait() disabling interrupts. Perhaps you have forgotten to enable interrupts in your idle loop.
There is a change in the format of AROS executables. Until now we were using Elf RELocable files which are usually used as intermediate object files. We had them for various reasons, one of them was how AROS files were built in the past. That days we had no real aros cross compiler and the option to embed relocation data in unix executables (or in executable files in general) was rather new and not every linux/unix system had it. Therefore we have decided to use intermediate files. Although it was somehow working (and it is still working :-)), it has some drawbacks. Therefore decided to introduce real Elf EXEC types, in first turn implemented on ARM target with option to expand in future to all other AROS architectures.
The first patch was pretty easy and appeared to work somehow. It generated nice executables with embedded relocation info. Not only that, it also removed all global symbols adjusting relocation data to be relative to the beginning of the sections. That move reduced number of symbols in each executable significantly (depending on the file between 20 and 80% of all symbols could be removed). The only symbols that stayed in the file are local ones - due to the nature of the patch wasn't able to remove them since we have not seen them in the symbol hash table.
The patch didn't worked though. The files were relocated, AROS kernel loaded, but it crashed very early. What happened? Well, the nature of ARM relocations happened :)
Most of the relocation data on all machines is rather simple. Relocation can be absolute or pc-relative, sometimes the offset has to be bit shifted. On ARM v7 there is another one. There, when one wants to load an address of function/variable into register a combination of two instructions can be used: movw and movt. The first one loads immediate into lower 16 bits of a register while clearing upper 16 bits. The second one loads immediate into upper 16 bits without touching lower halfword. Loading of a pointer into a register looks like this:
movw r0, #:lower16:label
movt r0, #:upper16:label
In this case there are two relocations - one for lower halfword and another for upper. If an overflow of lower 16 bits occurs during relocation process, the upper one should be updated as well. Unfortunately with current patch and with typical ARM executables there is not enough information to perform the calculations.
There are two options - the first one would be to give up and go back to "fake" executables, another one would be to change from REL to RELA relocation info. The latter contains an addend, extra data which can be used to perform all the relocation calculations I need.
Decided for the second option. The patch is already in the works. There is another function for the binutils' bfd backend to perform the final relocation. There can decide what to do with every reloc info, modify data and eventually strip some symbols. An advantage is - at this stage of the linking process have also full access to all local symbols so can change all relocations section relative and eventually strip all symbols from the files.
GPU
VCore developed by Alphamosaic Ltd and now owned by Broadcom. Most of start.elf runs on the GPU. Placing ALL the userland GPU code in the videocore.hidd isn't going to be a terribly big problem because the code they published is nothing more than a shim that sends data straight to the GPU to execute.
The good news about this is that we only need to write our HIDD using the OpenVG API. The shim is relatively small codewise and lives in the ARM memory (the actual OpenVG code itself lives in the GPU RAM area and its loaded from start.elf). That's also the bad news. Our driver has to translate AROS video calls to OpenVG calls, for most tasks it should be easy, for some, not so much. It's still probably less difficult and less work, than controlling the GPU directly.
The other good news is that anything done through OpenVG happens on the GPU, its truly accelerated. It also has some nice font functions, meaning we can lead into an accelerated text mode later.
Basically, AROS resets or locks up when it tries to use AROS_ATOMIC_INC or DEC. If I comment out the byte/word operations in the header files and use non-atomic operations, the code works as expected.
have read that the L1 cache needs to be enabled to use LDREX and co (which I also read is only meant to be used on multi processor systems with shared memory) - however I am certain this is correctly enabled.
If you are using LREX or STREX, you should have L1 cache enabled, at least on the ARM CPU I work with at work.
L1 cache is enabled by enabling the MMU *AND* setting the C and I bits in the CPU - the C bit is ignored, and the I bit only covers the 16 byte instruction pipeline if the MMU is not enabled.
Can you verify that your assembly is generating LDREX/STREX? From the behavior, it almost sounds like its generating the default Semaphore locked atomics.
Impossible. There are no semaphore-locked atomics. There are Disable()/Enable()-based ones instead. And there's a special #define AROS_NO_ATOMIC_OPERATIONS in this case, which tweaks Disable()/Enable() implementations not to recurse forever.
I have tested this on ARMv5 which does not have ldrex/strex, it works fine. On those ARMs there's no way to have real atomics. On other OSes (like Linux) this is done by introducing things like atomic_t, which appears to be a complex structure, holding the value together with accompanying spinlock (implemented using swp).
#warning "TODO: lookup optimal mmu table settings for raspi memory"
/* Set up an identity-mapping for all 4GB */
for(x = 0; x < 4096; x ++)
{
pagetable[x] = x<<20 | (0x40002|0x80000|0x010000|0x00C00|0x04);
}
Shouldn't there be a second loop that sets the 'C' bit in the descriptor for the RAM pages?
Currently, you have TEX=0, C=0, B=1 for all pages (Shared Device).
You should have TEX=0, C=1, B=0 for RAM (Write-Through, Cached)
So ..
pagetable[x] = x<<20 | 2;
should be enough?
No, for RAM you need to change the '| 0x40' to '| 0x80'
tell dosboot the correct defaults to use
Please don't do this. This bootconfig.c is a deprecated legacy thing. I wanted it to go away completely with time. Instead, display drivers should auto-install themselves during own initialization phase. I. e. detect hardware=>instantiate itself. This should make things way simpler. With this approach you only need to add the driver into KS image to get the device autobooted. No hardcoded stuff.
Currently VESA and VGA drivers do this, look there for examples. never rewrote ATI driver because i don't have any test system for it.
they defined a smaller AROSCPUContext than the ExceptionContext - yet reference it as ExceptionContext in other places, and since it hasn't allocated enough storage for ExceptionContext, are corrupting memory/the structure (since the elements that are there don't map 1 to 1 with the exception context).
AFAIK, AROS has been moving in a different direction to this in recent years. It is the job of graphics HIDDs to allocate bitmaps etc. so that they have the most suitable characteristics, including allocating them from GPU RAM where possible. The concept of chip RAM is only for legacy code, and most if not all non-68k platforms should have all system RAM
marked as chip.
BTW, is the video processing code you mention CPU code or GPU code?
Also, IIRC we have support for "external memory allocators". Perhaps that's what we need for the allocation of GPU RAM through the mailbox.
All hosted and x86 native ports should use proper context formats.
trying to clarify if the vblank handler has to have run by this point to prevent this deadlock. Actually, no. Unless you have installed VBlank handler which should wake up at some point. Without VBlank there will be no quantum count. Consequently, there will be no forced preemption. But the rest will work, and multitasking will be cooperative (switch happens only when current task voluntarily gives up the CPU). Does it depend on the vblank having run before this point? and if yes what does that mean on systems where it might be able to run enough code (e.g. get to this point) before the vblank interrupt has triggered? What is it waiting for? It could wait for timer, in this case you need timer.device working. VBlank is currently needed for exec's quantum counter. In current native ports we have only a single timer, which is served by timer.device. VBlank is simulated by timer.device also. If your machine has two timers, then you can use one of them for VBlank, and another for timer.device, this will simplify things down. VBlank needs to be 50 Hz for historical reasons, many programs use it as cheap timer. I am periodically thinking about making some abstract mechanism to be able to change quantum source (and untie it from 50 Hz), but have no time to come up with something good. Additionally i started disliking timer.device hardcoded design when PC has got many timers (old 8253, APIC, HPET).
Currently i think there should be some low-level entity representing tick source. timer.device should just select the most appropriate source for its units.
The BCM2835 has 4 GPU based timer sources - 2 are used by the GPU, so im using Timer3 for our heartbeat and the remaining one will be free to the system. There is also the less capable ARM timer but that is dependent on the CPU frequency. Very good. You won't need any emulation. Set the heartbeat to 50 Hz and drive VBlank from it. Use other timer for MicroHZ.
Can you use the 'econsole.hook' I make for debugging the Sam460 via the serial port?
It provides a before-anything-else shell prompt on the serial port. You can then do 'NewCLI' to test your graphics, or use any DOS command in shellcommands.resource.
You should just be able to add econsole.hook to your module list, and use 'econsole' in your bootargs.
So long as you have a working Exec/RawMayGetChar and Exec/RawPutChar, it should work.
Also make sure to add shell.resource and shellcommands.resource for this.
That should have done it.
If you set "#define DEBUG 1" in arch/all-native/econsole/econsole.c, do you get any additional serial output?
have added it to the build and added econsole to the command line - and can see the bootloader picks up on the emergency bootconsole tag, but I still only get the insert bootable media display?
Im assuming it exposes a fake filesystem that tricks aros into booting?
The contents of which are: ECON:AROS.boot
Way to handle the scheduling code? The implementations I had been following were causing problems, due to cascading interrupts which I cant handle properly in the asm stubs just now (when they break disable etc.) - since it means detecting the interrupted codes cpu mode and getting the correct sp/lr for it, and that's just too tedious for arm.
To work around this ive added a system idle task which does nothing - and when the scheduling code has no task to run switches this in and lets it run, thereby allowing the interrupts etc to resume until something does need to happen.
Also, by adding accounting code to cpu_Switch() and cpu_Dispatch(), it should allow the system to log idle time correctly (as well as running tasks).
have thought of also adding an additional task that never runs, solely to record time spent in IRQ handlers, but I digress..
was under the impression that kernel.resource should *never* be used outside of exec.library. This is a wrong impression.
Michal started designing it because portable nature of AROS does not fit well into exec's API with all its assumptions. So, he started the new, hardware-agnostic kernel API from scratch. Yes, exec sits on top of it in places. But kernel always meant to be open thing. Otherwise it would not exist.
it wasn't meant to be just used willy nilly by user code - but by lower system components (e.g. exec) so that they could be implemented in a more generic fashion, and the kernel resource itself hide the systems quirks.
Adding new things there perfectly keeps up with our decision to minimize AROS-specific intervention into APIs which can clash with MorphOS or Amiga OS4 extensions. We want at least source-level compatibility there. Binary compatibility on PPC would be extremely cool, but at the other hand we have no maintainer for this, as well as their ABIs splintering.
It depends on what exactly is being implemented - there's no reason we should have everything crammed into kernel.resource if it doesn't need to be (i.e. if its better suited as a separate component/subsystem in its own right)
The _LE versions are for when you have endian swapping taking place. If the graphics are the same endian as the CPU, no swapping should occur. I ran into a similar terminology problem in SDL with a friend insisting that his Radeon 7000 on his PC was big-endian. It is not, it just uses the same endianness for the graphics card and the CPU so no swapping was necessary. They were both little-endian.
The _LE versions are because the PixFmts refer to the bitmap data being in big endian format in memory, for which the normal version would need to do endianness conversion before applying the shifts/masks. on this platform it is in _LE in memory also so we don't need the conversion hence using the _LE version of the call). would use _LE (if it's really little endian 16 bit mode).
What is the bare minimum needed to implement a framebuffer based gfx driver, with our software handling the rest?
Have tried with just a gfx class that only expose new/dispose/newbitmap - and having an onscreenbitmap used only for the framebuffer itself (with all other bitmaps being chunkybm, and the framebuffer's superclass also being chunkybm), but that alone isn't enough it seems?
You can use workbench/hidds/sm502/ as your example - it is as simple as I could make it.
So, AROS creates the framebuffer bitmap (verified this) -> so surely it should be capable of then rendeing into it? I don't actually create the framebuffer "bitmap object" myself - only as a result of being asked to. The code I currently have on SVN seems to create the framebuffers bitmap object fine, but then crashes in intuitions DisplayDriver callback. In particular it crashes performing the getattr on the system default pointer. don't expose MEMF_CHIP in an allocatable form so AllocSpriteData was failing (and other code later doesn't check if the values are valid == illegal memory accesses)
So far have -:
vc_init: queries the gpus memory, and sets up a fake memory handler for it, then adds the bootmode driver and returns saying all is well
vc_gfxhidd:New: sets up some fake syncmodes to test with and creates the real gfx object.
vc_gfxhidd:NewBitmap: checks if its a framebuffer and uses the onbitmap class or uses the chunkybm class otherwise
vc_onbitmap:New; creates a chunkybm object and then pushes the real framebuffer address into it as the buffer,
vc4 had v8adds, v8subs, v8muld, v8min and v8max which operated on four 8bit uint values packed into a 32bit register. Multiplication was in the range 0.0 to 1.0 and addition/subtraction saturated. There were also a range unpacking/packing modes that allowed you to pack and unpack 8bit values into 32bit registers.
RasPi has to speak to the "operating system" which runs on the GPU itself and request/free memory - it cant directly manage it itself, and so the managed functions were used to wrap these calls.
The Arm and GPU share memory space. The framebuffer is shared. The Arm can write a pixel and it will appear on the screen (through GPU hardware) without flushing/copying being required.
The GPU can composite multiple FB's in real time - so you have a number of surfaces defined which are rotated etc and composited in real time to the output. Copying can map from the address space of the Arm to the flat space of the GPU which takes some code, but I don't think whole buffers are copied.
The DMA hardware can also access the whole memory space and can perform 2D fills and blits (no blending). This is documented in the peripheral spec posted. The DMA is just an Arm accessible peripheral and can be set up with low latency (e.g. microseconds).
must use a 0xc0000000-based bus address to access SDRAM, yet non-DMA access should go via a 0x0-based bus address.
For 2D dma, set TDMODE, and the spec says "interpret the TXFR_LEN register as YLENGTH number of transfers each of XLENGTH, and add the strides to the address after each transfer." so set STRIDE to pitch of the image, the width is XLENGTH and height is YLENGTH. You would fill by not setting the SRC_INC and point source to your fill data.
The DMA cannot see the ARM's L1 cache, so you would map the framebuffer with ioremap_nocache. Depending on where the source data comes from, it may need an L1 cache flush. The DMA can see the L2 cache. Use 0xC0000000 bus addresses when L2 is disabled and 0x40000000 bus addresses when L2 is enabled. (actually just call virt_to_bus and you'll get the right address out).
openGLES/openVG has high latency. Writing to framebuffer then reading it back is very inefficient (e.g. milliseconds). If you can drive it a unidirectional way, just streaming commands at then that is efficient. openVG is not implemented on top of openGLES - it uses the same hardware but as a first class interface
To improve the Gfx driver, we will need a DMA resource implemented so can use to perform DMA operations. The Gfx driver will need this to perform blits.
Actually MEMF_CHIP has to present, for historical reasons.
This has been never fully agreed upon, but in ports i wrote i exposed the whole memory as MEMF_CHIP. The idea behind this is that CHIP is originally the memory where graphics and sound data can be put. On non-Amiga platforms there are no restrictions on this, so the whole memory is CHIP.
Yes, many old software can misbehave with CHIP memory size larger than 2MB. But this actually applies only to m68k AROS which is going to run m68k binaries. In other cases it's quite logical to fix the program when porting.
As to original question: yes, it's enough to have a framebuffer bitmap (one with aoHidd_BitMap_FrameBuffer set to TRUE) and PutPixel routine. It framebuffer can be served by chunky bitmap class, then you can simply create chunky bitmap with your own buffer (see how VESA driver does this). Chunky PutPixel is already there.
struggling to determine what is the correct pixfmt to use for the 24/16/15 bit gfx modes on the RasPi. AFAIK it uses RGB565, for 16bit but im unsure what shifts etc should go with it? suffice to say Im getting the wrong colors so far lol.
<pre>
redmask: 0x0000F800
greenmask: 0x000007E0
bluemask: 0x0000001F
alphamask: 0
redshift: 16
greenshift: 21
blueshift: 27
alphashift: 0
</pre>
It should likely be vHidd_StdPixFmt_RGB16_LE
This stuff is a bit confusing. The "names" of the stdpixfmts are based on the layout in memory,
ignoring endianess. So for example:
ARGB32: will be 0xAA 0xRR 0xGG 0xBB in memory on both big endian and little endian machines.
The shifts and masks OTOH are based on pixel access (ULONG in this case), so differ depending
on whether you run on big endian machine or little endian machine (that's why there's stdpixfmt_le.h and
stdpixfmt_be.h in rom/hidds/graphics/).
With the 16 bit pixel format it's even more confusing, as for example it's impossible on little endian machine
to describe RGB16 with shifts/masks alone. That's why there's vHidd_PixFmt_SwapPixelBytes_Flag.
(RGB16 == RRRRRGGG GGGBBBBB in memory, and for pixel (WORD) access on little endian machine it needs to
be accessed as GGGBBBBBRRRRRGGGG).
The shifts btw indicate how much to shift the component to the left (!) so that it is moved to the highest bit (31).
The aHidd_PixFmt_StdPixFmt you specify will be ignored most of the time, because when the pixelfmt is registered,
the gfx hidd checks if there's an identical pixfmt (shifts/masks/etc., but ignoring pixfmt->stdpixfmt) already in the system,
and if so, it uses the already existing one and does not create a new one.
In theory it would be better if gfx drivers could simply/only specify a StdPixFmt without all the shifts/masks stuff when the
gfx driver uses pixfmt which matches one of the stdpixfmts exactly. Another possibility would be for gfx drivers to use
HIDD_Gfx_GetPIxFmt(stdpixfmt_gfx_driver_wants_to_use) and then peek shifts/masks from it and fill out a pixfmt
tag list based on that.
15bit very blue/green: Try to pass same shifts/masks/etc. as in 16 bit pixfmt (maybe you think it's using 15 bit R5G5B5
(or swapped) but it's actually still using 16 bit R5G6B5 (or swapped).
aHidd_PixFmt_StdPixFmt you pass is mostly ignored. It's the shift/masks/etc. that count.
But I would still pass the correct one (_LE) == whatever rom/hidds/graphics/stdpixfmts_??.h uses
in the entry where you have looked up shifts/masks/etc.
Use the shifts/masks/etc. from the entry in stdpixfmt_le.h (if you are running on little endian machine) or stdpixfmt_be.h (if you
are running on little endian machine) that matches the pixfmt that its meant to be.
0xAA,0xRR,0xGG,0xBB on little endian (->entry in stdpixfmt_le.h which says vHidd_StdPixFmt_ARGB32)
0xBB,0xGG,0xRR,0xAA on little endian (->entry in stdpixfmt_le.h which says vHidd_StdPixFmt_BGRA32)
0xAA,0xRR,0xGG,0xBB on big endian (->entry in stdpixfmt_be.h which says vHidd_StdPixFmt_ARGB32)
0xBB,0xGG,0xRR,0xAA on big endian (->entry in stdpixfmt_be.h which says vHidd_StdPixFmt_BGRA32)
it feels like AROS trashes the alpha component, otherwise it should be 8A8R8G8B.
read on the subject suggest its in 1x5r5g5b (x is ignored) to keep 16bit alignment .
Suggests to me that wrong shift/mask are being applied - however going by the 16bit versions it all looks correct to me so I am really confused as to what is happening.
The output image looks to have too much green/blue, and very weak red.
Kickstart
The idea is to minimize amount of archirecture-specific modules to make the user's life easier. So, the kickstart was split into 'base' (which does not contain anything machine-specific) and 'BSP' (Board Support Package) which contains all hardware-specific stuff. This way, for example, distribution makers can save up space on CD and make CDs with multiple platform support. Different configuration would load the same base with different BSP's.
Next there was some part which is entirely missing on hosted. These are filesystems. Hosted ports do not need them to boot up, so on hosted they are left out. At the other hand, they are also architecture-agnostic. So i put them into 'FS' package (standing for 'filesystem').
USB
Poseidon is one more big part. I made it into separate package in order to allow users to omit it if they don't need it (for example, to run on retro PCs without USB). Personally i have one. Again, Poseidon is hardware-agnostic (well, there are USB drivers but HCIs are pretty standard).
AFAIK its HCI 1.0 compliant but not familiar enough with poseidons drivers, nor USB, to just hack away at the existing code. Perhaps once i'm more familiar with the workings I can merge in the changes needed to get it operating but for now I will focus on getting it running. Also our drivers have known issues so perhaps a fresh set of eyes might shed some light on what is going wrong.
Another interesting question is whether Poseidon can operate on device side. Is it flexible enough? How similar is being a USB host and USB device? think it will need a bit of work on Poseidon's side. Until then I will force the driver into Host/Master mode in the init code, but leave open device etc to configure the chipset for either's use - and look at trying to add support for working in Device/Slave mode & switching modes once it's up and running.
Actually USBROMStartup is some kind of kludge. Can there be any alternative? Could device drivers be self-installing, like our HIDDs? This would get rid of need to list them in USBRomStartup.
* Model A and B limited to 150 mA per port.
* Model B+ and Pi 2 introduced configurable 600 mA to 1.2 A support over all ports - anything above that requires a powered USB hub.
Implementing the hardware driver that Poseidon uses to interact with the USB components.
Have code in place to (try) and initialise the USB chipset, and configure host/device mode operation (though AFAICT Poseidon doesn't support device mode). Started to get the "virtual" root hub written for the single USB port so that Poseidon should at least list it correctly in the GUI - and try to interact with it to find peripherals.
The BCM2835 uses a soft IP block from Synopsys’ DesignWare library (DWC), specifically the block is called dwc_usb_2_0_hs_otg_subsystem-ahb_se (“USB 2.0 Hi-Speed OTG Controller Subsystem w/AHB Interface SE”).
There is no public documentation for this, and pretty much zero chance of anyone getting hold of it even with NDA. However, there's a Linux driver written by Synopsys ([https://github.com/raspberrypi/linux dwc_usb]). Specifically directories [https://github.com/raspberrypi/linux/tree/rpi-patches/drivers/usb/host dwc_common_port] and [https://github.com/raspberrypi/linux/tree/rpi-patches/drivers/usb/host dwc_otg].
The Synopsys code is actually under a fairly permissive licence – it's not GPL, it's similar to BSD (’don't sue us if it breaks’ is pretty much the only clause). So this should not be a barrier to porting the code.
The code is really well written, with a nice partition between the work done by the driver (dwc_otg, which is fairly involved, given the host does more work than a conventional EHCI driver), and the interface to Linux (dwc_common_port).
Probably only need provision of relevant changes to dwc_common_port. Other things to consider....
* Provision of necessary headers to get it to compile
* Provision of necessary functions (main issues are wait queues, threads, work queues, tasklets, timers, spinlocks and mutexes (multithreading) )
* Interfacing between USB stack and the driver. dwc_otg/dwc_otg_hcd_linux.c looks like the place to start.
the Linux bits of the headers are only required for the dwc_common_port library. dwc_common_port includes a variety of crypto functions which are not used – it appears to also be used for ultrawideband (UWB) and wireless USB (WUSB) drivers where crypto will be an issue, but it isn't going to be for plain wired USB.
Every USB driver acts as an USB hub as well in order to let Poseidon control the state of USB ports. The code there was reading status of the only USB port in Raspberry's CPU but when changing the status it erroneously deleted some of the status bits, including the port enable one. It was so because those bits in the status register are of a type Read/WriteToClear. It means, if one does not want to change their value from 1 back to 0, one has to actually write the 0 value. Very practical thing e.g. in interrupt handlers, where one reads the interrupt status register to learn what was the interrupt reason, and writes it back to the same register in order to clear the interrupts.
After fixing that code it turned out that the communication was still unsuccessful. Apparently the USB device was not understanding the host for some reason. That should not happen since the request sent was one of the standard ones implemented by virtually anything with an USB connector, assumed that Poseidon clears the data caches before forwarding the work to the USB drivers but that's the responsibility of the driver itself.
The USB device responded and acknowledged the transmission! But why were all the request sent after address change failing with timeout? They should not. Once again, address set is supported just by anything. Tried to contact the device at address 0 once again and there it was, still responding properly. The enlightenment came. The bus address for DMA transmissions was, as it is in many bare metal USB implementations, just the pure memory address of the buffer as seen by the ARM cpu. Have "prefixed" it with the real location of uncached RAM and booted AROS once again.
Trident saw this:
Product : Hub: Vdr=0424/PID=9514
Manufacturer: Standard Microsystems Corp.
SerialNumber: n/a
/Users/michal/git/AROS/rom/USB/poseidon/./poseidon.library.c:psd_20_psdEnumerateDevice/3092: USBVersion: 0200
Class : 9
SubClass : 0
DevProto : 2
VendorID : 1060
ProductID : 38164
DevVers : 0200
and this:
Product : Vendor: Vdr=0424/PID=EC00
Manufacturer: Standard Microsystems Corp.
SerialNumber: n/a
/Users/michal/git/AROS/rom/USB/poseidon/./poseidon.library.c:psd_20_psdEnumerateDevice/3092: USBVersion: 0200
Class : 255
SubClass : 0
DevProto : 1
VendorID : 1060
ProductID : 60416
DevVers : 0200
and even this:
Product : Hub: Vdr=0424/PID=9514
Manufacturer: Standard Microsystems Corp.
SerialNumber: n/a
/Users/michal/git/AROS/rom/USB/poseidon/./poseidon.library.c:psd_20_psdEnumerateDevice/3092: USBVersion: 0200
Class : 9
SubClass : 0
DevProto : 2
VendorID : 1060
ProductID : 38164
DevVers : 0200
What are these things? The first one is USB hub built in the Raspberry. Thanks to this one the Pi machines (with exception of Pi0 and computing modules) have more than just one single USB port. The second one is the network chip in raspberry, the third one is my USB SD card reader which have just connected to see what happens. AROS tried, of course, to boot from it ;)
So, the first step towards working USB is done. The control transfers are working as you can see above. Next step is to implement bulk and interrupt transfers, having the basics in place. Finally some error handling will be added and USB for Pi will be as complete as the PC version.
[http://www.raspyfi.com/raspberry-pi-usb-audio-fix/ Issue with USB Audio]
Audio
The Pi 4B is the only Pi that can output HD Audio as an HD Audio passthrough bitstream, and it does it over HDMI. It's possible to use the two HDMI output for separate HDMI video and HDMI audio outputs to allow UHD HDR video and HD Audio with non-UHD HDR compatible AVRs.
The Pi3B+ and earlier will decode to PCM 5.1/7.1 and output over HDMI. HDMI is the only interconnect that has a standard for carrying Dolby True HD, DTS HD MA etc. as a bitstream - you can't carry it as a bitstream on any other interface.
Pi3 and Pi4 audio jack output derived from 12bit pulse width modulation is relatively poor. For better, choose USB Audio or I2C versions.
[https://github.com/raspberrypi/linux/tree/rpi-patches/sound/arm audio] and its [https://github.com/raspberrypi/firmware/issues/2 very high speed message passing interface type of thing VCHI]
The Model B+ added an additional voltage regulator for the audio output and an additional output driver to drive low-resistance loads like headphones. However it is still using pulse-width modulation (PWM), which has a major impact on sound quality
the old Raspberry Pi used a linear voltage regulator to provide the 3.3V to many of the components on the board while the new one uses a switching regulator. Both can perform reasonably well. However switch mode power supplies often show higher noise figures
Analogue audio
Audio over HDMI rev 1.3 & 1.4
Ethernet
10/100 BaseT Ethernet RJ45 socket
GPIO
GPIO shouldn't be too bad but bear in mind it is already accessed in places so they would need to allocate pins etc through it (e.g. sdcard to flicker the activity light, serial debug to output data on the GPIO pins)
Probably a resource rather than a device...
Started an i2c driver that will need to allocate GPIO pins. Feel free to work on it if you are interested ;p
GPU graphics with 2D and 3D acceleration
Sadly none yet for 32bit but for 64bit...
Miscellanous
hdmi issues
Setting the hdmi_force_hotplug=1 makes sure the Pi believes the monitor/TV is really there.
You might also need to set config_hdmi_boost=4 or even higher (up to 9) if your display needs a stronger signal.
If the display is a computer monitor or newer tv, use hdmi_group=1 (auto HDMI use) and if it is an older TV, try hdmi_group=2 (for DMT formats, i.e. for PC monitors) then you HAVE to "set hdmi_drive = 2 to enable HDMI output as this forces HDMI mode rather than DVI mode
Do not set hdmi_safe=1 as that overrides many of the previous options.
Using a shorter or better quality HDMI cable might help. Make sure your Pi's power supply delivers 1 A and not 500 mA.
If you see a problem with the red colour - either absent, or interference - then try a boost
composite video
changing the RCA cable, then the composite port worked out of the box
Boot it as you are doing, without HDMI. If you now plug in the HDMI, do you get the image? In other words, does the Pi think HDMI is connected even when it isn't?
Rename all the files in the first partion of the card except bootcode.bin, start.elf and fixup.dat What's the result?
Put back config.txt What's the result?
for PAL mode sdtv_mode=2
dmi_ignore_hotplug Pretends HDMI hotplug signal is not asserted so it appears a HDMI display is not attached
hdmi_ignore_hotplug=1 Use composite mode even if HDMI monitor is detected
<pre>
# NOOBS Auto-generated Settings:
#hdmi_force_hotplug=1
#config_hdmi_boost=4
#overscan_left=24
#overscan_right=24
#overscan_top=16
#overscan_bottom=16
#disable_overscan=0
start_x=1
gpu_mem=128
</pre>
tvservice -c "PAL 4:3"
<pre>
/opt/vc/bin/tvservice -s or tvservice -s
state: HPD high|HDMI mode|HDCP off|composite off (0x12001a), 1920x1080 @ 60 Hz, progressive
/opt/vc/bin/tvservice -m CEA
Group CEA has 1 modes:
(native) mode 16: 1920x1080 @ 60 Hz, progressive
/opt/vc/bin/tvservice -m DMT
Group DMT has 0 modes:
</pre>
sudo amixer cset numid=3 1
forces the audio to the headphone jack, even with the HDMI video output plugged in
config.txt
the hdmi_ignore_edid_audio=1 option sems relevant as it should tell ALSA that the only available audio is analog, no matter what the display says
There are several different ways that these 4 pole (ring) composite analog cables can be wired up, so some work great in some applications and can be a waste of time in others.
What is needed for the Raspberry Pi B+ and above, which like many camcorders needs the ring contact next to the base contact to be the ground.
The wiring for the 4 pole are:
TIP (LEFT AUDIO CHANNEL)
RING 1 (RIGHT AUDIO CHANNEL)
RING 2 (GROUND/EARTH)
RING 3 BASE/SLEEVE (VIDEO) YELLOW
Most Apple based Players and the Microsoft Zune (TM) are wired this way.
Most analogue camcorders are wired this way as well, where the ground in on Ring 2 will work with the Pi although you may need to swap your Video plug with the Right Audio plug.
Nearly all other MP3 players are not wired this way, the ground is on another ring ie the wrong one.
External devices
* Camera Module Omnivision ov5647 Sunny 5MP (NoIR version) V1.3 - NoIR at 850 nm, peak at 880 nm and trails off at 940 nm wavelengths
* Camera V2 Sony IMX219 V2.1 8mpixel 8MP 8megapixel - 3280 x 2464 pixels - video at 1080p30, 720p60 and 640x480p90 - wider field of view, 62 vs 54 degrees horizontally -
* Branded WIFI usb BCM43143 dongle
N.B. dreaded error after changing cameras (stupidly without turning off the power first) and lasted through several power cycles. It can be a bad 15-pin FFC ribbon cable, when swapped, camera(s) and the Pi itself are working OK. It can be an instance of a cold solder joint on the CSI connector on the pi board. the camera can be detected (that's done via I2C) but may still not be able to receive image data (done via CSI-2) if something is broken. CSI-2 is uni-directional. Control is generally done via I2C.
The CSI-2 receiver always writes to memory, not direct to the ISP. That's the way the Broadcom architecture works as it allows multipass processing easily. GPU memory is accessible from the ARM. Processing using the QPU graphics processors may be possible. currently the only supported sensor is OV5647 and IMX219. The linux drivers are all in the firmware blob, else you'd be looking at at least a man-month of work in a fully fledged imaging lab to do a decent tuning of the camera modules' ISP parameters.
Static electricity maybe an issue for the camera module and slightly less for the pi board.
== References ==
===Good sites to visit===
*[https://github.com/raspberrypi/firmware/tree/master/ Raspberry Pi Firmware build]
*[https://www.raspberrypi.com/documentation/computers/software-sources.html Documentation]
*[https://rpilocator.com/ RPiLocator]
Linux only
*[https://github.com/raspberrypi/linux Raspberry Pi Linux Build]
*[https://dietpi.com/ DietPi]
*[http://www.tinycorelinux.net/ports.html piCore]
*[https://wiki.alpinelinux.org/wiki/Raspberry_Pi Alpine Linux]
*[https://github.com/armbian/build Armbian]
*[ FydeOS]
*[ TwisterOS based on ChromiumOS]
*[https://note.com/jamesmondo/n/nc76e31402be8?hl=en BSD]
*[https://www.raspberrypi.com/software/operating-systems/ PiOS Lite] and then [https://hstwb.firstrealize.com/ HST]
*[ PiMiga for pi4 and pi5]
*[ amibian for pi2 and pi3]
*[ retropie pi1 and 2]
Other alternative lighter smaller than Pi OS
*[https://aros.sourceforge.io/nightly1.html Aros 64bit ARMV8 single core]
*[https://www.riscosopen.org/wiki/documentation/show/Welcome%20to%20RISC%20OS%20Pi RiscOS on Pi3 and Pi4]
*[https://github.com/michalsc/Emu68 ARM based realtime JIT 68k for amiga computers]
*[https://github.com/JJDSNT/bellatrix/releases/ Alternative use of Emu68 on Pi3b]
*[https://github.com/stevereaver/uaos uaOS with Emu68k]
*[https://github.com/aros-development-team/AROS/commit/f80a268607dfae81b2db94755ab4e4d31ccb72d6 m68kemu library reference]
*[ HaikuOS]
*[https://github.com/raspberrypi/noobs NOOBS] os loader with successor [https://github.com/procount/pinn PINN]
*[https://github.com/maxnet/berryboot berryboot]
*[https://github.com/brianwiddas/pi-baremetal Bare Metal Access on Pi 32bit]
Testing procedure is put sd card in, connect board to board if necessary, plug in hdmi and then power nothing else is done especially CSI DSI etc
[https://www.raspberrypi.com/documentation/computers/compute-module.html CM5] has the same 55mm x 40mm 2x100pin connectors form factor as the CM4 but [https://www.epdtonthenet.net/article/214508/Key-Considerations-When-Migrating-from-Raspberry-Pi-CM4-to-CM5.aspx some pins and other small things] have changed. Will need the [https://raspipcb.com/tech-blog/raspberry-pi-cm4-vs-cm5-difference-in-booting-from-sd-card/ right IO board to suit]
*Green [ Raspberry Pi Compute Module 5 IO Board REV2 [https://pip.raspberrypi.com/categories/1097-raspberry-pi-compute-module-5-io-board SC1967]] - untested
*Green [ RPi Compute Module 5 IO board REV1 [https://pip.raspberrypi.com/categories/1097-raspberry-pi-compute-module-5-io-board SC1751]] - untested
*Black SupTronics Geekbord X1500 CM5 IO Carrier Board - untested
*Black DeskPi Super6C Cluster Mini-ITX Board - untested
*[https://sipeed.com/nanocluster Sipeed NanoCluster] - untested up to 7 CM5
*Green BentoIO CMX0 - untested
*Box EDATec ED-CLAWBOX - untested
*Home Assistant Yellow - Kit with PoE with Raspberry Pi Compute Module 5 - untested
*Blue [https://www.waveshare.com/wiki/CM5_PoE_BASE_A Waveshare CM5-PoE-BASE-A] - untested
*Box Waveshare [ CM5-POE-BOX-A] - untested
*Blue [https://www.waveshare.com/wiki/CM5-IO-BASE-B Waveshare CM5-IO-BASE-B] - untested
*Blue [https://www.waveshare.com/wiki/CM5-IO-BASE-A Waveshare CM5-IO-BASE-A] - untested
*Blue Waveshare [https://www.waveshare.com/wiki/CM5-NANO-B CM5-NANO-B] - untested
*[https://carboncomputers.us/products/pi-flux piFlux]
*[https://carboncomputers.us/products/ Zitaotech Hackberry] CM5 lite only -
*Portable [https://www.waveshare.com/pocketterm35.htm Waveshare PocketTerm35] with Pi4B or Pi5 - untested
*Box [https://www.clockworkpi.com/uconsole ClockworkPi uConsole][https://www.youtube.com/watch?v=EtI_bAahbR8 CM4 into an adapter or CM3 into so-dimm - Cyberdeck] - untested
*Green RPi [https://datasheets.raspberrypi.com/cm4io/CM4IO-KiCAD.zip Compute Module 4] [https://datasheets.raspberrypi.com/cm4io/cm4io-datasheet.pdf IO board] V1.4 [https://datasheets.raspberrypi.com/cm4io/CM4IOUSB3-KiCAD.zip USB3] [https://datasheets.raspberrypi.com/cm4io/cm4iousb3-appnote.pdf CM4ISO] [https://datasheets.raspberrypi.com/cm4/cm4-datasheet.pdf Dual100pin] (2020) aka Development Platform Board - untested
*Purple Pi Hut Cytron CM4 Maker Board - untested
*Black DeskPi Super6C Cluster Mini-ITX Board - untested
*[ KubeSail PiBox mini 2]
*Home Assistant Yellow with Raspberry Pi Compute Module 4 - untested
*[ Turing Pi V2] - untested CM4 with 260-pin SO-DIMM socket adapters and/or nvidia jetson nanos - untested
*Blue [https://www.waveshare.com/wiki/CM4-IO-BASE-C Waveshare CM4-IO-BASE-C] - untested but binary blobs Rev01 Rev02
*Blue [https://www.waveshare.com/wiki/CM4-IO-BASE-B Waveshare CM4-IO-BASE-B] - untested but binary blobs
*Blue [https://www.waveshare.com/wiki/CM4-IO-BASE-A Waveshare CM4-IO-BASE-A] - untested but binary blobs
*Blue [https://www.waveshare.com/wiki/CM4-NANO-B Waveshare CM4-NANO] - untested but usb and audio turned off or rerouted
*Black [ Seeed Studio with BigTreeTech BTT pad 7] - bin blobs?
CM3 has a 200 pin sodimm ddr2 connector form factor but not electrically SC0028, SC0029
*Blue [https://wiki.geekworm.com/CM_IO_Board Geekworm RPi Compute Module IO Board] [https://github.com/geekworm-com/cm-io-board CSI DSI] with CM3 in ddr2 slot underside - '''works''' if SW1 on but CM3+ '''does not'''
*Green [https://cdn-shop.adafruit.com/product-files/3442/CMIO_schematic.pdf RPi V3 IO board CM3IO] and CM3 Lite - untested
*Green [https://turingpi.com/ turingpi v1 cluster] - untested up to 7 cm3 7xlan9514 12V discontinued, 3 x Pi4 homelab maybe better
*Blue [https://www.waveshare.com/wiki/Compute_Module_PoE_Board Waveshare Compute Module PoE Board] and CM3 lite (if not lite, write files to internal eMMC fat32) '''AVOID''' bin blobs
*Blue [https://www.waveshare.com/compute-module-io-board-plus.htm Waveshare Compute Module IO Board Plus] [https://www.waveshare.com/wiki/Compute_Module_IO_Board_Plus wiki] [https://forums.raspberrypi.com/viewtopic.php?t=235695 pin settings] with CM3+ Lite - '''AVOID''' binary blob
*[ Pi02w on Geekworm SupTronics X305 Raspberry Pi Zero IO Baseboard] - untested
*[ Spotpear Pi Zero 2w to Pi3b format-ish] - untested
*[ pi-top v4] box has 128x64 oled display, micro hdmi, 19Whr battery with pi4 and 15V PD 36W min needed
*[ pi-top v3] three green pieces, heatsink covers most of the base tray, pi-top hub mk1 lhs and Pi1B Pi2b Pi3b rhs secured from below, black rounded strip with pi-top above keyboard, 13.3" HD 1366 x 768 display, small touchpad,
*[ pi-top Model 2.0] pi-top on bottom bezel of 14-inch green laptop, large trackpad, keyboard slide down to reveal main system hub on slide rails moved to the right, Raspberry Pi3b screws down, hub slides in, 18V 2.5A 45W charger brick, battery 11.1V 3500mAh 38.85Wh and storage PiTopOS
*[ Pi-Top CEED Raspberry Pi Modular Educational Desktop with RPI3] monitor
*[https://www.indiegogo.com/en/projects/jesselozano/pi-top-a-raspberry-pi-laptop-you-build-yourself Pi-Top v1] wedge laptop with RPi2
<pre>
2008 Trustees collected for Foundation
2009 Pi Foundation charity status gained
2010
2011 First Raspberry prototypes
2012 First boards go on sale at CPC and RS. The Model A and B 700 MHz Arm11 - February 29th BCM 2835
2012 First million sold - more than the 10,000 original planned and anticipated
2013 First Alpha Experimental builds of AROS Native for the 32bit Pi
2013 Pi Trading launched making grants available, providing in house educational resources and Pi Academy for teacher training
2013 Over two million sold
2014 Over three million sold
2014 Pi 1 Model B+ introduced that moved composite video to audio jack and same half gig of memory
2014 Pi Model A+ v1.1 no ethernet and 1 usb - a little smaller -
2015 Over four million first gen pis sold
2015 Pi Zero 1.2 BCM2835 first production revision released with no camera port
2016 Pi0 1.3 released with camera csi connector
2017 Pi Zero W v1.1 1GHz Pi0W, single-core 32bit CPU BCM2835 released with Cypress CYW43438 wireless
2020 Raspberry Pi Pico SC0919 with RP2040 32-bit 2Core ARM Cortex-M0+ up to 133 MHz - 264KB of SRAM and 2MB of on-board QSPI Flash -
2024 Raspberry Pi Pico 2 with RP2350 2Core 32bit Arm Cortex-M33 and 2core open-hardware [https://github.com/wren6991/hazard3 Hazard3 RISC-V]
2015 Pi 2 Model B v1.1 BCM2836 900/600 MHz ARM Cortex-A7 Armv7 quad 32bit, 32bit VideoCore IV GPU - 1Gb RAM - 5V 2A micro usb - SMSC LAN9514 chip -
2015 Over a million pi2s sold
2015 Raspberry Pi 2 Model B version 1.2 Pi2bv1.2, aka Pi2B2 has armv8 BCM2837 underclocked to 900Mhz without wifi/bluetooth module
2016 Pi 3 Model B - Broadcom BCM2837 SOC four 64bit ARMv8 Cortex-A53 1.2GHz 32bit 1080p VideoCore IV GPU - 1Gb DDR2 - bluetooth 4.1, Cypress CYW43438 wireless 802.11n - 4 x USB2.0 ports - 5.1V 2.5A - SMSC LAN9514 chip
2016 PIs total over 10 million worldwide
2017 Compute Module 3 CM3 with BCM2837B0 armv8 Quad 64-bit - small 67.6mm x 31mm board which fits DDR2 SODIMM connector but not electrically compatible which plugs into needed IO board - beware of the I2C protocol issue
1Gb LPDDR2 RAM - Lite or 4Gb Emmc storage
2017 12 million pis sold in total
2018 Pi 3 Model B+ - 4c A53 BCM2837B0 1.4Ghz - 1Gb, wireless 802.11ac, gigabit ethernet (300Mbit/s) and bluetooth 4.2 - power over ethernet - 4 x USB2.0 ports - Microchip LAN7515 chip
2019 Over 15 million sold
2019 Pi 3 Model A+ with BCM2837b0 Cortex-A53 64-bit SoC @ 1.4 GHz with 512Mb LPDDR2, 1 usb2, 1 hdmi, 1 micro usb 5V 2A - no ethernet -
2019 Raspberry Pi Compute Module 3+ CM3+ - Broadcom BCM2837B0 1.2Ghz, Cortex-A53 (ARMv8) 64-bit SoC on DDR2 SODIMM mechanically compatible only factor - IO board required
1Gb DDR2 and 8GB, 16GB, 32GB or a Lite variant without eMMC
2021 Pi zero 2 (w or no W) RP3A0 quad 1GHz Cortex-A53 64bit BCM2710A1 512mB SDRam
2025 edaTEC CM0 ED-CM0NANA with additional dev board with quad 1Ghz A53 with 512Mb Raysan RAM, 2 USB2 and 10/100 ethernet - pico castellated edge
2019 Pi 4 Model B RPI4B - BCM2711B0T quad 64bit A72 1.5GHz, 4K VideoCore VI, AC wifi, Bluetooth 5.0, GbE Broadcom BCM54213PE (PHY ID 0x600d84a2), 2 micro hdmi decode up to 4K, USB-C 5.1V 3A power, 2xVLI VL805 USB 3, 2xUSB 2.0, 2GB 9LDWW D9WHZ or 4GB 9FDWW D9WHV, 8GB 0AA47 D9ZCL ddr4 ram
2020 Silent Pi 4 v1.2 upgrade with more USB-c psu support
2020 PI400 BCM2711C0T 1.8GHz 4Gb DDR4 inside keyboard, 5.1V 5A 27W usb-c psu, 2 micro hdmi, external ide style 40pin gpio, no audio port -
2020 Raspberry Pi Compute Module 4 BCM2711B0T on new 55mm x 40mm 2x100 pin form factor with extra breakout IO board
CM4101000 1Gb RAM Lite SOM
CM4102000 2GB RAM Lite
CM4104000 4GB RAM Lite
CM4004008-4GB-RAM 8GB-EMMC SOM System on Modules
CM4104032 4GB RAM 32GB emmc
CM4108000 8GB RAM Lite
CM4008016 8GB RAM 16Gb eMMc
2021 Raspberry Pi SC0763 Compute Module 4S CM4S with ddr2 sodimm pinouts but not electrically the same with suitable IO board extra cost -
CM4S01000 1GB RAM Lite
CM4S01008 1GB RAM 8GB eMMC Flash
CM4S02000 2GB RAM Lite
CM4S04000 4GB RAM Lite
CM4S04016 4GB RAM 16Gb KLMAG1JETD-B041
CM4S08000 8GB RAM Lite
2021 Pi 4 v1.4 BCM2711B1 upgraded power regulator, to deal with 8gig of ram being more power hungry -
2021-48 Raspberry Pi 4 model B v1.5 2GB
2023 Pi 5 v1.0 BCM2712 Quad A76 @2.4Ghz - VideoCore VII - no audio socket - dual 4k from mini hdmi - fan connector - 5.1V 5A psu
2024 Pi 5 2GB DDR4 version uses BCM2712D0
2024 Pi-500 with 8Gb LPDDR5 and membrane keyboard
2024 Pi 5 v1.1
2024 Raspberry Pi Compute Module 5 CM5 BCM2712 55mm x 40mm form factor with additional IO board
CM5004000 04GB RAM 0GB eMMC Lite
CM5008000 08GB RAM 0GB eMMC Lite
CM5016000 16GB RAM 0GB eMMC Lite
2025 Pi-500+ with 256GB NVMe storage, 16GB LPDDR4 RAM, and Gateron KS-33 Low Profile Blue mechanical keyboard switches
2025 Pi5 1GB DDR4 announced
2022 PiOS linux goes 64bit
2024 Pi Trading IPO stockmarket stock exchange listing
2026 April and May Aros 64bit fixed, added AHI audio, VC4 gfx started, usb functions added to rom
2026 June and July Aros 64bit usb2otg started, dma.resource, sdio.resource, bwfm.device wifi added
2026 Late July daily 64bit Pi3 LE little endian builds start
2026 August Pi 4, 400, 5 and 500 DTBs added, expanding existing support and wifi for Pi4 and Pi5
2026 August Pi5 HAT+ nvme and HDMI, AHI RPiI2S added, Pi4 HVS5 video scaler started,
2026
2027
2028 Pi 6
</pre>
The vcgencmd can be used to inspect and dump the current system configuration.
vcgencmd runs on top of VCHIQ as an RPC. The mailbox interface is an alternate but much simpler RPC.
VCHIQ is a bridge (queue) between the CPU and the GPU so they can communicate with the firmware.
Loads of [https://github.com/6by9/rpi3-gpiovirtbuf/blob/master/rpi3-gpiovirtbuf.c mailbox] which uses the GPIO control calls. [https://github.com/raspberrypi/firmware/wiki/Mailboxes may also be of interest]
A fair number of vcgencmd examples (search for vc_vchi_gencmd_init). [https://www.raspberrypi.org/forums/viewtopic.php?t=229203#p1406112 sends the relevant vcgencmd commands] to update the scaling kernel, but the [https://github.com/raspberrypi/userland/blob/master/host_applications/linux/apps/gencmd/gencmd.c command] is just a text string. Parsing and execution of the instructions is performed by the VideoCore firmware.
The Raspberry Pi runs two separate operating systems: Linux/Aros on the ARM, and a threedx RTOS called vcos running on the Videocore 4 VPU: vcos is commonly called "the firmware". Vcos is tasked with performing certain system services, for example running the display and audio outputs. The VCHI driver provides an interface to allow drivers to talk to vcos.
Doubtful, on any [https://www.web3d.org/ Web3d] [https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API WebGL] or [https://github.com/immersive-web/webxr WebXR] [https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API Device API] [https://developer.mozilla.org/en-US/docs/Web/API/XRInputSource XRInputSource] support. Hopefully, never/limited support features like location, peer-to-peer, invasive web apps, unwarranted storage, payments, proprietary video streaming etc
*spreadsheet [https://git.sheetjs.com/sheetjs/sheetjs sheetjs] [https://github.com/mleibman/SlickGrid SlickGrid] [https://github.com/6pac/SlickGrid SlickGrid] [https://github.com/jspreadsheet/ce jspreadsheet ce] [https://github.com/dream-num/Luckysheet Luckysheet] [https://github.com/ruilisi/fortune-sheet fortune-sheet] [https://github.com/dream-num/univer/ univer] probably without xlsx support
*presentations [https://github.com/impress/impress.js/ impress.js simplified] [https://github.com/bwlewis/slides slides] [https://zenomt.github.io/mdslides/ github markdown slides] [https://github.com/Patternslib/slides Patternslib slides markdown] probably without pptx support
*weather [https://github.com/kaushalsahu07/weather weather], [https://github.com/Himanshu3412/Weather-Forecast Weather Forecast],
==Future==
[https://github.com/ARMSX2/ARMSX2 Arm pi of pcsx2]
[https://tube.cadence.moe/ Cloudtube], [https://github.com/TeamPiped/documentation/blob/main/content/docs/public-instances/index.md TeamPiped], [], [], [],
[https://hyperpipe.codeberg.page/ hyperpipe], [https://ytify.pp.ua/ ytify], [], [],
[ ytdl], [https://github.com/golddominik893/liberatube liberatube]
[https://git.lolcat.ca/lolcat/4get 4get], [https://github.com/hnhx/librex librex], [], [],
{{BookCat}}
c72lgenuhjpocxucfbf61lwjz9qu38g
Seed Factories/Introduction
0
288346
4676010
4675813
2026-10-14T10:54:09Z
Danielravennest
13526
Update through end section 3.0
4676010
wikitext
text/x-wiki
{{DISPLAYTITLE:<span style="display:block;text-align:left;font-size:100%;background:#d0f0f0;line-height:2.5em; font-family:'Georgia', serif;">Chapter 1.0 - Introduction</span>}}
<div class="nonumtoc">{{TOCright}}</div>
<div style="font-size:125%; font-family:'Georgia', serif;">
 In engineering, a '''[[w:System|System]]''' is a group of related elements that act by rules to form a whole. Systems are distinct entities with boundaries, surrounded by their environment. They are defined for purposes like understanding, analysis, design, and improvement. Systems can include people, and any other kinds of elements.
 Systems have characteristics of interest, such as quality of life, size, emissions, and output rate. Their change in a desired direction is considered an improvement. Self-improvement is when the change is produced by internal action of the system. It has occurred throughout history in many ways, such the as evolution of life, and the development of civilization.
 Through history, large-scale systems like cities have grown, and made major improvements to themselves. But intentional design for growth and self-improvement has been rare. Designing from the start to avoid side effects like environmental damage and pollution is even rarer. We think future changes to existing systems, and newly made ones, should include such design features. So these volumes are mostly future-oriented, describing types of projects that haven't been done before, and for which few people have experience with. This is in comparison to mature fields like '''[[w:Civil_engineering|Civil Engineering]]''', where there are many past examples of construction projects, and many people with skills and experience in developing them. However the new features are in addition to the knowledge and experience from more mature fields, not a replacement.
==<span style="font-size:x-large; font-family:'Georgia', serif;">1.0 - Volume Overview</span>==
 
 Note that both volumes in this set are incomplete works-in-progress. They present work we have done so far, but are far from finished. Longer chapters are divided into numbered pages, and pages divided into sections and subsections for easier cross-reference.
 In this volume we consider self-improvement generally, and a particular example called a '''Seed Factory'''. This is a system that includes a starter set of equipment intentionally designed to improve by a repeating process:
 Part of the factory's capacity is used to make more or better equipment for the factory itself. The remaining capacity is used to make useful products, like any other factory. The fraction used for self-improvement can vary over time, according to whatever goals the factory operators choose. The added equipment increases the ability to make the next round of equipment and further improve. Output capacity increases as you add more equipment. So if a significant fraction of output is devoted to improvement then total capacity can grow exponentially. This idea matters because civilization faces a number of large-scale problems which can only be addressed by large-scale solutions. Exponentially growing systems can provide the necessary scale.
 This Chapter (1.0) introduces some of the problems, how the systems engineering method can be used to develop solutions, and some examples of self-improving designs we will detail later.
 '''[https://en.wikibooks.org/wiki/Seed_Factories/History Chapter 2]''' discusses the history of self-improvement in nature and in human civilization, and how those led to the problems we face. We then look at self-improvement as an idea. It is closely related to other ideas like progress and economic development. More recently, ideas like self-replicating systems, and technologies like computers and automation, have led to the concept of a seed factory as an instance of self-improvement. It is still a fairly new approach, so Chapter 2 finishes with what we don't know about it yet, and areas for further research and development.
 If new systems are going to address current problems, and not create new ones as a result, they need to be carefully planned and designed before building and operating them. Engineering is already a well-developed field, so we will not cover all of what already exists. Instead, the next two chapters cover what is new in our approach from a technical engineering standpoint. Note that small and simple projects and systems with minimal side effects don't need much planning and design. There are existing tools, machines, supplies, plans, instructions, and people with experience to carry them out.
 '''[https://en.wikibooks.org/wiki/Seed_Factories/Basics Chapter 3]''' presents new design elements to include in the design process. This includes the current state of the seed factory idea, the pieces which make it up, and a reference architecture for system designs.
 '''[https://en.wikibooks.org/wiki/Seed_Factories/Design Chapter 4]''' discusses the design process itself. A constantly growing and improving system is complicated. So we apply the "systems engineering" approach which was developed to handle such complex projects. A complete system includes more than just factory equipment, but if it is intended to grow and self-improve it will use a number of production processes and equipment types. So we provide a reference list of many of the available options as inputs to the design process.
 '''Chapters 5 through 8''' are a series of design examples for use on Earth. The series is linked by the fact that one example can grow into or produce starter sets for later ones. The examples are intended to show how a design is developed, and also serve as a reference for building and operating them.
 The last chapter (9.0) of this volume is a set of notes that are too new or don't fit into the main discussion. It also serves as part of our project database.
 Space beyond Earth is of interest because of larger available resources and the potential to reduce or even reverse unwanted side effects on Earth. The environments and distances of regions in space are typically more extreme and larger compared to those on Earth. In addition, objects in space are all in fairly fast motion relative to Earth and each other compared to motions on Earth. So a second '''[https://en.wikibooks.org/wiki/Space_Transport_and_Engineering_Methods Volume II]''' addresses these differences. It begins with the relevant science and engineering methods that apply to space projects. We then continue the series of design examples for various space regions. For each region we summarize local conditions and available resources. These will affect how systems are designed for each.
 Space projects are presented in general order of distance from Earth and in difficulty from easier to harder. Since the first set of people and equipment must come from Earth, this is the approximate order projects in each region would get started. Also later and more difficult regions will be able get support both from Earth and previously developed regions.
==<span style="font-size:x-large; font-family:'Georgia', serif;">2.0 - Some Problems Facing Civilization</span>==
 
 These are engineering-oriented books. Engineering in general involves applying knowledge towards useful ends, such as satisfying people's needs, solving problems, or making life better. If seed factories are to be more than just an interesting idea, they should be developed with such useful purposes in mind. Here we identify some current and future problems facing civilization. This is by no means a complete list. Rather, they are problems we think worth solving, and could be addressed by technical solutions. The ideas and methods in these books can then be applied with these problems in mind.
:'''Insufficient Development'''
 Many places where people live have less of the artifacts and systems of civilization, and the benefits they bring, relative to intensely developed areas like large high-income cities. Even in the most developed areas it would be difficult to find people perfectly satisfied with their current situation. They can usually list a number of things they would like to improve, if only they had more time, money, or other resources. There is no shortage of desire for improvements. What is lacking are the means to make them happen. This is particularly true in difficult or hostile environments, where the extra work required has left them nearly or entirely undeveloped.
 In addition to uneven development, even the most developed areas have an uneven distribution of resources. Those who have the least lead a precarious existence, where any adverse event can seriously degrade their lives. So in addition to general development, we would like to enable backup systems, reserves, and other buffers against adversity.
:'''A Deteriorating Environment'''
 A healthy environment is necessary for us to live on Earth. But side effects of our current civilization have led to changes for the worse. Probably the most pressing environmental problem is excess carbon dioxide (CO<sub>2</sub>) leading to climate change. Others include deforestation, desertification, species extinction, and various kinds of pollution, like airborne particulates and micro-plastics. In the future we would like to minimize, eliminate, or reverse these side effects and the changes for the worse they have caused.
:'''Technological Unemployment'''
 Recent centuries have seen accelerating replacement of manual labor with powered equipment. This produced a shift from farming, which used to be people's main activity, to manufacturing and services. Continued improvements have reduced manufacturing labor, to where services are now the dominant activity in developed areas. Since about the mid-20th century, technologies like automation, robotics, software, and artificial intelligence have enabled "Smart Tools". These have an increasing ability to work on their own, replacing much of the remaining labor.
 Our modern economic system is based on people trading their specialized labor for money, then trading money for the other things they need and want. If most labor can be replaced by smarter tools, we get the problem of technological unemployment. The unemployed can no longer buy what they need, and the still-employed lose them as customers. The system of trading work for money and then money for other goods breaks down.
 This is not yet a severe problem. Through history, people displaced from one kind of work have found something else to do, and the changes were slow enough that young people could start in the new fields while older people aged out the old ones. But the recent advances in smart tools threaten to displace many jobs in fields like transportation, distribution, and retail in a short period of time. The displaced workers may not be able to find new jobs in other fields. It is worth thinking about how to deal with this potential problem ''before'' it becomes severe and we are faced with mass unemployment.
==<span style="font-size:x-large; font-family:'Georgia', serif;">3.0 - How to Tackle These Problems?</span>==
 
 Our civilization, and the parts that make it up, are very complex systems. A method called '''Systems Engineering''' was developed in the 20th century to deal with such systems. We propose to use it to address the problems noted above. The systems approach starts by defining the unmet needs which one or more systems are intended to satisfy. For existing systems this is in terms of what changes are needed. Identifying what is wanted comes before any consideration of designs or solutions. Having the answer in mind before stating the problem prematurely limits considering all the options. Goals should also not be limited by what is thought to be possible now. Partly meeting the goals, and identifying what research or improvements are needed for the rest is better than limiting our goals and going no further.
 We identified some problems in a general way above. For the systems approach we need to specify what we want more exactly. That way we can measure how well proposed designs or solutions meet the goals, which ones are better or worse, and in what direction to make improvements. We will start specifying wants here, and continue the systems process in later sections. Since civilization already exists, these statements are in terms of changes. The goal statements (in bold face) are followed by some explanations.
:'''(1) Bring less-developed parts of civilization up to [TBD] level of satisfaction with their situation, given sufficient information about their options. Increase satisfaction in more developed areas by [TBD] and provide means to deal with adverse events.''' - TBD means "to be determined". We haven't defined how to measure satisfaction levels yet. We know we want some kind of measure for it, so we use [TBD] as a marker for later work to fill in. Significant numbers of people lack education and information on what is possible, and therefore can't know what they would want if they had that knowledge. Supplying them with that knowledge so they can choose is part of the goal. Satisfaction with the current state of things is not enough if something bad happens, so we also want to be able to handle adversity.
:'''(2) Reverse human-caused environmental problems by [TBD] percent while minimizing side effects. To the extent possible, also minimize natural risks.''' - All human activities have side effects, so we can never entirely eliminate them. The goal is then to minimize them, and make them less harmful. The natural world also presents many hazards, like hurricanes and earthquakes. We can't eliminate these hazards either, but we can minimize the damage they cause.
:'''(3) Avoid or minimize future problems, such as technological unemployment.''' - Permanently displaced workers due to automation is one problem we already identified. There may be others we want to deal with ahead of time. Part of the goal is to identify them.
==<span style="font-size:x-large; font-family:'Georgia', serif;">4.0 - Systems and the Systems Engineering Method</span>==
 
 A "System" is any collection of elements which interact with each other and the outside world, and performs some identifiable function or transformation. For example, a computer system allows you to read this document on Wikibooks. It contains elements like a power supply, semiconductor chips, and software that work together. It interacts with you as the reader, and the Internet to access this page. If you were editing this page, you would be transforming it from one version to the next.
 We define systems to help with understanding, analysis, design, and improvement, and to help meet intended goals. Every system has a boundary. This is a mental construct rather than a wall or a fence. It separates the system from what is outside the system. In general the parts of a system are related in some way, and perform an identifiable function. Sometimes system boundaries are natural and obvious, such as an airplane vs everything outside the airplane. Other times system boundaries and their contents are arbitrary and in multiple pieces and places. Defining them can still be helpful in working on a project.
 A wide variety of things can cross the system boundary, and thus enter or leave the system. For example, a factory system can take in raw materials and power as inputs, and deliver finished products and various kinds of wastes as outputs. Physics tells us matter and energy can't spontaneously appear or disappear, only change form. So mathematically, the change in the contents of a system equals the flows entering the system minus the flows leaving.
 Systems can be any shape or size, and can contain other, smaller, systems. Smaller systems within a larger one are called "subsystems", which can in turn contain even smaller subsystems, to any level of depth. The human mind can't comprehend the entirety of a large complex system. So a key method in systems engineering is to break up large systems into smaller subsystems and sub-sub-systems, until they are small enough and simple enough to understand, design, build, etc. The flows at every level must still equal the change in subsystem contents, so straightforward bookkeeping can ensure nothing has been forgotten or lost in the total system.
 Having identified problems and set goals, the next step is starting to identify potential solutions that can meet them. At the start, we don't know what the best approach will be. So typically multiple candidates will be proposed or formulated. Over time, most of these will be weeded out and optimized, until one or a few best options remain. Research and testing may be needed before the final choices are made. The details of the process are more fully covered in '''[https://en.wikibooks.org/wiki/Seed_Factories/Design Section 4]'''.
 The premise of these books is that seed factories and self-improving systems can be part of the solutions to the problems noted above. That needs to be proven, though, and not just assumed. The examples we present and analyze will help to do that, but they need to be put to actual use and shown to work as expected.
 Self-improvement is a design feature. It is not a complete solution by itself. System designs must also include and build on past experience in fields like '''[[w:Industrial_technology|Industrial Technology]]''', other '''[[w:Engineering|Engineering]]''' fields, and other parts of our accumulated human knowledge. Those other subjects will be referenced and included where appropriate.
==<span style="font-size:x-large; font-family:'Georgia', serif;">5.0- Design Examples</span>==
 
 Chapters 5 through 8 describe four types of self-improving production systems. Each is intended to help solve the problems and meet the goals noted above. How we do this is by using particular approaches and features in their design.
 The first problem is that of insufficient development in terms of modern artifacts and systems. In principle this can be resolved by producing and delivering the needed items. But that presents several secondary problems. People in low-income areas may lack funds to pay for such things. Even if they were donated, they may not have the skills and experience to operate and maintain them. A solution to both secondary problems is to bootstrap their own production from seed factory starter sets and their own labor. They will need less funds to build the factories if they self-build them, and they can then make the other finished products they want. The experience gained in building the factories and making the products will then enable them to operate and maintain them later.
 In more developed areas, there are still widespread shortages of time, money, or resources to make improvements and increase satisfaction. Our approach to this is self-improving systems with a high level of smart tools. Starter sets take less money, smart tools take less time to operate, and the production systems can produce their own energy and obtain material resources. Due to the higher level of complexity and skills needed, these systems would likely be developed as cooperative projects involving many people.
 The second problem is risk from environmental damage and natural events. A start towards solving it is education about these risks and what can be done to reduce them. New systems can be designed to incorporate renewable energy, avoid or recycle wastes, reduce pollution, and maintain natural habitats. These design features would be included in both finished products and the production systems that make them.
 The third item is addressing future problems before they become urgent. An early task is to identify what those problems might be, besides technological unemployment that we already identified. Then the systems approach would be used to identify solutions or preventive measures, and incorporate them into system designs. The unemployment problem could be addressed by production systems of the types in our examples. Their owner-builders receive a share of their output directly, regardless of how automated the systems are, or how much labor is needed for their operation. In other words, the production systems work for their owners, so the owners don't have to, or as much.
 The four examples form a linked series of projects. One way to move through the series is by evolution. Enough improvements and growth can turn one example into the next. Another way is by setting up new seed factories for a later example. The various parts for new seed factories can be made by matured previous ones. A later example could also be started fresh by supplying equipment from elsewhere, or by some mixture of internal and outside sources. However they are started, the experience from earlier projects and their growth paths can be applied to later ones.
 The example systems are:
* '''[[Seed_Factories/Concept|Personal Production]] (Chapter 5)'''
 This example has the goal of making a range of basic products for a local community of owner/operators, such as food, building materials, and utilities. It is personal in the sense they make things for their own use and others in their community. It is not like a personal computer in having just one owner. It begins with a network of people interested in working together and conventional workshop tools. At first, production is at hobby and home-use scale. This keeps early costs within reach. To this they gradually add a starter set of seed machines. The combined collection is partly used to make more equipment, alongside the basic products.
 Later equipment is scaled in size to increase output, and more diverse to increase product range. The equipment eventually becomes too large for individuals to house, and too expensive for them to afford individually. The wider product range also becomes too complex for one person to have all the skills needed. The solution is building or acquiring larger and more dedicated production spaces, and have multiple owners with different skills who work together to make what is needed.
 There are two approaches to working together: distributed and centralized. In the distributed approach, each person owns one or a few pieces of equipment. A production request is then distributed as needed to the people and their equipment, who do their parts to make the product. In this approach, ways are needed to settle up the resources and costs in meeting each other's needs. In the centralized approach, the equipment is in one or a few larger places, with shared ownership. A mixed approach is also possible, part distributed and part centralized.
 As production grows beyond personal needs, the network can start to operate like a commercial workshop, building items for outside customers in addition to the local community. At the hobby and home-use scale, participation is mostly part-time, and the owners' main support is from conventional work. As production grows to commercial levels, some of the people can transition to full-time self-employment and have a large part of their physical needs supplied from within the network.
* '''[[Seed_Factories/WWF|The "Makernet"]] (Chapter 6)'''
 We define a '''Location''' as an area small enough that people can easily travel to work in person, and exchange products with each other. An example would be a US metropolitan area. In the Personal Production example, one location can then contain multiple home and dedicated sites where work is done. Since modern communications are worldwide, the network of people working together and exchanging items does not have to be restricted to a single location. So our second example extends the distributed approach to multiple locations in different parts of the world.
 Production sites are then network nodes that communicate by means such as the Internet. We call it a "Makernet" because the network collectively makes things. Owner-operators and customers can communicate with each other by any available method, including electronically. Smart production machines can also communicate with each other directly, or be controlled by people and software remotely.
 Shipping physical items long distances involves significant cost, energy, and time. Therefore makernet production will tend to be concentrated on items with higher value to mass ratios. At the high end, electronic design files for new machines and products have no mass, and can be sent anywhere at low cost. They are well suited for a worldwide network. At the opposite end crushed stone for construction is heavy and cheap. It will tend to be limited to a single location near the quarry rather than being shipped long distances.
 In a well-developed makernet, a customer may submit a product order to the network through a website. Production requests are then routed to various network nodes, who supply the materials, fabricate parts, and do other necessary steps. As each step is completed, payment is routed to the node. Eventually the finished item is delivered to the customer. Production nodes can contain any number of machines and processes. Since new machines can collectively be made by already existing nodes, a single seed factory starter set can in theory extend the network everywhere over time.
 For node operators, modern communications allows people to work remotely from the actual equipment. This has potential advantages in commuting cost and flexibility in hours and location. The Personal Production example is a local community at a single location. So much of the interaction can be in person or by voice. The Makernet approach emphasizes software and networking, with people doing things at times of their choosing, rather than on a work schedule in a conventional factory. New starter sets would tend to be optimized for size and mass, so they can be shipped farther at reasonable cost.
* '''[[Seed_Factories/Industrial|Industrial Production]] (Chapter 7)'''
 The goal of this example is large-scale production of more specialized products, much like conventional factories. It begins with smaller-scale commercial networks like the previous examples, or starter sets specifically designed to grow to industrial scale. In either case, growth by self-expansion should be a less expensive way to reach the desired production capacity. In one version, the starter sets are mobile, and are used like construction equipment. They are brought to a new industrial site and start making parts and equipment. Once the new factory reaches sufficient capacity, the seed factory components move on to the next project. In another version, a commercial-scale network grows in place to the larger industrial scale.
 Individual industrial sites grow towards scale and efficiency rather than diversity of outputs. This is partly because it gets harder to fit all the large equipment and operations in one place. Starter sets and small-scale production favor flexibility in what they can make, at the expense of being less efficient. At industrial scales, the individual machines can be optimized for their specific tasks. They are then easier to automate because they each do fewer different things.
 Industrial-scale sites can still operate as a network, and make things for each other as needed. However, the larger scale output goes well beyond the original owner's needs, or even the general needs of a given location They can then sell products directly to a wider market. They can also sell production shares to people who otherwise don't participate in site operations. Production shares entitle people to a share of the products made, either without further payment, or just to cover inputs like raw materials. An example of this would be a large-scale automated farm, whose shareholders then get a portion of the food produced. Industrial-scale sites can use conventional factory financing via capital markets if internal funding is not sufficient.
* '''[[Seed_Factories/Remote|Remote and Difficult Locations]] (Chapter 8)'''
 This book's last example is production in remote locations, or where environment conditions are difficult or extreme. In such locations, the benefit of self-expanding systems is not having to bring all the infrastructure with you. Instead, you bring a starter set and produce most of the rest locally. Examples of remote and difficult locations on Earth include deserts, polar regions, and the ocean surface. More extreme locations include high altitudes, ice caps, deep underground, or underwater. Current civilization mostly occupies a thin layer within 30 meters of about 13% of the Earth's surface. Extending it horizontally to the remaining area, and vertically beyond the first few meters would vastly increase available space and resources. The key to this is affordability, which self-expanding systems can help provide.
 The more difficult and remote the location, the higher the cost of transporting everything there, and the more incentive there is to use a small starter set and build locally. High levels of automation and productivity can make it possible to live and work in such locations by providing the infrastructure and resources needed. Remote controlled operation allows building up capacity without necessarily living there. For example, the Sahara Desert may be a great place to make solar panels, because of abundant sunlight and sand as inputs. But people may not want to live there full time. Working remotely can allow that choice. Conversely, if technology enables living in a remote location, it might be desirable for some people. Since other people don't live there, land would be cheap. It might be scenic or have other features people would prefer.
* '''Space (Volume II)'''
 The most remote and difficult places are regions in space beyond the Earth. Synchronous orbits, where many satellites operate, are twice as far as any two points on Earth can be, and the farthest known Solar System orbits extend ten million times farther than that. The space environment has a number of difficult or hostile conditions for people and other living things. This includes lack of breathable atmosphere and water, high radiation levels, and low gravity. On the other hand, space contains large amounts of untapped energy and material resources. If seed factories and self-expanding production can help make these resources accessible, the potential gain for civilization is enormous.
 Since the conditions are so different, and involve different engineering specialties and designs, we reserve discussion of their examples to a second volume on '''[https://en.wikibooks.org/wiki/Space_Transport_and_Engineering_Methods Space Systems Engineering]'''. The examples for space are linked to the previous ones for Earth in a couple of ways. First, industrial and in some cases remote and difficult locations are needed make and operate transportation to reach space. Second, the first seed factories to use in space must be designed and built down here, and some of their operation can be remotely controlled from Earth.
*'''[[Seed_Factories/Notes|Conceptual Design Notes]] (Chapter 9)'''
 The final section of this volume is a collection of material that is (a) too new or not organized enough for the main text, or (b) is too detailed and would interrupt the flow of the discussion. The ideas we present in these books are a work in progress, so the final section also serves as a kind of "engineer's notebook" to record that work. In the past, such notebooks were on bound paper or pages in file folders. Larger sketches and drawings were kept in drawers or rolls. Only a few people could access them and collaborate. The modern approach is a shared electronic database where everyone has access to the full contents. Our work is open-source and we encourage collaboration. So the notes in Section 9 form part of our database. Material that is not suited to the Wikimedia format will be stored elsewhere and linked from that section, and from other parts of both volumes.
</div>
{{BookCat}}
sx2ryy4wkqkvkd0cbjrh81h12lusu12
Template:Delete/doc
10
289937
4675829
4475792
2026-10-13T13:05:17Z
~2026-55040-66
3628329
4675829
wikitext
text/x-wiki
{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{Documentation subpage}}
<6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!!-- PLEASE ADD CATEGORIES AND INTERWIKIS AT THE BOTTOM OF THIS PAGE -->
This template indicates that a page may qualify for speedy deletion and adds it to [[:Category:Candidates for speedy deletion]] for review by administrators. Please familiarize yourself with [[WB:DP|Wikibooks' deletion policy]], before using this template on any pages.
=== Usage ===
{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{tlx|delete}}
* Use {{para|soon|<anything>}} to add a "soon" qualifier to the message.
* Use {{para|reason|<why>}} to explain why this page fits the criteria for speedy deletion.
* The form {{tlx|delete|''reason to delete''}} (i.e., with an unnamed parameter) can also be used.
=== See also ===
*{{tlx|rfd}}
*{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{tlx|Impending Doom}}
<includeonly>
<!-- CATEGORIES AND INTERWIKIS HERE, THANKS -->
[[Category:Deletion templates]]
[[aa:Template:Delete]]
[[af:Sjabloon:Delete]]
[[als:Vorlage:Löschen]]
[[ang:Template:Delete]]
[[as:Template:Delete]]
[[ast:Plantía:Delete]]
[[az:Şablon:Delete]]
[[ba:Ҡалып:Delete]]
[[be:Шаблон:Выдаліць]]
[[bg:Шаблон:Бързо_изтриване]]
[[bi:Template:Delete]]
[[bm:Modèle:Delete]]
[[bn:Template:Delete]]
[[bo:Template:Delete]]
[[ca:Plantilla:Fora]]
[[ch:Template:Delete]]
[[co:Template:Delete]]
[[cs:Šablona:Smazat]]
[[cv:Шаблон:Delete]]
[[cy:Nodyn:Delete]]
[[da:Skabelon:Slet]]
[[es:Plantilla:Borrar]]
[[et:Mall:Kustutada]]
[[fa:الگو:حذف_سریع]]
[[fi:Malline:Roskaa]]
[[ga:Teimpléad:Scrios]]
[[gl:Modelo:Lixo]]
[[gn:Tembiecharã:Delete]]
[[gu:Template:Delete]]
[[he:תבנית:מחק]]
[[hi:साँचा:Delete]]
[[hr:Predložak:Bris]]
[[hy:Կաղապար:Delete]]
[[ia:Patrono:Delete]]
[[ie:Template:Delete]]
[[it:Template:Cancella_subito]]
[[ja:Template:即時削除]]
[[kk:Үлгі:Delete]]
[[km:ទំព័រគំរូ:Delete]]
[[kn:ಟೆಂಪ್ಲೇಟು:Delete]]
[[ko:틀:Delete]]
[[ks:Template:Delete]]
[[la:Formula:Delenda_est]]
[[lb:Schabloun:Delete]]
[[ln:Modèle:Delete]]
[[lt:Šablonas:Delete]]
[[lv:Veidne:Delete]]
[[mg:Modèle:Delete]]
[[ml:ഫലകം:Delete]]
[[mk:Шаблон:Брзо бришење]]
[[mn:Template:Delete]]
[[mr:साचा:Delete]]
[[ms:Templat:Hapus]]
[[na:Template:Ai]]
[[nah:Plantilla:Delete]]
[[nds:Vörlaag:Delete]]
[[ne:Template:Delete]]
[[no:Mal:Hurtigsletting]]
[[oc:Modèl:Delete]]
[[pa:ਨਮੂਨਾ:Delete]]
[[pl:Szablon:Ek]]
[[ps:کينډۍ:Delete]]
[[pt:Predefinição:Lixo]]
[[rm:Template:Delete]]
[[ro:Format:Delete]]
[[ru:Шаблон:Delete]]
[[sa:Template:Delete]]
[[se:Template:Delete]]
[[si:Template:Delete]]
[[simple:Template:Delete]]
[[sl:Predloga:Delete]]
[[su:Citakan:Delete]]
[[sv:Mall:Radera]]
[[sw:Template:Delete]]
[[ta:வார்ப்புரு:Delete]]
[[th:แม่แบบ:ลบ]]
[[tk:Template:Delete]]
[[tl:Template:Delete]]
[[tr:Şablon:Sil]]
[[tt:Ürnäk:Delete]]
[[ug:Template:Delete]]
[[uk:Шаблон:Delete]]
[[uz:Shablon:Delete]]
[[vi:Tiêu_bản:Delete]]
[[vo:Samafomot:Delete]]
[[xh:Template:Delete]]
[[yo:Template:Delete]]
[[za:Template:Delete]]
[[zh:Template:Delete]]
[[zh-min-nan:Template:Delete]]
[[zu:Template:Delete]]
</includeonly>
gmtu9q61yk3anv1ai0eo0gxngogrh01
4675830
4675829
2026-10-13T13:05:44Z
Veritas Sapientiae
3399623
Reverted edits by [[Special:Contribs/~2026-55040-66|~2026-55040-66]] ([[User talk:~2026-55040-66|talk]]) to last version by MathXplore: reverting vandalism
4385031
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- PLEASE ADD CATEGORIES AND INTERWIKIS AT THE BOTTOM OF THIS PAGE -->
This template indicates that a page may qualify for speedy deletion and adds it to [[:Category:Candidates for speedy deletion]] for review by administrators. Please familiarize yourself with [[WB:DP|Wikibooks' deletion policy]], before using this template on any pages.
=== Usage ===
{{tlx|delete}}
* Use {{para|soon|<anything>}} to add a "soon" qualifier to the message.
* Use {{para|reason|<why>}} to explain why this page fits the criteria for speedy deletion.
* The form {{tlx|delete|''reason to delete''}} (i.e., with an unnamed parameter) can also be used.
=== See also ===
*{{tlx|rfd}}
*{{tlx|Impending Doom}}
<includeonly>
<!-- CATEGORIES AND INTERWIKIS HERE, THANKS -->
[[Category:Deletion templates]]
[[aa:Template:Delete]]
[[af:Sjabloon:Delete]]
[[als:Vorlage:Löschen]]
[[ang:Template:Delete]]
[[as:Template:Delete]]
[[ast:Plantía:Delete]]
[[az:Şablon:Delete]]
[[ba:Ҡалып:Delete]]
[[be:Шаблон:Выдаліць]]
[[bg:Шаблон:Бързо_изтриване]]
[[bi:Template:Delete]]
[[bm:Modèle:Delete]]
[[bn:Template:Delete]]
[[bo:Template:Delete]]
[[ca:Plantilla:Fora]]
[[ch:Template:Delete]]
[[co:Template:Delete]]
[[cs:Šablona:Smazat]]
[[cv:Шаблон:Delete]]
[[cy:Nodyn:Delete]]
[[da:Skabelon:Slet]]
[[es:Plantilla:Borrar]]
[[et:Mall:Kustutada]]
[[fa:الگو:حذف_سریع]]
[[fi:Malline:Roskaa]]
[[ga:Teimpléad:Scrios]]
[[gl:Modelo:Lixo]]
[[gn:Tembiecharã:Delete]]
[[gu:Template:Delete]]
[[he:תבנית:מחק]]
[[hi:साँचा:Delete]]
[[hr:Predložak:Bris]]
[[hy:Կաղապար:Delete]]
[[ia:Patrono:Delete]]
[[ie:Template:Delete]]
[[it:Template:Cancella_subito]]
[[ja:Template:即時削除]]
[[kk:Үлгі:Delete]]
[[km:ទំព័រគំរូ:Delete]]
[[kn:ಟೆಂಪ್ಲೇಟು:Delete]]
[[ko:틀:Delete]]
[[ks:Template:Delete]]
[[la:Formula:Delenda_est]]
[[lb:Schabloun:Delete]]
[[ln:Modèle:Delete]]
[[lt:Šablonas:Delete]]
[[lv:Veidne:Delete]]
[[mg:Modèle:Delete]]
[[ml:ഫലകം:Delete]]
[[mk:Шаблон:Брзо бришење]]
[[mn:Template:Delete]]
[[mr:साचा:Delete]]
[[ms:Templat:Hapus]]
[[na:Template:Ai]]
[[nah:Plantilla:Delete]]
[[nds:Vörlaag:Delete]]
[[ne:Template:Delete]]
[[no:Mal:Hurtigsletting]]
[[oc:Modèl:Delete]]
[[pa:ਨਮੂਨਾ:Delete]]
[[pl:Szablon:Ek]]
[[ps:کينډۍ:Delete]]
[[pt:Predefinição:Lixo]]
[[rm:Template:Delete]]
[[ro:Format:Delete]]
[[ru:Шаблон:Delete]]
[[sa:Template:Delete]]
[[se:Template:Delete]]
[[si:Template:Delete]]
[[simple:Template:Delete]]
[[sl:Predloga:Delete]]
[[su:Citakan:Delete]]
[[sv:Mall:Radera]]
[[sw:Template:Delete]]
[[ta:வார்ப்புரு:Delete]]
[[th:แม่แบบ:ลบ]]
[[tk:Template:Delete]]
[[tl:Template:Delete]]
[[tr:Şablon:Sil]]
[[tt:Ürnäk:Delete]]
[[ug:Template:Delete]]
[[uk:Шаблон:Delete]]
[[uz:Shablon:Delete]]
[[vi:Tiêu_bản:Delete]]
[[vo:Samafomot:Delete]]
[[xh:Template:Delete]]
[[yo:Template:Delete]]
[[za:Template:Delete]]
[[zh:Template:Delete]]
[[zh-min-nan:Template:Delete]]
[[zu:Template:Delete]]
</includeonly>
atzjeglw9ljyrpq67jivq66pako78pu
4675832
4675830
2026-10-13T13:06:11Z
~2026-55040-66
3628329
Undid revision [[Special:Diff/4675830|4675830]] by [[Special:Contributions/Veritas Sapientiae|Veritas Sapientiae]] ([[User talk:Veritas Sapientiae|discuss]])
4675832
wikitext
text/x-wiki
{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{Documentation subpage}}
<6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!!-- PLEASE ADD CATEGORIES AND INTERWIKIS AT THE BOTTOM OF THIS PAGE -->
This template indicates that a page may qualify for speedy deletion and adds it to [[:Category:Candidates for speedy deletion]] for review by administrators. Please familiarize yourself with [[WB:DP|Wikibooks' deletion policy]], before using this template on any pages.
=== Usage ===
{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{tlx|delete}}
* Use {{para|soon|<anything>}} to add a "soon" qualifier to the message.
* Use {{para|reason|<why>}} to explain why this page fits the criteria for speedy deletion.
* The form {{tlx|delete|''reason to delete''}} (i.e., with an unnamed parameter) can also be used.
=== See also ===
*{{tlx|rfd}}
*{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{tlx|Impending Doom}}
<includeonly>
<!-- CATEGORIES AND INTERWIKIS HERE, THANKS -->
[[Category:Deletion templates]]
[[aa:Template:Delete]]
[[af:Sjabloon:Delete]]
[[als:Vorlage:Löschen]]
[[ang:Template:Delete]]
[[as:Template:Delete]]
[[ast:Plantía:Delete]]
[[az:Şablon:Delete]]
[[ba:Ҡалып:Delete]]
[[be:Шаблон:Выдаліць]]
[[bg:Шаблон:Бързо_изтриване]]
[[bi:Template:Delete]]
[[bm:Modèle:Delete]]
[[bn:Template:Delete]]
[[bo:Template:Delete]]
[[ca:Plantilla:Fora]]
[[ch:Template:Delete]]
[[co:Template:Delete]]
[[cs:Šablona:Smazat]]
[[cv:Шаблон:Delete]]
[[cy:Nodyn:Delete]]
[[da:Skabelon:Slet]]
[[es:Plantilla:Borrar]]
[[et:Mall:Kustutada]]
[[fa:الگو:حذف_سریع]]
[[fi:Malline:Roskaa]]
[[ga:Teimpléad:Scrios]]
[[gl:Modelo:Lixo]]
[[gn:Tembiecharã:Delete]]
[[gu:Template:Delete]]
[[he:תבנית:מחק]]
[[hi:साँचा:Delete]]
[[hr:Predložak:Bris]]
[[hy:Կաղապար:Delete]]
[[ia:Patrono:Delete]]
[[ie:Template:Delete]]
[[it:Template:Cancella_subito]]
[[ja:Template:即時削除]]
[[kk:Үлгі:Delete]]
[[km:ទំព័រគំរូ:Delete]]
[[kn:ಟೆಂಪ್ಲೇಟು:Delete]]
[[ko:틀:Delete]]
[[ks:Template:Delete]]
[[la:Formula:Delenda_est]]
[[lb:Schabloun:Delete]]
[[ln:Modèle:Delete]]
[[lt:Šablonas:Delete]]
[[lv:Veidne:Delete]]
[[mg:Modèle:Delete]]
[[ml:ഫലകം:Delete]]
[[mk:Шаблон:Брзо бришење]]
[[mn:Template:Delete]]
[[mr:साचा:Delete]]
[[ms:Templat:Hapus]]
[[na:Template:Ai]]
[[nah:Plantilla:Delete]]
[[nds:Vörlaag:Delete]]
[[ne:Template:Delete]]
[[no:Mal:Hurtigsletting]]
[[oc:Modèl:Delete]]
[[pa:ਨਮੂਨਾ:Delete]]
[[pl:Szablon:Ek]]
[[ps:کينډۍ:Delete]]
[[pt:Predefinição:Lixo]]
[[rm:Template:Delete]]
[[ro:Format:Delete]]
[[ru:Шаблон:Delete]]
[[sa:Template:Delete]]
[[se:Template:Delete]]
[[si:Template:Delete]]
[[simple:Template:Delete]]
[[sl:Predloga:Delete]]
[[su:Citakan:Delete]]
[[sv:Mall:Radera]]
[[sw:Template:Delete]]
[[ta:வார்ப்புரு:Delete]]
[[th:แม่แบบ:ลบ]]
[[tk:Template:Delete]]
[[tl:Template:Delete]]
[[tr:Şablon:Sil]]
[[tt:Ürnäk:Delete]]
[[ug:Template:Delete]]
[[uk:Шаблон:Delete]]
[[uz:Shablon:Delete]]
[[vi:Tiêu_bản:Delete]]
[[vo:Samafomot:Delete]]
[[xh:Template:Delete]]
[[yo:Template:Delete]]
[[za:Template:Delete]]
[[zh:Template:Delete]]
[[zh-min-nan:Template:Delete]]
[[zu:Template:Delete]]
</includeonly>
gmtu9q61yk3anv1ai0eo0gxngogrh01
4675833
4675832
2026-10-13T13:06:28Z
CptViraj
3232362
[[WB:REVERT|Reverted]] edit by [[Special:Contributions/~2026-55040-66|~2026-55040-66]] ([[User talk:~2026-55040-66|talk]]) to last version by Veritas Sapientiae
4385031
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- PLEASE ADD CATEGORIES AND INTERWIKIS AT THE BOTTOM OF THIS PAGE -->
This template indicates that a page may qualify for speedy deletion and adds it to [[:Category:Candidates for speedy deletion]] for review by administrators. Please familiarize yourself with [[WB:DP|Wikibooks' deletion policy]], before using this template on any pages.
=== Usage ===
{{tlx|delete}}
* Use {{para|soon|<anything>}} to add a "soon" qualifier to the message.
* Use {{para|reason|<why>}} to explain why this page fits the criteria for speedy deletion.
* The form {{tlx|delete|''reason to delete''}} (i.e., with an unnamed parameter) can also be used.
=== See also ===
*{{tlx|rfd}}
*{{tlx|Impending Doom}}
<includeonly>
<!-- CATEGORIES AND INTERWIKIS HERE, THANKS -->
[[Category:Deletion templates]]
[[aa:Template:Delete]]
[[af:Sjabloon:Delete]]
[[als:Vorlage:Löschen]]
[[ang:Template:Delete]]
[[as:Template:Delete]]
[[ast:Plantía:Delete]]
[[az:Şablon:Delete]]
[[ba:Ҡалып:Delete]]
[[be:Шаблон:Выдаліць]]
[[bg:Шаблон:Бързо_изтриване]]
[[bi:Template:Delete]]
[[bm:Modèle:Delete]]
[[bn:Template:Delete]]
[[bo:Template:Delete]]
[[ca:Plantilla:Fora]]
[[ch:Template:Delete]]
[[co:Template:Delete]]
[[cs:Šablona:Smazat]]
[[cv:Шаблон:Delete]]
[[cy:Nodyn:Delete]]
[[da:Skabelon:Slet]]
[[es:Plantilla:Borrar]]
[[et:Mall:Kustutada]]
[[fa:الگو:حذف_سریع]]
[[fi:Malline:Roskaa]]
[[ga:Teimpléad:Scrios]]
[[gl:Modelo:Lixo]]
[[gn:Tembiecharã:Delete]]
[[gu:Template:Delete]]
[[he:תבנית:מחק]]
[[hi:साँचा:Delete]]
[[hr:Predložak:Bris]]
[[hy:Կաղապար:Delete]]
[[ia:Patrono:Delete]]
[[ie:Template:Delete]]
[[it:Template:Cancella_subito]]
[[ja:Template:即時削除]]
[[kk:Үлгі:Delete]]
[[km:ទំព័រគំរូ:Delete]]
[[kn:ಟೆಂಪ್ಲೇಟು:Delete]]
[[ko:틀:Delete]]
[[ks:Template:Delete]]
[[la:Formula:Delenda_est]]
[[lb:Schabloun:Delete]]
[[ln:Modèle:Delete]]
[[lt:Šablonas:Delete]]
[[lv:Veidne:Delete]]
[[mg:Modèle:Delete]]
[[ml:ഫലകം:Delete]]
[[mk:Шаблон:Брзо бришење]]
[[mn:Template:Delete]]
[[mr:साचा:Delete]]
[[ms:Templat:Hapus]]
[[na:Template:Ai]]
[[nah:Plantilla:Delete]]
[[nds:Vörlaag:Delete]]
[[ne:Template:Delete]]
[[no:Mal:Hurtigsletting]]
[[oc:Modèl:Delete]]
[[pa:ਨਮੂਨਾ:Delete]]
[[pl:Szablon:Ek]]
[[ps:کينډۍ:Delete]]
[[pt:Predefinição:Lixo]]
[[rm:Template:Delete]]
[[ro:Format:Delete]]
[[ru:Шаблон:Delete]]
[[sa:Template:Delete]]
[[se:Template:Delete]]
[[si:Template:Delete]]
[[simple:Template:Delete]]
[[sl:Predloga:Delete]]
[[su:Citakan:Delete]]
[[sv:Mall:Radera]]
[[sw:Template:Delete]]
[[ta:வார்ப்புரு:Delete]]
[[th:แม่แบบ:ลบ]]
[[tk:Template:Delete]]
[[tl:Template:Delete]]
[[tr:Şablon:Sil]]
[[tt:Ürnäk:Delete]]
[[ug:Template:Delete]]
[[uk:Шаблон:Delete]]
[[uz:Shablon:Delete]]
[[vi:Tiêu_bản:Delete]]
[[vo:Samafomot:Delete]]
[[xh:Template:Delete]]
[[yo:Template:Delete]]
[[za:Template:Delete]]
[[zh:Template:Delete]]
[[zh-min-nan:Template:Delete]]
[[zu:Template:Delete]]
</includeonly>
atzjeglw9ljyrpq67jivq66pako78pu
Template:Lua/doc
10
293582
4675918
4483841
2026-10-13T22:45:47Z
Koavf
16549
4675918
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- PLEASE ADD CATEGORIES AND INTERWIKIS AT THE BOTTOM OF THIS PAGE -->
{{hatnote|This template '''also''' uses Lua, and its module is at [[Module:Lua banner]].}}
{{lua|Module:Lua banner}}
This template is used to show that templates have been converted to [[w:Lua (programming language)|Lua]]. It can be placed on the template's /doc page or on its talk page. It automatically adds the template to [[:Category:Lua-based templates]].
== Usage ==
; Basic usage
{{tlx|lua|''module name''}}
; All parameters
{{tlx|lua|''module name''|''note''|4=category=''custom category''|5=nocat=''true''}}
== Examples ==
* {{tlx|lua}}
{{lua|nocat=true}}
* {{tlx|lua|Module:Collapsible list}}
{{lua|Module:Collapsible list|nocat=true}}
* {{tlx|lua|Module:Collapsible list|You can use this script as an example to help you get started.}}
{{lua|Module:Collapsible list|You can use this script as an example to help you get started.|nocat=true}}
== Categorization ==
This template adds pages to [[:Category:Lua-based templates]] if the page is in the template namespace, and it is not on any of the subpages /doc, /sandbox, /sandbox2 or /testcases. You can specify a different category with the {{para|category}} parameter, e.g. {{para|category|Lua String-based templates}}. To suppress categorization, use {{para|nocat|true}}.
== See also ==
* [[w:Wikipedia:Lua|Wikipedia:Lua]]
* {{tl|module rating}}
<includeonly>
<!-- CATEGORIES AND INTERWIKIS HERE, THANKS -->
</includeonly>
i8c7fsqsuwpfegum0maviu9l4mwfo9r
On 2D Inverse Problems/Two models
0
306309
4675931
3593534
2026-10-13T23:16:20Z
DVD206
724793
moving files landscaping
4675931
wikitext
text/x-wiki
Certain properties common to discrete and continuous Dirichlet-to-Neumann maps are
===[[On 2D Inverse Problems/On kernel and matrix|kernel and matrix]]===
<!--
=== [[On 2D Inverse Problems/Kernel of Dirichlet-to-Neumann map|Kernel of Dirichlet-to-Neumann map]] ===
=== [[On 2D Inverse Problems/Schrodinger equation|Schrodinger equation]] ===-->
<s>schreaded</s>
=== [[On 2D Inverse Problems/Variation diminishing property|Variation diminishing]] ===
=== [[On 2D Inverse Problems/Variation diminishing property|Dropped glass of wine]] ===
{{status|100%}}
[[User:DVD206|DVD206]] ([[User talk:DVD206|discuss]] • [[Special:Contributions/DVD206|contribs]]) 18:13, 4 November 2019 (UTC)
{{bookcat}}
c47bim81rr1h21dn7esyva9tjsez0w9
4675932
4675931
2026-10-13T23:16:51Z
DVD206
724793
/* kernel and matrix */
4675932
wikitext
text/x-wiki
Certain properties common to discrete and continuous Dirichlet-to-Neumann maps are
===The [[On 2D Inverse Problems/On kernel and matrix|kernel and matrix]]===
<!--
=== [[On 2D Inverse Problems/Kernel of Dirichlet-to-Neumann map|Kernel of Dirichlet-to-Neumann map]] ===
=== [[On 2D Inverse Problems/Schrodinger equation|Schrodinger equation]] ===-->
<s>schreaded</s>
=== [[On 2D Inverse Problems/Variation diminishing property|Variation diminishing]] ===
=== [[On 2D Inverse Problems/Variation diminishing property|Dropped glass of wine]] ===
{{status|100%}}
[[User:DVD206|DVD206]] ([[User talk:DVD206|discuss]] • [[Special:Contributions/DVD206|contribs]]) 18:13, 4 November 2019 (UTC)
{{bookcat}}
dp1uakl94havcq1a5w8op1vbmedpav8
On 2D Inverse Problems/Body
0
306318
4675866
4671485
2026-10-13T16:23:19Z
DVD206
724793
ai thoughts
4675866
wikitext
text/x-wiki
== [[On 2D Inverse Problems/Gemini conversation| AI thoughts]] ==
== [[On 2D Inverse Problems/Basic definitions and background| "By definition..."]] ==
<!--
=== [[On 2D Inverse Problems/Graphs and manifolds|Graphs and surfaces]] ===
=== [[On 2D Inverse Problems/Harmonic functions|Harmonic functions]] ===
=== [[On 2D Inverse Problems/On random processes|On random processes]] ===
=== [[On 2D Inverse Problems/Special matrices|Special matrices and determinants]] ===
=== [[On 2D Inverse Problems/Electrical networks|Electrical networks]] ===
=== [[On 2D Inverse Problems/The inverse problems|The inverse problems]] ===
-->
== [[On 2D Inverse Problems/Classics|Classics and hopscotch]] ==
<!--
=== [[On 2D Inverse Problems/On the inverse problem of Calderon|On the inverse problem of Calderon]] ===
=== [[On 2D Inverse Problems/"Can One Hear the Shape of a Drum?"|"Can One Hear the Shape of a Drum?"]] ===
=== [[On 2D Inverse Problems/On inhomogeneous string of Krein|On inhomogeneous string of Krein]] ===
-->
== [[On 2D Inverse Problems/Embedded| Digital veggies]] ==
<!--=== [[On 2D Inverse Problems/Medial graphs|Medial graphs]] ===
=== [[On 2D Inverse Problems/Y-Δ and star-mesh transforms|Y-Δ and star-mesh transforms]] ===
=== [[On 2D Inverse Problems/Two new spectral theorems|Two new spectral theorems]] ===-->
== [[On 2D Inverse Problems/Radial|The apple & onion case]] ==
<!--
=== [[On 2D Inverse Problems/Fourier coordinates|Fourier transform]] ===
=== [[On 2D Inverse Problems/Stieltjes continued fractions|Stieltjes continued fractions]] ===
=== [[On 2D Inverse Problems/Solution of the inverse problem|Solution of the inverse problem]] ===
-->
== [[On 2D Inverse Problems/The square root case|The square root of the operah/tor minus]] Garfield/Laplacian ==
<!--=== [[On 2D Inverse Problems/The case of the unit disc|The case of the unit disc]] ===
=== [[On 2D Inverse Problems/An infinite example|An infinite example]] ===
=== [[On 2D Inverse Problems/Zolotarev problem|Zolotarev problem]] ===-->
== [[On 2D Inverse Problems/Two models|Duel maps & naps]] ==
<!--
=== [[On 2D Inverse Problems/Kernel of Dirichlet-to-Neumann map|Kernel of Dirichlet-to-Neumann map]] ===
=== [[On 2D Inverse Problems/Riemann mapping theorem|Riemann mapping theorem]] ===
=== [[On 2D Inverse Problems/Schrodinger equation|Schrodinger equation]] ===
=== [[On 2D Inverse Problems/Variation diminishing property|Variation diminishing property]] ===
=== [[On 2D Inverse Problems/Spectral properties|Spectral properties]] ===-->
=== [[On 2D Inverse Problems/Notation|<math>notifications</math> & note notions]] ===
{{BookCat}}
faw3t3jazk7dtjxx1ho5u8j4tuz91cf
4675933
4675866
2026-10-13T23:24:11Z
DVD206
724793
trinary tree toc
4675933
wikitext
text/x-wiki
== [[On 2D Inverse Problems/Gemini conversation| AI thoughts]] ==
=== [[On 2D Inverse Problems/Basic definitions and background| "By definition..."]] ===
<!--
=== [[On 2D Inverse Problems/Graphs and manifolds|Graphs and surfaces]] ===
=== [[On 2D Inverse Problems/Harmonic functions|Harmonic functions]] ===
=== [[On 2D Inverse Problems/On random processes|On random processes]] ===
=== [[On 2D Inverse Problems/Special matrices|Special matrices and determinants]] ===
=== [[On 2D Inverse Problems/Electrical networks|Electrical networks]] ===
=== [[On 2D Inverse Problems/The inverse problems|The inverse problems]] ===
-->
=== [[On 2D Inverse Problems/Classics|Classics and hopscotch]] ===
<!--
=== [[On 2D Inverse Problems/On the inverse problem of Calderon|On the inverse problem of Calderon]] ===
=== [[On 2D Inverse Problems/"Can One Hear the Shape of a Drum?"|"Can One Hear the Shape of a Drum?"]] ===
=== [[On 2D Inverse Problems/On inhomogeneous string of Krein|On inhomogeneous string of Krein]] ===
-->
== [[On 2D Inverse Problems/Embedded| Digital veggies]] ==
<!--=== [[On 2D Inverse Problems/Medial graphs|Medial graphs]] ===
=== [[On 2D Inverse Problems/Y-Δ and star-mesh transforms|Y-Δ and star-mesh transforms]] ===
=== [[On 2D Inverse Problems/Two new spectral theorems|Two new spectral theorems]] ===-->
=== [[On 2D Inverse Problems/Radial|The apple & onion case]] ===
=== [[On 2D Inverse Problems/Notation|<math>notifications</math> & note notions]] ===
<!--
=== [[On 2D Inverse Problems/Fourier coordinates|Fourier transform]] ===
=== [[On 2D Inverse Problems/Stieltjes continued fractions|Stieltjes continued fractions]] ===
=== [[On 2D Inverse Problems/Solution of the inverse problem|Solution of the inverse problem]] ===
-->
== [[On 2D Inverse Problems/The square root case|The square root of the operah/tor minus]] Garfield/Laplacian ==
<!--=== [[On 2D Inverse Problems/The case of the unit disc|The case of the unit disc]] ===
=== [[On 2D Inverse Problems/An infinite example|An infinite example]] ===
=== [[On 2D Inverse Problems/Zolotarev problem|Zolotarev problem]] ===-->
=== [[On 2D Inverse Problems/Embedded| Embedded graphics and printed counts]] ===
=== [[On 2D Inverse Problems/Two models|Duel maps & naps]] ===
<!--
=== [[On 2D Inverse Problems/Kernel of Dirichlet-to-Neumann map|Kernel of Dirichlet-to-Neumann map]] ===
=== [[On 2D Inverse Problems/Riemann mapping theorem|Riemann mapping theorem]] ===
=== [[On 2D Inverse Problems/Schrodinger equation|Schrodinger equation]] ===
=== [[On 2D Inverse Problems/Variation diminishing property|Variation diminishing property]] ===
=== [[On 2D Inverse Problems/Spectral properties|Spectral properties]] ===-->
{{BookCat}}
2xveu1wyfmh6o7x1zkoapun2g6v2dxl
Template:Nav
10
308261
4675831
3348681
2026-10-13T13:05:48Z
~2026-55040-66
3628329
4675831
wikitext
text/x-wiki
<includeonly>{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{#invoke:Printable version|displays_footer<!--
-->|{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{{TOC|{{{1|{{#ifexist:{{BASEPAGENAME}}/TOC|{{BASEPAGENAME}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}/TOC|{{BASEPAGENAME}}}}}}}}}}<!--
-->|{{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{page|{{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{2|}}}}}}<!--
-->|programming<!--
-->}}{{#if:{{{nocat|}}}||{{BookCat}}}}{{#if:{{{lang|}}}{{{next|}}}{{{title_next|}}}{{{previous|}}}{{{title_previous|}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}}|[[Category:Navigation template with parameters]]}}</includeonly><noinclude>{{Documentation}}</noinclude>
37m8mm1cuqj968jw5sqmxfoqks2z2ld
4675834
4675831
2026-10-13T13:06:29Z
CptViraj
3232362
[[WB:REVERT|Reverted]] edit by [[Special:Contributions/~2026-55040-66|~2026-55040-66]] ([[User talk:~2026-55040-66|talk]]) to last version by Pi zero
3348681
wikitext
text/x-wiki
<includeonly>{{#invoke:Printable version|displays_footer<!--
-->|{{{TOC|{{{1|{{#ifexist:{{BASEPAGENAME}}/TOC|{{BASEPAGENAME}}/TOC|{{BASEPAGENAME}}}}}}}}}}<!--
-->|{{{page|{{{2|}}}}}}<!--
-->|programming<!--
-->}}{{#if:{{{nocat|}}}||{{BookCat}}}}{{#if:{{{lang|}}}{{{next|}}}{{{title_next|}}}{{{previous|}}}{{{title_previous|}}}|[[Category:Navigation template with parameters]]}}</includeonly><noinclude>{{Documentation}}</noinclude>
773ps282xbjh5zgogsgdjvpjiawe5k4
Talk:Radiation Oncology/Breast/Partial breast irradiation
1
371455
4675973
3083514
2026-10-14T05:58:01Z
Jcb
90773
4675973
wikitext
text/x-wiki
The following should be added to
===Meta-Analysis===
*'''Heraklion University, Greece; 2010''' {{PMID|20210799}} -- "Partial Breast Irradiation or Whole Breast Radiotherapy for Early Breast Cancer: A Meta-Analysis of Randomized Controlled Trials." (Valachis A, Breast J. 2010 Feb 23. [Epub ahead of print])
**Meta-analysis. 3 trials with 1,140 patients.
**Outcome: No difference in OS (OR 0.9, NS), DM (OR 0.7, NS), or SCV recurrences (OR 1.4, NS). However, PBI increased risk of local recurrence (OR 2.1, SS), and axillary recurrence (OR 3.4, SS) compared with whole breast RT
**Conclusion: PBI doesn't jeopardize survival but issue of locoregional recurrence needs to be addressed
**Letter to editor (Polgar C, {{PMID|20127229}}): Inappropriate to include the 2 "old" British trials using inadequate patient selections criteria
*'''Aarhus, Denmark; 2009''' {{PMID|18783840}} -- "Accelerated partial breast irradiation as part of breast conserving therapy of early breast carcinoma: A systematic review." (Offerssen BV, Radiother Oncol. 2009 Jan;90(1):1-13. Epub 2008 Sep 8.)
NEW material
A meta-analysis of randomised trials of partial breast irradiation (PBI) vs. whole breast irradiation (WBI) as part of breast conserving therapy (more than 4000 patients) demonstrated a reduction in non-breast-cancer and overall mortality. <ref>{{cite journal|last1=Vaidya|first1=Jayant S.|last2=Bulsara|first2=Max|last3=Wenz|first3=Frederik|last4=Coombs|first4=Nathan|last5=Singer|first5=Julian|last6=Ebbs|first6=Stephen|last7=Massarut|first7=Samuele|last8=Saunders|first8=Christobel|last9=Douek|first9=Michael|last10=Williams|first10=Norman|last11=Joseph|first11=David|last12=Tobias|first12=Jeffrey S.|last13=Baum|first13=Michael|title=Reduced mortality with partial breast irradiation for early breast cancer – a meta-analysis of randomised trials|journal=International Journal of Radiation Oncology*Biology*Physics|date=May 2016|doi=10.1016/j.ijrobp.2016.05.008}}</ref> [http://www.sciencedirect.com/science/article/pii/S0360301616302000 Full text and Audio Slides]
e0kndq3hccx4otpcdpe7i491cqdcaof
Haskell/Prologue: IO, an applicative functor
0
376672
4676015
4218416
2026-10-14T11:07:15Z
Luciérnaga de conocimiento
3401314
4676015
wikitext
text/x-wiki
{{clear}}
{{Haskell/Minitoc|chapter=Monads|noexercises=1}}
{{info|For shorter links to this chapter, be they within the book or off-wiki, you can use the [[Haskell/Applicative prologue]] redirect.}}
The emergence of functors is a watershed in the course of this book. The reasons for that will begin to reveal themselves in this prologue, as we set the stage for the next several chapters of the book. While the code examples we will work with here are very simple, we will use them to bring several new and important ideas into play, ideas that will be revisited and further developed later in the book. That being so, we recommend that you study this chapter at a gentle pace, which will give you space for thinking about the implications of each step, as well as trying out the code samples in GHCi.
== Scene 1 : <code>Applicative</code> ==
Our initial examples will use the function <code>readMaybe</code>, which is provided by the <code>Text.Read</code> module.
<syntaxhighlight lang="haskell">
GHCi> :m +Text.Read
GHCi> :t readMaybe
readMaybe :: Read a => String -> Maybe a
</syntaxhighlight>
<code>readMaybe</code> provides a simple way of converting strings into Haskell values. If the provided string has the correct format to be read as a value of type <code>a</code>, <code>readMaybe</code> gives back the converted value wrapped in <code>Just</code>; otherwise, the result is <code>Nothing</code>.
<syntaxhighlight lang="haskell">
GHCi> readMaybe "3" :: Maybe Integer
Just 3
GHCi> readMaybe "foo" :: Maybe Integer
Nothing
GHCi> readMaybe "3.5" :: Maybe Integer
Nothing
GHCi> readMaybe "3.5" :: Maybe Double
Just 3.5
</syntaxhighlight>
{{body note|To use <code>readMaybe</code>, we need to specify which type we are trying to read. Most of the time, that would be done through a combination of type inference and the signatures in our code. Occasionally, however, it is more convenient to just slap in a ''type annotation'' rather than writing down a proper signature. For instance, in the first example above the <code>:: Maybe Integer</code> in <code>readMaybe "3" :: Maybe Integer</code> says that the type of <code>readMaybe "3"</code> is <code>Maybe Integer</code>.}}
We can use <code>readMaybe</code> to write a little program in the style of those in the [[Haskell/Simple input and output|Simple input and output]] chapter that:
* Gets a string given by the user through the command line;
* Tries to read it into a number (let's use <code>Double</code> as the type); and
* If the read succeeds, prints your number times 2; otherwise, prints an explanatory message and starts over.
{{body note|Before continuing, we suggest you try writing the program. Beyond <code>readMaybe</code>, you will likely find <code>getLine</code>, <code>putStrLn</code> and <code>show</code> useful. Have a look at the [[Haskell/Simple input and output|Simple input and output]] chapter if you need a reminder about how to do reading from and printing to the console. }}
Here is a possible implementation:
<syntaxhighlight lang="haskell">
import Text.Read
interactiveDoubling = do
putStrLn "Choose a number:"
s <- getLine
let mx = readMaybe s :: Maybe Double
case mx of
Just x -> putStrLn ("The double of your number is " ++ show (2*x))
Nothing -> do
putStrLn "This is not a valid number. Retrying..."
interactiveDoubling
</syntaxhighlight>
<pre>
GHCi> interactiveDoubling
Choose a number:
foo
This is not a valid number. Retrying...
Choose a number:
3
The double of your number is 6.0
</pre>
Nice and simple. A variation of this solution might take advantage of how, given that <code>Maybe</code> is a <code>Functor</code>, we can double the value before unwrapping <code>mx</code> in the case statement:
<syntaxhighlight lang="haskell">
interactiveDoubling = do
putStrLn "Choose a number:"
s <- getLine
let mx = readMaybe s :: Maybe Double
case fmap (2*) mx of
Just d -> putStrLn ("The double of your number is " ++ show d)
Nothing -> do
putStrLn "This is not a valid number. Retrying..."
interactiveDoubling
</syntaxhighlight>
In this case, there is no real advantage in doing that. Still, keep this possibility in mind.
=== Application in functors ===
Now, let's do something slightly more sophisticated: reading two numbers with <code>readMaybe</code> and printing their sum (we suggest that you attempt writing this one as well before continuing).
Here is one solution:
<syntaxhighlight lang="haskell">
interactiveSumming = do
putStrLn "Choose two numbers:"
sx <- getLine
sy <- getLine
let mx = readMaybe sx :: Maybe Double
my = readMaybe sy
case mx of
Just x -> case my of
Just y -> putStrLn ("The sum of your numbers is " ++ show (x+y))
Nothing -> retry
Nothing -> retry
where
retry = do
putStrLn "Invalid number. Retrying..."
interactiveSumming
</syntaxhighlight>
<syntaxhighlight lang="haskell">
GHCi> interactiveSumming
Choose two numbers:
foo
4
Invalid number. Retrying...
Choose two numbers:
3
foo
Invalid number. Retrying...
Choose two numbers:
3
4
The sum of your numbers is 7.0
</syntaxhighlight>
<code>interactiveSumming</code> works, but it is somewhat annoying to write. In particular, the nested <code>case</code> statements are not pretty, and make reading the code a little difficult. If only there was a way of summing the numbers before unwrapping them, analogously to what we did with <code>fmap</code> in the second version of <code>interactiveDoubling</code>, we would be able to get away with just one <code>case</code>:
<syntaxhighlight lang="haskell">
-- Wishful thinking...
case somehowSumMaybes mx my of
Just z -> putStrLn ("The sum of your numbers is " ++ show z)
Nothing -> do
putStrLn "Invalid number. Retrying..."
interactiveSumming
</syntaxhighlight>
But what should we put in place of <code>somehowSumMaybes</code>? <code>fmap</code>, for one, is not enough. While <code>fmap (+)</code> works just fine to partially apply <code>(+)</code> to the value wrapped by <code>Maybe</code>...
<syntaxhighlight lang="haskell">
GHCi> :t (+) 3
(+) 3 :: Num a => a -> a
GHCi> :t fmap (+) (Just 3)
fmap (+) (Just 3) :: Num a => Maybe (a -> a)
</syntaxhighlight>
... we don't know how to apply a function wrapped in <code>Maybe</code> to the second value. For that, we would need a function with a signature like this one...
<syntaxhighlight lang="haskell">
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
</syntaxhighlight>
... which would then be used like this:
<syntaxhighlight lang="haskell">
GHCi> fmap (+) (Just 3) <*> Just 4
Just 7
</syntaxhighlight>
The GHCi prompt in this example, however, is not wishful thinking: <code>(<*>)</code> actually exists, and if you try it in GHCi, it will actually work! The expression looks even neater if we use the infix synonym of <code>fmap</code>, <code>(<$>)</code>:
<syntaxhighlight lang="haskell">
GHCi> (+) <$> Just 3 <*> Just 4
Just 7
</syntaxhighlight>
The actual type <code>(<*>)</code> is more general than what we just wrote. Checking it...
<syntaxhighlight lang="haskell">
GHCi> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
</syntaxhighlight>
... introduces us to a new type class: <code>Applicative</code>, the type class of ''applicative functors''. For an initial explanation, we can say that an applicative functor is a functor which supports applying functions within the functor, thus allowing for smooth usage of partial application (and therefore functions of multiple arguments). All instances of <code>Applicative</code> are <code>Functor</code>s, and besides <code>Maybe</code>, there are many other common <code>Functor</code>s which are also <code>Applicative</code>.
This is the <code>Applicative</code> instance for <code>Maybe</code>:
<syntaxhighlight lang="haskell">
instance Applicative Maybe where
pure = Just
(Just f) <*> (Just x) = Just (f x)
_ <*> _ = Nothing
</syntaxhighlight>
The definition of <code>(<*>)</code> is actually quite simple: if neither of the values are <code>Nothing</code>, apply the function <code>f</code> to <code>x</code> and wrap the result with <code>Just</code>; otherwise, give back <code>Nothing</code>. Note that the logic is exactly equivalent to what the nested <code>case</code> statement of <code>interactiveSumming</code> does.
Note that beyond <code>(<*>)</code> there is a second method in the instance above, <code>pure</code>:
<syntaxhighlight lang="haskell">
GHCi> :t pure
pure :: Applicative f => a -> f a
</syntaxhighlight>
<code>pure</code> takes a value and brings it into the functor in a default, trivial way. In the case of <code>Maybe</code>, the trivial way amounts to wrapping the value with <code>Just</code> – the nontrivial alternative would be discarding the value and giving back <code>Nothing</code>. With <code>pure</code>, we might rewrite the three-plus-four example above as...
<syntaxhighlight lang="haskell">
GHCi> (+) <$> pure 3 <*> pure 4 :: Num a => Maybe a
Just 7
</syntaxhighlight>
... or even:
<syntaxhighlight lang="haskell">
GHCi> pure (+) <*> pure 3 <*> pure 4 :: Num a => Maybe a
Just 7
</syntaxhighlight>
Just like the <code>Functor</code> class has laws which specify how sensible instances should behave, there is a set of laws for <code>Applicative</code>. Among other things, these laws specify what the "trivial" way of bringing values into the functor through <code>pure</code> amounts to. Since there is a lot going on in this stretch of the book, we will not discuss the laws now; however, we will return to this important topic in a not too distant future.
{{body note|In any case, if you are curious feel free to make a detour through the [[Haskell/Applicative functors|Applicative functors]] chapter and read its "Applicative functor laws" subsection. If you choose to go there, you might as well have a look at the "ZipList" section, which provides an additional example of a common applicative functor that can be grasped using only what we have seen so far.}}
To wrap things up, here is a version of <code>interactiveSumming</code> enhanced by <code>(<*>)</code>:
<syntaxhighlight lang="haskell">
interactiveSumming = do
putStrLn "Choose two numbers:"
sx <- getLine
sy <- getLine
let mx = readMaybe sx :: Maybe Double
my = readMaybe sy
case (+) <$> mx <*> my of
Just z -> putStrLn ("The sum of your numbers is " ++ show z)
Nothing -> do
putStrLn "Invalid number. Retrying..."
interactiveSumming
</syntaxhighlight>
== Scene 2 : <code>IO</code> ==
In the examples above, we have been taking I/O actions such as <code>getLine</code> for granted. We now find ourselves at an auspicious moment to revisit a question first raised many chapters ago: what is the type of <code>getLine</code>?
Back in the [[Haskell/Simple input and output|Simple input and output]] chapter, we saw the answer to that question is:
<syntaxhighlight lang="haskell">
GHCi> :t getLine
getLine :: IO String
</syntaxhighlight>
Using what we learned since then, we can now see that <code>IO</code> is a type constructor with one type variable, which happens to be instantiated as <code>String</code> in the case of <code>getLine</code>. That, however, doesn't get to the root of the issue: what does <code>IO String</code> really mean, and what is the difference between that and plain old <code>String</code>?
=== Referential transparency ===
A key feature of Haskell is that all expressions we can write are ''referentially transparent''. That means we can replace any expression whatsoever by its value without changing the behaviour of the program. For instance, consider this very simple program:
<syntaxhighlight lang="haskell">
addExclamation :: String -> String
addExclamation s = s ++ "!"
main = putStrLn (addExclamation "Hello")
</syntaxhighlight>
Its behaviour is wholly unsurprising:
<syntaxhighlight lang="haskell">
GHCi> main
Hello!
</syntaxhighlight>
Given that <code>addExclamation s = s ++ "!"</code>, we can rewrite <code>main</code> so that it doesn't mention <code>addExclamation</code>. All we have to do is replace <code>s</code> with <code>"Hello"</code> on the right-hand side of the <code>addExclamation</code> definition and then replace {{nowrap|<code>addExclamation "Hello"</code>}} with the resulting expression. As advertised, the program behaviour does not change:
<syntaxhighlight lang="haskell">
GHCi> let main = putStrLn ("Hello" ++ "!")
GHCi> main
Hello!
</syntaxhighlight>
Referential transparency ensures that this sort of substitution works. This guarantee extends to anywhere in any Haskell program, which goes a long way towards making programs easier to understand, and their behaviour easier to predict.
Now, suppose that the type of <code>getLine</code> were <code>String</code>. In that case, we would be able to use it as the argument to <code>addExclamation</code>, as in:
<syntaxhighlight lang="haskell">
-- Not actual code.
main = putStrLn (addExclamation getLine)
</syntaxhighlight>
In that case, however, a new question would spring forth: if <code>getLine</code> is a <code>String</code>, which <code>String</code> is it? There is no satisfactory answer: it could be <code>"Hello"</code>, <code>"Goodbye"</code>, or whatever else the user chooses to type at the terminal. And yet, ''replacing'' <code>getLine</code> with any <code>String</code> breaks the program, as the user would not be able to type the input string at the terminal any longer. Therefore <code>getLine</code> having type <code>String</code> would break referential transparency. The same goes for all other I/O actions: their results are ''opaque'', in that it is impossible to know them in advance, as they depend on factors external to the program.
=== Cutting through the fog ===
As <code>getLine</code> illustrates, there is a fundamental indeterminacy associated with I/O actions. Respecting this indeterminacy is necessary for preserving referential transparency. In Haskell, that is achieved through the <code>IO</code> type constructor. <code>getLine</code> being an <code>IO String</code> means that it is not any actual <code>String</code>, but both a placeholder for a <code>String</code> that will only materialise when the program is executed and a promise that this <code>String</code> will indeed be delivered (in the case of <code>getLine</code>, by slurping it from the terminal). As a consequence, when we manipulate an <code>IO String</code> we are setting up plans for what ''will'' be done once this unknown <code>String</code> comes into being. There are quite a few ways of achieving that. In this section, we will consider two of them; we will add a third one in the next few chapters.
The idea of dealing with a value which isn't really there might seem bizarre at first. However, we have already discussed at least one example of something not entirely unlike it without batting an eyelid. If <code>mx</code> is a <code>Maybe Double</code>, then <code>fmap (2*) mx</code> doubles the value ''if it is there'', and works regardless of whether the value actually exists.<ref>The key difference between the two situations is that with <code>Maybe</code> the indeterminacy is only apparent, and it is possible to figure out in advance whether there is an actual <code>Double</code> behind <code>mx</code> – or, more precisely, it is possible as long as the value of <code>mx</code> does not depend on I/O!</ref> Both <code>Maybe a</code> and <code>IO a</code> imply, for different reasons, a layer of indirection in reaching the corresponding values of type <code>a</code>. That being so, it comes as no surprise that, like <code>Maybe</code>, ''<code>IO</code> is a <code>Functor</code>'', with <code>fmap</code> being the most elementary way of getting across the indirection.
To begin with, we can exploit the fact that <code>IO</code> is a <code>Functor</code> to replace the <code>let</code> definitions in <code>interactiveSumming</code> from the end of the previous section with something more compact:
<syntaxhighlight lang="haskell">
interactiveSumming :: IO ()
interactiveSumming = do
putStrLn "Choose two numbers:"
mx <- readMaybe <$> getLine -- equivalently: fmap readMaybe getLine
my <- readMaybe <$> getLine
case (+) <$> mx <*> my :: Maybe Double of
Just z -> putStrLn ("The sum of your numbers is " ++ show z)
Nothing -> do
putStrLn "Invalid number. Retrying..."
interactiveSumming
</syntaxhighlight>
<code>readMaybe <$> getLine</code> can be read as "once <code>getLine</code> delivers a string, whatever it turns out to be, apply <code>readMaybe</code> to it". Referential transparency is not compromised: the value behind <code>readMaybe <$> getLine</code> is just as opaque as that of <code>getLine</code>, and its type (in this case <code>IO (Maybe Double)</code>) prevents us from replacing it with any determinate value (say, <code>Just 3</code>) as it would violate referential transparency.
Beyond being a <code>Functor</code>, <code>IO</code> is also an <code>Applicative</code>, which provides us with a second way of manipulating the values delivered by I/O actions. We will illustrate it with an <code>interactiveConcatenating</code> action, similar in spirit to <code>interactiveSumming</code>. A first version is just below. Can you anticipate how to simplify it with <code>(<*>)</code>?
<syntaxhighlight lang="haskell">
interactiveConcatenating :: IO ()
interactiveConcatenating = do
putStrLn "Choose two strings:"
sx <- getLine
sy <- getLine
putStrLn "Let's concatenate them:"
putStrLn (sx ++ sy)
</syntaxhighlight>
Here is a version exploiting <code>(<*>)</code>:
<syntaxhighlight lang="haskell">
interactiveConcatenating :: IO ()
interactiveConcatenating = do
putStrLn "Choose two strings:"
sz <- (++) <$> getLine <*> getLine
putStrLn "Let's concatenate them:"
putStrLn sz
</syntaxhighlight>
<code>(++) <$> getLine <*> getLine</code> is an I/O action which is made out of two other I/O actions (the two <code>getLine</code>). When it is executed, these two I/O actions are executed and the strings they deliver are concatenated. One important thing to notice is that <code>(<*>)</code> maintains a consistent order of execution between the actions it combines. Order of execution matters when dealing with I/O – examples of that are innumerable, but for starters consider this question: if we replace the second <code>getLine</code> in the example above with <code>(take 3 <$> getLine)</code>, which of the strings entered at the terminal will be cut down to three characters?
As <code>(<*>)</code> respects the order of actions, it provides a way of sequencing them. In particular, if we are only interested in sequencing and don't care about the result of the first action we can use <code>\_ y -> y</code> to discard it:
<syntaxhighlight lang="haskell">
GHCi> (\_ y -> y) <$> putStrLn "First!" <*> putStrLn "Second!"
First!
Second!
</syntaxhighlight>
This is such a common usage pattern that there is an operator specifically for it: <code>(*>)</code>.
<syntaxhighlight lang="haskell">
u *> v = (\_ y -> y) <$> u <*> v
</syntaxhighlight>
<syntaxhighlight lang="haskell">
GHCi> :t (*>)
(*>) :: Applicative f => f a -> f b -> f b
GHCi> putStrLn "First!" *> putStrLn "Second!"
First!
Second!
</syntaxhighlight>
It can be readily applied to <code>interactiveConcatenating</code> example:
<syntaxhighlight lang="haskell">
interactiveConcatenating :: IO ()
interactiveConcatenating = do
putStrLn "Choose two strings:"
sz <- (++) <$> getLine <*> getLine
putStrLn "Let's concatenate them:" *> putStrLn sz
</syntaxhighlight>
Or, going even further:
<syntaxhighlight lang="haskell">
interactiveConcatenating :: IO ()
interactiveConcatenating = do
sz <- putStrLn "Choose two strings:" *> ((++) <$> getLine <*> getLine)
putStrLn "Let's concatenate them:" *> putStrLn sz
</syntaxhighlight>
Note that each <code>(*>)</code> replaces one of the magical line breaks of the <code>do</code> block that lead actions to be executed one after the other. In fact, that is all there is to the replaced line breaks: they are just syntactic sugar for <code>(*>)</code>.
Earlier, we said that a functor adds a layer of indirection for accessing the values within it. The flip side of that observation is that the indirection is caused by a ''context'', within which the values are found. For <code>IO</code>, the indirection is that the values are only determined when the program is executed, and the context consists in the series of instructions that will be used to produce these values (in the case of <code>getLine</code>, these instructions amount to "slurp a line of text from the terminal"). From this perspective, <code>(<*>)</code> takes two functorial values and combines not only the values within but also the contexts themselves. In the case of <code>IO</code> combining the contexts means appending the instructions of one I/O action to those of the other, thus sequencing the actions.
== The end of the beginning ==
This chapter was a bit of a whirlwind! Let's recapitulate the key points we discussed in it:
* <code>Applicative</code> is a subclass of <code>Functor</code> for ''applicative functors'', which are functors that support function application without leaving the functor.
* The <code>(<*>)</code> method of <code>Applicative</code> can be used as a generalisation of <code>fmap</code> to multiple arguments.
* An <code>IO a</code> is not a tangible value of type <code>a</code>, but a placeholder for an <code>a</code> value that will only come into being when the program is executed and a promise that this value will be delivered through some means. That makes referential transparency possible even when dealing with I/O actions.
* <code>IO</code> is a functor, and more specifically an instance of <code>Applicative</code>, that provides means to modify the value produced by an I/O action in spite of its indeterminacy.
* A functorial value can be seen as being made of values in a ''context''. The <code>(<$>)</code> operator (that is, <code>fmap</code>) cuts through the context to modify the underlying values. The <code>(<*>)</code> operator combines both the contexts and the underlying values of two functorial values.
* In the case of <code>IO</code>, <code>(<*>)</code>, and the closely related <code>(*>)</code>, combine contexts by sequencing I/O actions.
* A large part of the role of <code>do</code> blocks is simply providing syntactic sugar for <code>(*>)</code>.
As a final observation, note that there is still a major part of the mystery behind <code>do</code> blocks left to explain: what does the left arrow do? In a <code>do</code>-block line such as...
<syntaxhighlight lang="haskell">
sx <- getLine
</syntaxhighlight>
... it looks like we are extracting the value produced by <code>getLine</code> from the <code>IO</code> context. Thanks to the discussion about referential transparency, we now know that must be an illusion. But what is going on behind the scenes? Feel free to place your bets, as we are about to find out!
{{Haskell/NotesSection}}
{{Haskell/Navigation|chapter=Monads|noexercises=1}}
{{BookCat}}
sdhmqe2qj1uaydtvtyyduxbr7w75thx
Radiation Oncology/Palliation/Lung tumor/Guidelines
0
381599
4675962
4675647
2026-10-14T01:00:46Z
JackBot
396820
Formatting, [[Special:UncategorizedPages]]
4675962
wikitext
text/x-wiki
<big>'''Palliative Lung Guidelines'''</big>
:see also: [[Radiation Oncology/NSCLC/Guidelines]]
*'''ASTRO'''
**'''2011''': {{PMID|25740118}} -- "Palliative thoracic radiotherapy in lung cancer: An American Society for Radiation Oncology evidence-based clinical practice guideline." (Rodrigues G, Pract Radiat Oncol. 2011 Apr-Jun;1(2):60-71.)
{{BookCat}}
6x6j20rhwpt1bj2lkri3tvzruq5eorh
TI-Basic Z80 Programming/Loops
0
409648
4675966
4675791
2026-10-14T04:43:04Z
Rex Valerio
3628187
Correct summation notation to match the example
4675966
wikitext
text/x-wiki
It is important while writing programs to save space due to the calculator's limited memory. To help this, loops can be used which can repeat a section of code a number of times. TI-Basic offers a few types of loops: <code>While</code>, <code>For</code>, and <code>Repeat</code>.
== While ==
The <code>'''[[../List of Commands/While|While]]'''</code> ({{TI-Basic/Key|PRGM}}<code> '''''CTL'' 5'''</code>) loop executes a block of commands between the <code>While</code> and <code>End</code> commands as long as the specified condition is true. The condition is tested at the beginning of the loop (when the <code>End</code> command is encountered), so if the condition is initially false, the block of commands will never execute.
=== Syntax ===
{{bcode:Syntax|
While ''condition is true''
''statements''
End
|
* Where <code>condition</code> is any statement resulting in a true/false/zero/non-zero result
** If <code>condition</code> returns true or non-zero, <code>statement</code> continues to execute
** If <code>condition</code> returns false or zero, <code>statement</code> will not execute and will skip to after the <code>End</code>
}}
=== Examples ===
The following example demonstrates a very basic <code>While</code> Loop that will display <code>X</code> until <code>Y</code> equals 0:
{{bcode:Example|
:While Y≠0
:Disp X
:End
}}
== For ==
The <code>'''[[../List of Commands/For|For]]'''</code> ({{TI-Basic/Key|PRGM}}<code> '''''CTL'' 4'''</code>) loop executes a block of commands between the <code>For</code> and <code>End</code> commands ''n'' number of times. <code>For</code> is useful when you know the exact number of times you want to repeat a section of code.
=== Syntax ===
{{bcode:Syntax|
For(variable,begin,end[,increment])
''statements''
End
|
* Where <code>variable</code> is a <code>Real</code> (A-Z & θ). This variable represents a counter.
* Where <code>begin</code> is the number to begin counting from
* Where <code>end</code> is the number to stop execution once <code>variable</code> equals <code>end</code>
* Where, optionally, <code>increment</code> is the amount to change <code>variable</code> after each loop. If this argument is not passed, it is assumed to be <code>1</code>.
}}
=== Examples ===
To print the numbers 1 to 5 using a <code>For</code> loop:
{{bcode:Example|
:For(I,1,5)
:Disp I
:End
}}
This code will print:
{{Bcode:Output|<nowiki>
1
2
3
4
5</nowiki>}}
----
To traverse a list and print its elements:
{{bcode:Example|
:For(I,1,dim(L1))
:Disp L1(I)
:End
}}
== Repeat ==
The <code>'''[[../List of Commands/Repeat|Repeat]]'''</code> ({{TI-Basic/Key|PRGM}}<code> '''''CTL'' 6'''</code>) loop executes a block of commands between the <code>Repeat</code> and <code>End</code> commands until specified condition is true. The condition is tested at the beginning of the loop (when the <code>End</code> command is encountered), so if the condition is initially true, the block of commands will never execute.
<code>Repeat</code> is simply <code>While</code> where the condition is inverted.
=== Syntax ===
{{bcode:Syntax|
Repeat ''condition''
''statements''
End
|
* Where <code>condition</code> is any statement resulting in a true/false/zero/non-zero result
** If <code>condition</code> returns false or zero, <code>statement</code> continues to execute
** If <code>condition</code> returns true or non-zero, <code>statement</code> will not execute and will skip to after the <code>End</code>
}}
=== Examples ===
The following example demonstrates the use of a <code>Repeat</code> statement. It will continue to ask the user for an <code>X</code> value until <code>X > 5 </code>:
{{bcode:Example|
:0→X
:Repeat X>5
:Prompt X
:End
}}
== You try it! ==
Try these examples to practice using loops.
=== Summation from 1 to ''n'' ===
Write a program that asks the user for a number ''n'' (must be greater than 1) and prints the sum of the numbers 1 to ''n''. For example, if ''n'' = 6, the program would display <code>21</code> (<math>1+2+3+4+5+6=21</math>).
{{Collapse top|title=Solution}}
{{bcode:Example|
:0→N // Clear n
:Repeat N>1 // Until n is greater than 1,
:Prompt N // Ask for n
:End // End repeat loop
:0→S // Clear s (sum)
:For(X,1,N) // From 1 to n,
:S+X→S // Add X to S
:End // End for loop
:Disp S // Print
}}
{{Collapse top|title=Alternate solution using summation}}
{{bcode:Example|
:0→N // Clear n
:Repeat N>1 // Until n is greater than 1,
:Prompt N // Ask for n
:End // End repeat loop
:Disp Σ(X,X,1,N) // Summation Σ(expression,variable,start,end)
}}
This example uses the following summation expression: <math>\sum_{x=1}^{N} x</math>
{{Collapse bottom}}
{{Collapse bottom}}
=== Fibonacci Sequence ===
The Fibonacci Sequence is defined as <math>F(n) = F(n-1) + F(n-2)</math> where <math>F(1) = 0</math> and <math>F(2) = 1</math>. Therefore, the first 10 elements of the sequence are <code>0, 1, 1, 2, 3, 5, 8, 13, 21, 34</code>. Write a program that stores the first 100 elements of the sequence to <code>L<small>1</small></code>, then display them. ''Remember, you will have to instantiate the list first.''
{{Collapse top|title=Solution}}
{{bcode:Example|<nowiki>
:DelVar L1 // List instantiation
:100→dim(L1) // List instantiation
:0→L1(1) // F(1) = 0
:1→L1(2) // F(2) = 1
:For(A,3,100) // We start at 3 since 1 and 2 are already set
:L1(A-1)+L1(A-2)→L1(A) // F(N) = F(N-1) + F(N-2)
:End // End for loop
:ClrHome // Clear screen
:For(A,1,100) // From 1 to 100
:Disp L1(A) // Print F(A)
:End // End for loop</nowiki>
}}
{{Collapse bottom}}
=== FizzBuzz ===
FizzBuzz is a children's game often used today as a programming evaluation program. The original game consists of players taking turns to count incrementally, replacing any number divisible by 3 with the word "fizz", and any number divisible by 5 with the word "buzz". For this example, write a program that counts from 1 to 100, replacing numbers divisible by 3 with "Fizz", 5 with "Buzz", and 3 and 5 with "FizzBuzz."
''Hint: Take the remainder of the current value and the key numbers and compare it to 0.''
You will have to get creative writing this program as there are many ways to approach it. The following solution is just one of many solutions:
{{Collapse top|title=Solution}}
In this example, we must check multiples of 15 before checking 3 or 5.
{{bcode:Example|<nowiki>
:ClrHome
:For(X,1,100)
:If remainder(X,15)=0:Then
:Disp "FIZZBUZZ"
:Else
:If remainder(X,3)=0:Then
:Disp "FIZZ"
:Else
:If remainder(X,5)=0:Then
:Disp "BUZZ"
:Else
:Disp X
:End
:End
:End
:End</nowiki>
}}
{{Collapse top|title=Solution without <code>remainder</code>}}
{{bcode:Example|<nowiki>
:ClrHome
:For(X,1,100)
:If fPart(X/15)*15=0:Then
:Disp "FIZZBUZZ"
:Else
:If fPart(X/3)*3=0:Then
:Disp "FIZZ"
:Else
:If fPart(X/5)*5=0:Then
:Disp "BUZZ"
:Else
:Disp X
:End
:End
:End
:End</nowiki>
}}
{{Collapse bottom}}
{{Collapse bottom}}
{{BottomNav|Conditional Statements|Advanced Variables}}
jj01p871rkda2uy34qedot1gdvw378m
On 2D Inverse Problems/Acknowledgements
0
410035
4675927
3584531
2026-10-13T23:05:25Z
DVD206
724793
redirect detour
4675927
wikitext
text/x-wiki
Volume I: Wikipedia, StackExchange and SageMathCloud helped publishing the book @all stages of the process.
Volumes II and III: Copilot/Covid, Gemini/Germany and Meta/eta/beta/zeta AI on cellphone and laptop...
{{BookCat}}
4cg4b73aln8ssa5n8mle6dovn4gli65
On 2D Inverse Problems/redial
0
410555
4675916
3590089
2026-10-13T22:43:29Z
DVD206
724793
hAPPY Halloween...
4675916
wikitext
text/x-wiki
"Why do mathematicians celebrate dec.25th on oct.31st?"
An answer: 31 = 8*3+1=25 base 8!?
<includeonly>ℳ♥</includeonly>
{{BookCat}}
5l3e9aa68bi6rhtw1cbydk5wrd63odt
Radiation Oncology/Psycho-oncology
0
419512
4675971
4342094
2026-10-14T05:32:09Z
Jcb
90773
4675971
wikitext
text/x-wiki
* Psycho-oncology is an interdisciplinary field at the intersection of physical, psychological, social, and behavioral aspects of the cancer experience for both patients and caregivers
* Also known as Psychiatric Oncology or Psychosocial Oncology, researchers and practitioners in the field are concerned with aspects of individuals' experience with cancer beyond medical treatment, and across the cancer trajectory, including at diagnosis, during treatment, transitioning to and throughout survivorship, and approaching the end-of-life
* Founded by Jimmie Holland in 1977 via the incorporation of a psychiatric service within the Memorial Sloan Kettering Cancer Center in New York, the field has expanded drastically since and is now universally recognized as an integral component of quality cancer care
* Cancer centers in major academic medical centers across the country now uniformly incorporate a psycho-oncology service into their clinical care, and provide infrastructure to support research efforts to advance knowledge in the field
* Isabelle Lang-Rollin et al. Dialogues Clin Neurosci. 2018 Mar; 20(1): 13–22. Psycho-oncology ([[PMID: 29946207]])
{{BookCat}}
==Psilocybin==
*Indole alkaloid found in family of mushrooms
*After ingestion, metabolized to psilocin in the body. This metabolite is responsible for psychotropic properties via serotonin 2A receptor
*Psilocin is further metabolized to 4-hydroxyindole-3-acetic acid (4-HIAA)
*No specific studies reviewing effects of psilocybine on radiation oncology patients.
*'''US Multi-Institutional; 2023''' (2019 - 2022) {{PMID|37651119}} -- "Single-Dose Psilocybin Treatment for Major Depressive Disorder: A Randomized Clinical Trial" (Raison CL, JAMA. 2023 Sep 5;330(9):843-853. doi: 10.1001/jama.2023.14530.)
**Randomized Phase 2. 11 sites. 104 participants with major depressive disorder, >60 days, moderate+ symptoms. Single dose 25 mg psilocybin vs 100 mg niacin placebo. MADRS score (0-60) used.
**Outcome: MADRS scores psilocybin better by 12.3 points (SS) at 43 days. Also reduced Sheehan Disability Score by 2.3 points (SS). More sustained response
**Toxicity: Severe AE psilocybin 8% (migraine x1, headache x1, illusion x1, panic attack/paranoia x1) vs control 0%. No suicidal ideation. No changes in vital signs or labs.
**Conclusion: Psilocybin clinically significant reduction in depressive symptoms and functional disability, without serious adverse events
*'''Medical University of Vienna; 2022''' {{PMID|34871422}} -- "Psilocybin Therapy of Psychiatric Disorders Is Not Hampered by hERG Potassium Channel-Mediated Cardiotoxicity" (Hack B, Int J Neuropsychopharmacol. 2022 Apr 19;25(4):280-282. doi: 10.1093/ijnp/pyab085.)
**Cell culture. 4-HIAA applied to hERG channels, up to 500x concentration
**Conclusion: hERG blockade by clinical levels of psilocin does not account for cardiotoxic effects
*'''Copenhagen University, 2021''' {{PMID|34246868}} -- "Psilocybin-induced changes in brain network integrity and segregation correlate with plasma psilocin level and psychedelic experience" (Madsen MK, Eur Neuropsychopharmacol. 2021 Sep:50:121-132. doi: 10.1016/j.euroneuro.2021.06.001. Epub 2021 Jul 8.)
**15 participants. MRI data acquistion correlated with psilocin plasma concentrations
**Outcome: Executive control and dorsal attention networks desegretate
**Conclusion: Expression network integrity and segregation implicated in the psychedelic experience and consciousness
64s6bso30mahn5t7049t5d5r7eepdfp
Fractals/Computer graphic techniques/2D/exp
0
450369
4675991
4660206
2026-10-14T08:54:36Z
PJ Geest
213156
/* number */ png -> svg
4675991
wikitext
text/x-wiki
=Disambiguation=
Exponential mapping of the plane '''is''':
* is exponential [[Fractals/Computer graphic techniques/2D/transformation|transformation of the plane]]
Exponential mapping of the plane ''' is not'''
* the Julia set or Mandelbrot set of [[Fractals/exponential|the exponential function ( exponentia map)]], like Exponential Mandelbrot z := exp(z) + c
* Logarithmic scale on one axis<ref>[[:w:Logarithmic_scale|Logarithmic_scale in wikipedia]]</ref>
* Logarithmic scale on both axes: Log-log scale plot<ref>[https://uk.mathworks.com/help/matlab/ref/loglog.html matlab ref: loglog plot]</ref>
* polar azimuthal equidistant projection ( Exponential map in Riemannian geometry)<ref>[[:w:Exponential_map_(Riemannian_geometry)|Exponential_map_(Riemannian_geometry)]]</ref>
* The exponential operator, anamorphosis operator which can be applied to grayscale images.<ref>[https://homepages.inf.ed.ac.uk/rbf/HIPR2/pixexp.htm Exponential/`Raise to Power' Operator by R. Fisher, S. Perkins, A. Walker and E. Wolfart ( 2003)]</ref>
Compare exponential function by different input
* single number ( 0D space) gives natural exponent of the number
* number line ( 1D space). Exponential scale is not used. Logarithmic scale is used for exponential data. It gives a linear function.<ref>[https://www.qliktips.com/2020/04/exponential-data-and-logarithmic-scales.html exponential-data-and-logarithmic-scales by Stephen Redmond]</ref>
* plane ( 2D space) gives exponential mapping
==number==
In mathematics, the logarithm is the inverse function to exponentiation. That means the logarithm of a number x to the base b is the exponent to which b must be raised, to produce x
:<math>y = \log_b x</math>
is equivalent to
:<math>x=b^y</math>
if {{mvar|b}} is a positive real number. (If {{mvar|b}} is not a positive real number, both exponentiation and logarithm can be defined but may take several values, which makes definitions much more complicated.)<ref>[https://www.pacifict.com/Exponential.html 24 Views of the Complex Exponential Function by Pacific Tech]</ref>
<gallery>
Logarithm inversefunctiontoexp.png|a logarithm function and an exponential function
Logarithm plots.svg|Plots of logarithm functions, with three commonly used bases. The special points {{math|log<sub>''b''</sub> ''b'' {{=}} 1}} are indicated by dotted lines, and all curves intersect in {{math|1=log<sub>''b''</sub> 1 = 0}}
Binary logarithm plot with grid.svg|Graph showing a logarithmic curve, crossing the ''x''-axis at ''x''= 1 and approaching minus infinity along the ''y''-axis.|The graph of the logarithm base 2 crosses the ''x''-axis at {{math|''x'' {{=}} 1}} and passes through the points {{nowrap|(2, 1)}}, {{nowrap|(4, 2)}}, and {{nowrap|(8, 3)}}, depicting, e.g., {{math|log<sub>2</sub>(8) {{=}} 3}} and {{math|2<sup>3</sup> {{=}} 8}}. The graph gets arbitrarily close to the {{mvar|y}}-axis, but does not meet it
</gallery>
The real exponential function is a bijection from <math>\mathbb{R}</math> to <math>(0;\infty)</math>.<ref>{{cite book |last1=Meier |first1=John |last2=Smith |first2=Derek |title=Exploring Mathematics |date=7 August 2017 |publisher=Cambridge University Press |isbn=978-1-107-12898-9 |page=167 }}</ref> Its inverse function is the natural logarithm, denoted <math>\ln, \log, \log_e;</math> because of this, some old texts refer to the exponential function as the '''antilogarithm'''.
==scale ==
A '''logarithmic scale''' (or '''log scale''') is a way of displaying numerical data over a very wide range of values in a compact way—typically the largest numbers in the data are hundreds or even thousands of times larger than the smallest numbers. Such a scale is nonlinear: the numbers 10 and 20, and 60 and 70, are not the same distance apart on a log scale. Rather, the numbers 10 and 100, and 60 and 600 are equally spaced. Thus moving a unit of distance along the scale means the number has been ''multiplied'' by 10 (or some other fixed factor). Often exponential growth curves are displayed on a log scale, otherwise they would increase too quickly to fit within a small graph. Another way to think about it is that the ''number of digits'' of the data grows at a constant rate. For example, the numbers 10, 100, 1000, and 10000 are equally spaced on a log scale, because their numbers of digits is going up by 1 each time: 2, 3, 4, and 5 digits. In this way, adding two digits ''multiplies'' the quantity measured on the log scale by a factor of 100.
Logarithmic scale
* on 1 axis = semi-log plot<ref>[[:w:semi-log plot|semi-log plot in wikipedia]]</ref>
** linear-log plot
** log-linear plot
* on both axes = log-log plot<ref>[[:w:Log–log plot|Log–log plot in wikipedia]]</ref>
<gallery>
LinLinScale.svg| Lin-Lin scale
LogLinScale.svg| Log-Lin scale
LinLogScale.svg| Lin-Log scale
LogLogScale.svg| Log-Log scale
</gallery>
Logarithmic scale is used for exponential data. It gives a linear function.<ref>[https://www.qliktips.com/2020/04/exponential-data-and-logarithmic-scales.html exponential-data-and-logarithmic-scales by Stephen Redmond]</ref><ref>[http://www.lagado.name/blog/log-scale-reading/ Log-Scale Reading Posted July 17, 2015 by Scott]</ref>
[[File:Logarithmic scale (2).png|thumb|right|The function of f(x) = 2^x plotted on the logarithmic scale looks like linear function]]
==mapping==
* [https://www-users.cse.umn.edu/~arnold/complex/exp-g.html GRAPHICS FOR COMPLEX ANALYSIS by Douglas N. Arnold]:
** "the complex exponential maps the infinite open strip bounded by the horizontal lines through +/- pi i one-to-one onto the plane minus the negative real axis.
** The lines of constant real part are mapped to circles, and lines of constant imaginary part to rays from the origin.
** In the animation we view a rectangle in the strip rather than the entire strip, so the region covered is an annulus minus the negative real axis.
** The inner boundary of the annulus is so close to the origin as to be barely visible.
** We also make the strip a bit thinner than 2 pi, so that the annulus does not quite close up."
** the complex exponential map takes the rectangle |Re(z)| ≤ a, |Im(z)| ≤ π onto the annulus <math>e^{-a} \le |w| \le e^a</math>
* [https://www.falstad.com/complexviewer/ Composition of complex Mappings Viewer by Paul Falstad] - the composition of selected mapping functions: g(f(z)). One have to increase grid size to have tha same effect ( rectangle to annulus mapping)
* [https://www.geogebra.org/m/aEUGrASs The Complex Exponential Function Author:Susan Addington]
* [https://www.geogebra.org/m/qCSzkRsP Complex mappings Author:Juan Carlos Ponce Campuzano]
* [https://www.geogebra.org/m/pkBB6Hkm Complex exponential function Author:Tatsuyoshi Hamada] : Complex exponential function maps rectangular domain to fan shaped image ( part or full sector of punctured circle )
* [https://www.geogebra.org/m/Ac43DNNP Complex exponential map by Siamak on geogebra]:
** vertical axis is transformed to the circle on the w-plane
** horizontal axis is is transformed to the radii on the w-plane
* Images of a square grid of size [-3,3]x[-3,3] under the (conformal) exponential map givers almost full annulus<ref>[https://functions.wolfram.com/ElementaryFunctions/Exp/visualizations/4/ wolfram Exp visualizations]</ref>
* The complex exponential function mapping biholomorphically a rectangle [-1,1]x[0 ,pi/2] to a quarter-annulus <math>[ e^{-1}, e]x[ e^{-1}, e]</math><ref>[http://www.scientificlib.com/en/Mathematics/LX/Biholomorphism.html scientificlib : Biholomorphism ]</ref>
* [https://www.pacifict.com/Exponential.html 24 Views of the Complex Exponential Function by Pacific Tech]
* [https://mathematica.stackexchange.com/questions/231371/how-do-i-visualize-expz-as-a-complex-mapping mathematica question: how-do-i-visualize-expz-as-a-complex-mapping]
* [https://virtualmathmuseum.org/ConformalMaps/exp/index.html virtual math museum: ConformalMaps, complex exponential function]:"a Cartesian Grid is mapped “conformally” (i.e., preserving angles) to a Polar Grid: the parallels to the real axis are mapped to radial lines, and segments of length 2π that are parallel to the imaginary axis are mapped to circles around 0."
exp(x + i · y) = exp(x) · exp(i · y) = exp(x) · cos(y) + i · exp(x) · sin(y)
<gallery caption="Surfaces representing the complex exponential">
Exponential Function (Real Part).png|real part
Exponential Function (Imag Part).png|imaginary part
Exponential Function Modulus.png|modulus = cabs
Exponential Function Argument.png|main argument = carg
</gallery>
<gallery caption="Density curve representing of the complex exponential">
Exponential Function (Real Part) Density.png|real part
Exponential Function (Imag Part) Density.png|imaginary part
</gallery>
<gallery caption= "exponential mapping">
An Introduction to the Log-Polar Mapping.png|The Log-Polar Mapping. Point (x,y) is mapped to <math>(\rho, \theta)</math> where <math>\rho =\log \sqrt{x^2 + y^2}</math> and <math>\theta = \arctan(\frac{y}{x}) </math>. In general circles around orogin and radii are mapped to horizontal and vertical lines.
Cardioid under log mapping.png
Mercator projections vs rotation.gif|mercator projection vs rotation
Exponential map of the sphere.svg| the exponential mapping from the tangent space to the sphere
</gallery>
{| class="wikitable"
|-
! 3D !! 2D !! description
|-
| [[File:Exp.gif|framed|center|<math>f(z)=\exp(z)</math>]] || [[File:ContourExp.gif|framed|center|<math>f(z)=\exp(z)</math>]] ||
|-
| [[File:LogPlot.gif|framed|center|<math>f(z)=\log(z)</math>]] || [[File:ContourLog.gif|framed|center|<math>f(z)=\log(z)</math>]] ||
|}
===period===
The exponential function is periodic:
exp(z + 2 π * i) = exp(z).
The periodicity is also clear from the formula:
exp(x + i * y) = exp(x) * (cos(y) + i * sin(y)) .
The graph of the exponential function is a two-dimensional surface ( x,y) that curves through four dimensions ( x,y,v,w).
<gallery>
Complex exponential function graph spiral shape yvw dimensions.jpg| v+iw = exp(x+iy) for values of x from -1.5 to 1.5 and values of y from -2π to 2π, so that shows two complete rotations of the spiral.
</gallery>
=Name=
* exponential mapping<ref>[https://www.physlets.org/roess/roessse37.html Conformal mapping with the complex exponential function]</ref>
* the exponential map<ref>[http://mathr.co.uk/blog/2014-12-17_exponential_mapping_with_kalles_fraktaler.html Exponential mapping with Kalles Fraktaler by Claude Heiland-Allen]</ref><ref>[https://mrob.com/pub/muency/exponentialmap.html exponential map Robert P. Munafo, 2010 Dec 5. From the Mandelbrot Set Glossary and Encyclopedia, by Robert Munafo, (c) 1987-2022.]</ref><ref>[https://www.geogebra.org/m/Ac43DNNP Complex exponential map by Siamak]</ref>
* Mercator ( it is not good name because here is only mapping from flat complex plane ( 2D Cartesian plane) to exponential plane. Here there is no mapping from sphere to flat complex plane ( Cartesian plane)<ref>[[:w:Transverse_Mercator_projection|Transverse_Mercator_projection in wikipedia]]</ref> )
** [[Fractals/Computer_graphic_techniques/2D/algorithms#map_projections|Mercator map]]
** Mercator projection <ref>[http://www.fractalforums.com/kalles-fraktaler/kf-extras-for-manipulating-output-from-kalles-fraktaler-2/?topicseen kf-extras for manipulating output from Kalles Fraktaler 2]</ref><ref> [https://mrgris.com/projects/merc-extreme/ Mercator: Extreme An interactive visualization of the extreme distortions of the Mercator projection by Drew Griscom Roos]</ref><ref>[http://www.quadibloc.com/maps/mcy0101.htm The Mercator Projection by John J. G. Savard]</ref><ref>[https://archive.bridgesmathart.org/2013/bridges2013-217.pdf The Mercator Redemption by Sébastien Pérez-Duarte and David Swart ]</ref>
* [[Fractals/fractalzoomer#Polar_Projection|polar projection]]
* log-polar mapping ( [[Fractals/Computer_graphic_techniques/2D/coordinate#Log-polar_coordinates|Log-polar coordinates]] )
* logarithmic <ref>[https://www.flickr.com/photos/87547772@N00/sets/72157615740829949/ flickr : Mercator Mandelbrot Maps by Anders Sandberg]</ref>
** logarithmic projection around a point c0: z-> (log(|z-c0|)
* log(z)-Mandelbrot-Zooms<ref>[https://www.foerstemann.name/dokuwiki/doku.php?id=log%20z%20-mandelbrot-zooms log(z)-Mandelbrot-Zooms by Thorsten Forstemann]</ref> = side scrolling ( side scrolling fractal zoom )<ref>[https://www.youtube.com/watch?v=6kosH4H4dMA&lc=z13lvv0hqz33x30qu04cclgojqzjdffjvwo0k.1504628562849336 youtube video : Mandelbrot deep zoom to 2^142 or 5.5*10^42. Log(z) by SeryZone X ]</ref><ref>[https://www.youtube.com/watch?v=cH%20o5y3Mn40 Mandelbrot Zoom 333 - log(z)(Sery's Edition) by SeryZone Arts]</ref><ref>[https://www.youtube.com/watch?v=2o6vj9BWCAg Mandelbrot Mercator Testing by Fractal MathPro]</ref>
General names:
* graphical projection
* geometric transformation
=Description=
{|width="100%" cellspacing="0" cellpadding="15" valign="top" style="margin:0.8em 0; border: 1px solid SlateBlue; background:#F7F7FF;{{Text default color}}; "
|valign="top" style="border-right:1px dashed SlateBlue"|
<syntaxhighlight lang=txt>
Math notation
</syntaxhighlight>
<math>map : \mathbb{C} \to \mathbb{C}</math>
<math>c_e \leftarrow e^c+c_0</math>
|valign="top" style="border-right:1px dashed SlateBlue"|
<syntaxhighlight lang=c>
// c with complex type
complex double map(complex double c) {
return c_e = cexp(c) + c0; }
</syntaxhighlight>
|valign="top" style="border-right:1px dashed SlateBlue"|
<syntaxhighlight lang=c>
// c without complex type
cx_e = exp(creal(c)) * cos(cimag(c)) + realpart(c0); // real part of c_e
cy_e = exp(creal(c)) * sin(cimag(c)) + imagpart(c0); // imag part of c_e
</syntaxhighlight>
|}
==Features==
Maps
* Rectangle of Cartesian plane to quadratic sectors of polar coordinate,
* x is mapped to radius, and y to angle ( radians)<ref>[https://www.geogebra.org/m/Ac43DNNP Complex exponential map by Siamak]</ref>
* horizontal
** maps <math>c_0</math> to infinity ( limit of the sequence = [[Fractals/Iterations_in_the_complex_plane/Mandelbrot_set/MFpoint12|MF = the Myrberg-Feigenbaum point = the Feigenbaum Point]])
** maps important components related with above sequence to the same size
* vertical
** vertical coordinate are periodic of period <math>2\pi</math>, because they use trigonometric functions
Examples:
* sequence of root points for periods <math>p = 1*2^n</math> ( [[Fractals/Iterations_in_the_complex_plane/1over2_family|period doubling cascade]]) and the limit point of the sequence is [[Fractals/Iterations in the complex plane/def cqp#Myrberg-Feigenbaum|the Myrberg-Feigenbaum point]] <math>\mathbf{MF}_{1/2} = c_0 = -1.401155...</math>
* sequence of root points for periods <math>p = 1*3^n</math> and the limit point of the sequence is [[Fractals/Iterations in the complex plane/def cqp#Myrberg-Feigenbaum|the Myrberg-Feigenbaum point]] <math>\mathbf{MF} = c_0 = -1.7864402555636388747...</math>
<gallery>
Feigenbaum stretch.png
Feigenbaum stretch 3.png
</gallery>
==Informal description ==
* The exponential mapping transforms the entire complex plane into a strip that has unlimited length along the real axis, and a width of 2π along the imaginary axis. [https://mrob.com/pub/muency/exponentialmap.html Exponential Map from the Mandelbrot Set Glossary and Encyclopedia, by Robert Munafo, (c) 1987-2022]
* " The idea is to focus on a point in or near the Mandelbrot set, and create an image where one direction is the logarithm of the distance and the other one the angle. The result is very much like the astro-ph/031571 map<ref>[http://arxiv.org/abs/astro-ph/?0310571 A Map of the Universe by J. Richard Gott III, Mario Jurić, David Schlegel, Fiona Hoyle, Michael Vogeley, Max Tegmark, Neta Bahcall, Jon Brinkmann]</ref> and theXKCD cartoon versions.<ref>[http://xkcd.com/485/ xkcd : Depth]</ref> This map projection is conformal, so it does not distort local angles, and objects are usually recognizable on all scales." Anders Sandberg<ref>[http://www.aleph.se/andart/archives/2009/03/mercator_mandelbrot.html Mercator Mandelbrot by Anders Sandberg]</ref>
* Images of the Mandelbrot set with a logarithmic projection around a point c0: z-> (log(|z-c0|), arg(z-c0)). Anders Sandberg <ref>[https://flickr.com/photos/arenamontanus/albums/72157615740829949 flickr album : Mercator Mandelbrot Maps by Anders Sandberg]</ref>
* "it is a log map toward the target point (or, as some might say, a Mercator projection with the target point as South pole and complex ∞ as North pole); horizontally it is periodic and I have placed two periods side to side, whereas vertically it extends to infinity at the top and at the bottom, which corresponds to zooming infinitely far out or in, at a factor of exp(2π)≈535.5 for every size of a horizontal period. Horizontal lines (“parallels”) on the log map correspond to concentric circles around the target point, and vertical lines to radii emanating from it; and the anamorphosis preserves angles." David Madore <ref>[http://www.madore.org/~david/math/mandelbrot.html Mandelbrot set images and videos by David Madore]</ref>
* "The coordinate system is such that the angular component goes to the y-axis, and the radius goes to the x-axis of the resulting image. In addition, the x-axis (radius) is normalized with exp-function so that angles are preserved in this mapping. " Mika Seppä<ref>[http://neuro.hut.fi/~mseppa/images/Fract.html FRACTALS IN POLAR COORDINATES by Mika Seppä]</ref>
* log : "To illustrate the complexity of the boundary of the Mandelbrot set, Figure 8 renders the image of dM under the transformation log(z - c) for a certain c in the boudary of Mandelbrot set. Note the cusp on the main cardioid in the upper right; looking to the left in the figure corresponds to zooming in towards the point c. (Namely, c = -0.39054087... - 0.58678790i... the point on the boundary of the main cardioid corresponding to the golden mean Siegel disk.). Note the cusp on the main cardioid in the upper right; looking to the left in the figure corresponds to zooming in towards the point c. "<ref>[http://www.ams.org/journals/bull/1994-31-02/S0273-0979-1994-00519-1/S0273-0979-1994-00519-1.pdf FRONTIERS IN COMPLEX DYNAMICS by CURTIS T. MCMULLEN]</ref>
* "Legendary side scrolling fractal zoom. 1 Month + (Interpolator+Video Editor) = Log(z). This means logarithmic projection for this location, that gives this interesting side-scrolling plane ^^)"<ref>[https://www.youtube.com/watch?v=6kosH4H4dMA youtube video : Mandelbrot deep zoom to 2^142 or 5.5*10^42. Log(z) by SeryZone X]</ref>
* " There are no program that can render this fractal on log(Z) plane. But you can make it in Ultra Fractal or in similar software with programmable distributive. Formula is:C = exp(D), for D - is your zoomable coordinates" SeryZone X
* just c = c0 + cexp(x + i y) and x + i y = clog(c - c0), with scaling by 2pi/width (Claude)
* idea
** [https://arxiv.org/abs/astro-ph/0310571 A Map of the Universe by J. Richard Gott III, Mario Jurić, David Schlegel, Fiona Hoyle, Michael Vogeley, Max Tegmark, Neta Bahcall, Jon Brinkmann]
** [https://xkcd.com/485/ XKCD cartoon versions]
==Formal mathematical description ==
[[File:Complex log and exp mapping.png|thumb|right|Complex log and exp mapping]]
'''Forward transformation'''
Here transformation is a [[:w:Function_composition|composition]] of 2 transformations:
* [[:w:Exponentiation#Complex_exponentiation|complex exponential function]]: <math> f(c) = e^c </math>
* [[Fractals/Computer_graphic_techniques/2D/transformation#translation|geometric or complex translation]] <math>t(x) = x + c_0</math>
<math> c_e = t(f(c)) </math>
:<math>c_e \leftarrow e^c+c_0</math>
where:
* c is a parameter point from c plane ( flat image in Cartesian coordinate = linear scale on both axes). It is a a parameter of quadratic map <math>z^2 + c </math>
* <math>c_e</math> is a parameter in a new transformed plane ( log-polar image )
* <math>c_0</math> is a constant parameter (for translation). It is sometimes called center, but better name seems to be: target or limit point
* e is Euler's number, is a mathematical constant approximately equal to 2.71828,
'''Inverse transformation''':
:<math> c = ln(c_e - c_0)</math>
where:
* <math>ln</math> is natural logarithm
===exp===
Complex exponential map
The complex exponential function is '''periodic''' with period {{math|2''πi''}} and <math>\exp(z+2\pi i k)=\exp z</math> holds for all <math>z \in \mathbb{C}, k \in \mathbb{Z}</math>.
The exponential function maps any '''line''' in the complex plane to a '''logarithmic spiral''' in the complex plane with the center at the origin.
Two special cases exist:
* when the original line is parallel to the real axis, the resulting spiral never closes in on itself;
* when the original line is parallel to the imaginary axis, the resulting spiral is a circle of some radius.
Considering the complex exponential function as a function involving four real variables:
<math display="block">v + i w = \exp(x + i y)</math>
the graph of the exponential function is a two-dimensional surface curving through four dimensions.
Starting with a color-coded portion of the <math>xy</math> domain, the following are depictions of the graph as variously projected into two or three dimensions.
<gallery caption="Graphs of the complex exponential function" class="center" mode="packed" style="text-align:left" heights="200px">
Complex exponential function graph domain xy dimensions.svg|Checker board key:<br> <math>x> 0:\; \text{green}</math><br> <math>x< 0:\; \text{red}</math><br><math> y> 0:\; \text{yellow}</math><br><math> y< 0:\; \text{blue}</math>
Complex exponential function graph range vw dimensions.svg|Projection onto the range complex plane (V/W). Compare to the next, perspective picture.
Complex exponential function graph horn shape xvw dimensions.jpg|Projection into the <math>x</math>, <math>v</math>, and <math>w</math> dimensions, producing a flared horn or funnel shape (envisioned as 2-D perspective image).
Complex exponential function graph spiral shape yvw dimensions.jpg|Projection into the <math>y</math>, <math>v</math>, and <math>w</math> dimensions, producing a spiral shape. (<math>y</math> range extended to <math>\pm2\pi</math>, again as 2-D perspective image)
</gallery>
The second image shows how the domain complex plane is mapped into the range complex plane:
* zero is mapped to 1
* the real <math>x</math> axis is mapped to the positive real <math>v</math> axis
* the imaginary <math>y</math> axis is wrapped around the unit circle at a constant angular rate
* values with negative real parts are mapped inside the unit circle
* values with positive real parts are mapped outside of the unit circle
* values with a constant real part are mapped to circles centered at zero
* values with a constant imaginary part are mapped to rays extending from zero
The third and fourth images show how the graph in the second image extends into one of the other two dimensions not shown in the second image.
The third image shows the graph extended along the real <math>x</math> axis. It shows the graph is a surface of revolution about the <math>x</math> axis of the graph of the real exponential function, producing a horn or funnel shape.
The fourth image shows the graph extended along the imaginary <math>y</math> axis. It shows that the graph's surface for positive and negative <math>y</math> values doesn't really meet along the negative real <math>v</math> axis, but instead forms a spiral surface about the <math>y</math> axis. Because its <math>y</math> values have been extended to {{math|±2''π''}}, this image also better depicts the 2π periodicity in the imaginary <math>y</math> value.
===Log===
Complex logarithm as a conformal map<ref>[[:w:Complex_logarithm#The_complex_logarithm_as_a_conformal_map|The complex logarithm as a conformal map in wikipedia]]</ref>
Since a branch of '''<math>\log z</math>''' is holomorphic, and since its derivative '''<math>\log z</math>''' is never 0, it defines a conformal map.
For example, '''the principal branch''' <math>w = \operatorname{Log} z</math>, viewed as a mapping from <math>\mathbb{C}-\mathbb{R}_{\le 0}</math> to the horizontal strip defined by <math>\left| \operatorname{Im}z \right| < \pi</math>, has the following properties, which are direct consequences of the formula in terms of polar form:
* Circles<ref>Strictly speaking, the point on each circle on the negative real axis should be discarded, or the principal value should be used there.</ref> in the ''z''-plane centered at 0 are mapped to vertical segments in the ''w''-plane connecting <math>a - \pi i</math> to <math>a + \pi i</math>, where ''<math>a</math>'' is the real log of the radius of the circle.
* Rays emanating from 0 in the ''z''-plane are mapped to horizontal lines in the ''w''-plane.
Each circle and ray in the ''z''-plane as above meet at a right angle. Their images under Log are a vertical segment and a horizontal line (respectively) in the ''w''-plane, and these too meet at a right angle. This is an illustration of the conformal property of Log.
[[File:Complex log mapping.svg|thumb|right|Complex log mapping maps radii to horizontal lines and circles to vertical lines]]
==description for programmers ==
<syntaxhighlight lang=c>
// https://code.mathr.co.uk/mandelbrot-graphics/blob/HEAD:/c/lib/m_d_transform.c
static void m_d_transform_exponential_forward(void *userdata, double _Complex *c, double _Complex *dc) {
m_d_transform_exponential_t *t = userdata;
double _Complex c0 = *c;
double _Complex dc0 = *dc;
*c = cexp(c0) + t->center;
*dc = dc0 * cexp(c0);
}
static void m_d_transform_exponential_reverse(void *userdata, double _Complex *c, double _Complex *dc) {
m_d_transform_exponential_t *t = userdata;
double _Complex c0 = *c;
double _Complex dc0 = *dc;
*c = clog(c0 - t->center);
*dc = dc0 / (c0 - t->center);
}
</syntaxhighlight>
[https://www.complang.tuwien.ac.at/schani/mathmap/stills.html Filter Mercator from MathMap]
filter mercator (image in)
in(xy*xy:[cos(pi/2/Y*y),1])
end
Maxima CAS src code:
<pre>
(%i1) kill(all);
(%i2) display2d:false;
(%i3) ratprint : false; /* remove "rat :replaced " */
(%i4) c:cx +cy*%i$
(%i5) c0:c0x+c0y*%i$
(%i6) realpart(c0 + exp(c));
(%o6) %e^cx*cos(cy)+c0x
(%i7) imagpart(c0 + exp(c));
(%o7) %e^cx*sin(cy)+c0y
(%i8) cabs(c0 + exp(c));
(%o8) sqrt((%e^cx*sin(cy)+c0y)^2+(%e^cx*cos(cy)+c0x)^2)
(%i9) carg(c0 + exp(c));
(%o9) atan2(%e^cx*sin(cy)+c0y,%e^cx*cos(cy)+c0x)
</pre>
Notes
* the mapping is '''periodic''' because there are trigonometric functions inside
<pre>
(%i1) kill(all);
(%i2) display2d:false;
(%i3) ratprint : false; /* remove "rat :replaced " */
(%i4) ce:ceex+cey*%i;
(%i5) c0:c0x+c0y*%i;
(%i6) realpart(log(ce - c0));
(%o6) log((cey-c0y)^2+(ceex-c0x)^2)/2
(%i7) imagpart(log(ce - c0));
(%o7) atan2(cey-c0y,ceex-c0x)
</pre>
<syntaxhighlight lang=glsl>
// https://www.foerstemann.name/dokuwiki/doku.php?id=log_z_-mandelbrot-zooms
// log(z)-Mandelbrot-Zooms by
<languageVersion: 1.0;>
kernel zoomer
< namespace : "Zoomer"; vendor : "private"; version : 2; description : "zoomer 2"; >
{
const float PI = 3.14159265;
const float EU = 2.71828;
parameter float translate <
minValue:float(0);
maxValue:float(400.0);
defaultValue:float(0.0); >;
parameter float rotate <
minValue:float(0.0);
maxValue:float(960.0);
defaultValue:float(0.0); >;
input image4 iImage1;
input image4 iImage2;
input image4 iImage3;
input image4 iImage4;
output float4 outputColor;
void evaluatePixel()
{
float2 position = outCoord() - float2(479.5,199.5);
float2 tmp = outCoord();
tmp.y = abs(log(sqrt(pow(position.x,2.0) + pow(position.y,2.0))/510.0))*30.474;
tmp.x = mod((atan(position.x, position.y)/PI + 1.0)*480.0, 958.5) ;
position = tmp + float2(rotate,translate);
position.x = mod(position.x,958.5)+1.0;
if ( position.y < 398.5) {outputColor = sampleLinear( iImage1, position );}
else if ( position.y < 797.0) {outputColor = sampleLinear( iImage2, position - float2( 0.0 , 398.0 ));}
else if ( position.y < 1199.5) {outputColor = sampleLinear( iImage3, position - float2( 0.0 , 796.0 ));}
else {outputColor = sampleLinear( iImage4, position - float2( 0.0 , 1194.0 ) );}
}
}
</syntaxhighlight>
===center===
<math>c_0</math> is a constant parameter (for translation = offset).
It is sometimes called center, but better name seems to be:
* target
* limit point
* offset or translation
The target point ( center) is projected onto -∞+0i in the exponential-mapped view. It would be intinitely far to the left and it is not seen on the image.
===zoom===
* the leftmost column of the image has the minimal zoom ( the biggest plane radius )
* the rightmost column of the image has the maximal zoom ( the smallet plane radius )
=== exponential grid scan ===
Conventions:
* Robert Munafo generate the angle based on the horizontal pixel coordinate, and the radius from the vertical pixel coordinate ( image is in the vertical position , it is standing on the shorter dimension)
* the normal way is to have the angle come from the vertical pixel coordinate ( image is in the horizontal position , it is lying on the longer dimension)
The grid scan with exponential coordiante mapping is different then [[Fractals/scanning#standard|the standard scan for flat images]].
<syntaxhighlight lang="c">
for (int j = 0; j < h; ++j) { // vertical coordinate = number of the rows
double e_angle = ((double) j) * px / r * 3.14159265359; // Robert's way: angle from 0 to 2π.
for (int i = 0; i < w; ++i) { // horizontal coordinate = number of the columns
e_radius = ((double) i) * px / r * 3.14159265359;
.....
}
</syntaxhighlight>
Description
* image_width is the maximal number of pixels = width of the image in pixels ( integer number)
Here:
* pixel coordinate j is going from 0 to image_height - 1
* so j/pixel_height goes from 0.0 to 1.0
* therfore angle goes from 0 to 2 pi
Claude's way is mathematically correct: the angle is usually thought of as going from -π to π, not from 0 to 2π. To fix this part, you can adjust your pixel coordinate right before computing an angle from it. Change this:
double e_angle = ((double) j) * px / r * 3.14159265359;
to this:
double e_angle = ((double) (j-h/2)) * px / r * 3.14159265359;
Notes
* e_radius is a linear function of i
* e_angle is a linear function of j
===computing pixel coordinate===
Here is example by by Robert Munafo<ref>[https://mrob.com/pub/muency/exponentialmap.html Exponential Map from the Mandelbrot Set Glossary and Encyclopedia, by Robert Munafo, (c) 2010 Dec 5. ]</ref>
<syntaxhighlight lang=c>
/* Inputs are:
ctr_r is the real coordinate of the center of the view we want to plot
ctr_i is the imaginary coordinate of the center of the view
real_width is the width of the image (in real coordinates). this should reflect the width when "zoomed in" all the way
pixel_width is the number of pixels per row of the image we want to create
pixel_height is the number of rows of pixels, or pixels per column
This setup code computes:
px_spacing is the width of the image (in real coordinate)
divided by the number of pixels in a row
halfwidth is half the width of the image (in real coordinate)
halfheight is half the height of the image (in imaginary coordinate)
min_r is the real coordinate of the left edge of the image
max_i is the imaginary coordinate of the top of the image
*/
void setup()
{
px_spacing = real_width / pixel_width;
halfwidth = real_width / 2.0;
halfheight = halfwidth * pixel_height / pixel_width;
min_r = ctr_r - halfwidth;
max_i = ctr_i + halfheight;
}
/* Plot a single pixel, row i and column j. Use as many rows as you need
for the image to show the whole Mandelbrot set. */
void pixel_53(int i, int j, int itmax)
{
double cr, ci, offset_r, offset_i, angle, log_radius;
/* compute angle and radius. Note that pixel_width is the number of
pixels wide of the image, and j goes from 0 to pixel_width-1. This
means that "j/pixel_width" goes from 0.0 to 1.0, and therefore
angle goes from 0 to 2 pi. log_radius needs to be computed the
same way in order for shapes to be preserved, which happens because
the complex exponential function is a conformal map.
Important: the row coordinate i can be as big as you want: add as many
rows of pixels as are needed for the "log_radius" to get close to 1.
This ensures that exp(log_radius) gets big enough to go beyond the
area that has the Mandelbrot set in it. */
angle = (((double) j) / pixel_width) * 2.0 * 3.14159265359;
log_radius = (((double) i) / pixel_width) * 2.0 * 3.14159265359;
/* compute offsets = translation = add complex number offset */
offset_r = cos(angle) * halfwidth * exp(log_radius);
offset_i = sin(angle) * halfwidth * exp(log_radius);
ci = ctr_i + offset_i;
cr = ctr_r + offset_r;
evaluate_and_plot(cr, ci, itmax, i, j);
}
</syntaxhighlight>
Compare with
* [https://mathr.co.uk/mandelbrot/exponential_strip.svg exponential strip by Claude Heiland-Allen]: The rendering of the final video can be accelerated by computing exponentially spaced rings around the zoom center, before reprojecting to a sequence of flat images. In case of problems : https://mathr.co.uk/mandelbrot/exponential_strip.svg
===aspect ratio===
* For best (more conformal) results use a wide aspect ratio (9:1 works well, window size 1152x128 or 1536x170).
===scale factor R===
To minimize the total number of pixels that need calculating, which is proportional to<ref>[https://mathr.co.uk/blog/2020-06-18%20optimizing%20zoom%20animations%20again.html optimizing zoom animations again by Claude ]</ref>
<math> K = \frac{R^2 - 1}{log R}</math>
Define the efficiency of zoom by
<math>\frac{2}{K}</math>
then:
* the traditional R=2 has an efficiency of only 46%,
* R=4/3 has 74%
* R=8/7 has 87% efficacy
where
* video image size is W×H
=Videos=
* [https://www.youtube.com/watch?v=7EHB3ty-A_M Mercator - Scrolling Mandelbrot Fractal by Mathtown]
* [https://www.youtube.com/watch?v=UHzAY5Q7ji0 Mappings by the exponential function by William Nesse]
* [https://www.youtube.com/watch?v=gJdXyPiipS0 Mapping properties of the exponential function by MatheMagician]
* [https://www.youtube.com/watch?v=_vcU0g2MCDo The function f(z)=exp(z) by Michael Robinson]
* [https://www.youtube.com/watch?v=wzRumG7TW3s Complex: visualizing exponential map and local inverse by James Cook]
* [https://www.youtube.com/watch?v=2o6vj9BWCAg Mandelbrot Mercator Testing by Fractal MathPro]
=Images=
* [[:commons:Category:Mandelbrot sets - Mercator projection|Category:Mandelbrot sets - Mercator projection in commons]]
<gallery>
Lyapunov exponent of real quadratic map.png| without transformation
Lyapunov_exponent_of_real_quadratic_map_with_exponential_transformation_on_the_real_axis.png|real (= 1D) version
Bifurcation diagram of complex quadratic map.png|1D: 3 windows with non-linear, i.e. logarithmic x-axis scale:
Feigenbaum stretch.png|complex (= 2D) version
Fractal 31-08-2018 12;31;13.png|normal projection
Fractal 31-08-2018 12;31;26.png|polar projection
M(3,1) Misiurewicz point looks like at 1E10 magnification (bottom) use the exponential map.jpg|M(3,1) Misiurewicz at 1E10 magnification (bottom) use the exponential map
Mandelbrot set exponential mapping. Example 8.png
Mathmap-mercator.gif| Mercator Effect in GIMP with MathMap
</gallery>
{{multiple image
| align = center
| direction = vertical
|
| image1 = Mandelbrot set exponential mapping c=-1.7864402555636389.png
| width1 = 1024
| alt1 =
| caption1 =
| image2 = Feigenbaum stretch 3.png
| width2 = 1024
| alt2 =
| caption2 =
| footer = 2 images with the same parmeter. In the upper image main antenna is on both sides, in the lower one in the center of the image
}}
<gallery caption="Mercator" |align="left">
Mercator Mandelbrot (3381920619).png| Map of the region close to the Myrberg-Feigenbaum point. The buds of the main Mandelbrot set converge geometrically towards this place (at a rate set by Feigenbaum's constant), producing the regularly spaced buds at the top and bottom. Since I did not have an exact coordinate for it, the map is centered a little bit away.
Deep_Mercator_Mandelbrot_(3426572062).png|This image corresponds to a 10^30 zoom around a point (I just used 30 digits of precision, so there are artefacts at the left edge
Deep_Mercator_Mandelbrot_(3426573430).png| This image corresponds to a 10^30 zoom around a point (I just used 30 digits of precision, so there are artefacts at the left edge).
Deeper_Mercator_Mandelbrot_(3430921497).png| 10^60 zoom. The banded structure occurs because the zoom passes through the embedded Julia sets around smaller Mandelbrot sets; each new Mandelbrot zoomed past adds their own Julia set to the sequence. The center point is c=-1.256827152259138864846434197797294538253477389787308085590211144291 +0.37933802890364143684096784819544060002129071484943239316486643285025i
Mercator Mandelbrot (3381359926).png|right|thumb|Zooms of the Mandelbrot set around a point projected so that the distance to the point forms a logarithmic scale. Details on the left edge are ~10^15 times smaller than on the right edge. The rightmost black blob in the pictures is the main "continent" of the set. Satelite sets of different sizes can be seen linked by fractal chains of varying complexity. The colors are set using the distance estimator method.
</gallery>
=How to read location from exponential image ?=
* [https://fractalforums.org/fractal-programs-discussion-help-and-support/12/can-you-find-the-location-of-this-fractal/4963/msg36157 fractalforums.org : can-you-find-the-location-of-this-fractal ?]
* "An inverse mapping (using the complex logarithm function) is used to compute the location (in the strip) of needed data for any given location in the normal orthogonal coordinate space." Robert Munafo<ref>[https://mrob.com/pub/muency/exponentialmap.html exponential map From the Mandelbrot Set Glossary and Encyclopedia, by Robert Munafo, (c) 1987-2022.]</ref>
Tips:
* the image is not symmetric ( up and down) so imaginary part of c0 is not zero
=Implementations=
Fractal programs
* [[Fractals/fraktaler-3|fraktaler-3]]
* [[Fractals/ultrafractal#exponential|UltraFractal]]
* [[Fractals/fractalzoomer#Polar_Projection| Polar_Projection in fractalzoomer]]
* [[Fractals/Fractalshades#exponential |Fractalshades - python program by Geoffroy Billotey]]
* [[Fractals/emndl|emndl: exponential strip visualisation of the Mandelbrot set, program by Claude Heiland-Allen]]
* [https://github.com/adammaj1/PFRACT pfract - console c program by Mika Seppä]
* [https://mathr.co.uk/blog/2011-04-23_emndl-0.1_released.html emndl: mathr's exponential strip mandelbrot set renderer]: it is: c = c0 + cexp(x + i y) and x + i y = clog(c - c0), with scaling by 2pi/width
* [https://gbillotey.github.io/Fractalshades-doc/examples/projections/P01-feigenbaum%20expmap.html Fractalshades doc : P01-feigenbaum expmap ]
'''[[Fractals/kallesfraktaler|Kalles Fractaler]] and zoomasm'''
* The rendering of the final video can be accelerated by computing exponentially spaced rings around the zoom center, before reprojecting to a sequence of flat images.
* [[Fractals/kallesfraktaler|kf-2.15]] supports rendering EXR keyframes in exponential map form
* [https://fractalforums.org/kalles-fraktaler/15/zoomasm/3851 zoomasm] can assemble above keyframes into a zoom video. zoomasm works from EXR, including raw iteration data, and colouring algorithms can be written in OpenGL shader source code fragments
* [[Fractals/kf-extras|kf-extras by Claude Heiland-Allen]] - has the exponential map (aka log polar or mercator projection) convertor
'''OpenCV'''
* [https://docs.opencv.org/3.4/da/d54/group__imgproc__transform.html#ga49481ab24fdaa0ffa4d3e63d14c0d5e4 opencv 3.4 warpPolar() function]
* [https://areshopencv.blogspot.com/2010/12/logpolar-transform-using-camera.html logpolar transform using Camera by Aresh T. Saharkhiz]
* [https://stackoverflow.com/questions/2164570/reprojecting-polar-to-cartesian-grid stackoverflow question: reprojecting-polar-to-cartesian-grid]
* [https://www.developpez.net/forums/d580157/c-cpp/bibliotheques/opencv/transformation-polaire-cvlogpolar/ descr]
* [https://stackoverflow.com/questions/72080160/how-to-tune-log-polar-mapping-in-opencv stackoverflow question: how-to-tune-log-polar-mapping-in-opencv]
* [https://stackoverflow.com/questions/51675940/converting-an-image-from-cartesian-to-polar-limb-darkening stackoverflow question : converting-an-image-from-cartesian-to-polar-limb-darkening]
'''ImageMagic'''
* [http://www.fmwconcepts.com/imagemagick/pano2fisheye/index.php pano2fisheye - Transforms a spherical panorama to a fisheye view] = ? Reverse polar coordinates?
* [https://legacy.imagemagick.org/Usage/distorts/#depolar distorts depolar]
* [https://im.snibgo.com/poldist.htm snibgo's ImageMagick pages: Polar distortions]
'''processing'''
* [https://forum.processing.org/one/topic/how-to-change-an-image-from-x-y-coordinate-to-polar-coordinate.html forum.processing : how-to-change-an-image-from-x-y-coordinate-to-polar-coordinate]
'''sci-kit'''
* [https://scikit-image.org/docs/dev/auto_examples/registration/plot_register_rotation.html#sphx-glr-download-auto-examples-registration-plot-register-rotation-py Using Polar and Log-Polar Transformations for Registration]
* [https://scikit-image.org/docs/dev/api/skimage.transform.html#skimage.transform.warp_polar skimage.transform : wrp_polar]
'''Mathworks'''
* [https://uk.mathworks.com/matlabcentral/fileexchange/27023-log-polar-image-sampling Log-polar image sampling version 1.0.0.0 (4.33 KB) by David Young from mathworks]
==glsl==
A typical shader looks like this ( code by Thorsten Förstemann):
<syntaxhighlight lang="glsl">
// https://web.archive.org/web/20210715234846/https://www.foerstemann.name/dokuwiki/doku.php?id=log_z_-mandelbrot-zooms
<languageVersion: 1.0;>
kernel zoomer
< namespace : "Zoomer"; vendor : "private"; version : 2; description : "zoomer 2"; >
{
const float PI = 3.14159265;
const float EU = 2.71828;
parameter float translate <
minValue:float(0);
maxValue:float(400.0);
defaultValue:float(0.0); >;
parameter float rotate <
minValue:float(0.0);
maxValue:float(960.0);
defaultValue:float(0.0); >;
input image4 iImage1;
input image4 iImage2;
input image4 iImage3;
input image4 iImage4;
output float4 outputColor;
void evaluatePixel()
{
float2 position = outCoord() - float2(479.5,199.5);
float2 tmp = outCoord();
tmp.y = abs(log(sqrt(pow(position.x,2.0) + pow(position.y,2.0))/510.0))*30.474;
tmp.x = mod((atan(position.x, position.y)/PI + 1.0)*480.0, 958.5) ;
position = tmp + float2(rotate,translate);
position.x = mod(position.x,958.5)+1.0;
if ( position.y < 398.5) {outputColor = sampleLinear( iImage1, position );}
else if ( position.y < 797.0) {outputColor = sampleLinear( iImage2, position - float2( 0.0 , 398.0 ));}
else if ( position.y < 1199.5) {outputColor = sampleLinear( iImage3, position - float2( 0.0 , 796.0 ));}
else {outputColor = sampleLinear( iImage4, position - float2( 0.0 , 1194.0 ) );}
}
}
</syntaxhighlight>
==Python==
* [https://stackoverflow.com/questions/3798333/image-information-along-a-polar-coordinate-system stackoverflow question: image-information-along-a-polar-coordinate-system]
The images created in this way are also called:
* Exponential Maps
* Mercator-Mandelbrot Maps
* Mercator projection of the Riemann number ball.<ref>[http://www.madore.org/~david/math/mandelbrot.html Mandelbrot set images and videos by David Madore] </ref><ref>[https://mrob.com/pub/muency/exponentialmap.html Exponential Map in Mu-Ency - The Encyclopedia of the Mandelbrot Set by Robert P. Munafo]</ref>
[[File:Mandelbrot numpy set 3.png|thumb|right|Logarithmic projection and zoom images of the Mandelbrot set (more details in the image description)]]
In the following program example, a logarithmic projection of the Mandelbrot set is calculated ,
The Mandelbrot set is calculated with NumPy using complex matrices. A logarithmic projection presented by David Madore and Anders Sandberg is used. This projection makes the calculation of zoom animations much easier
The logarithmic projection allows the creation of zoom animations of the Mandelbrot set to be extremely accelerated (see also the animation by Thorsten Förstemann and the coordinate analysis by Claude Heiland-Allen
<ref>[https://web.archive.org/web/20210715234846/https://www.foerstemann.name/dokuwiki/doku.php?id=log_z_-mandelbrot-zooms Log(z)-Mandelbrot-Zooms by Thorsten Förstemann]</ref><ref>[https://www.youtube.com/watch?v=cH_o5y3Mn40 Animation on youtube.com by Thorsten Förstemann: Mandelbrot Zoom 333 - log(z)(Sery's Edition) SeryZone Arts]</ref><ref>[https://mathr.co.uk/blog/2020-06-18_optimizing_zoom_animations_again.html Optimizing zoom animations again by Claude Heiland-Allen]</ref><ref>[https://mathr.co.uk/web/m-location-analysis.html#Mercator-Mandelbrot Analysis of location by Claude Heiland-Allen]</ref>
<div style="font-size: 70%; box-shadow: 0 0 16px #e0e0e0; max-width: 500px;">
<syntaxhighlight lang="python">
import numpy as np
import matplotlib.pyplot as plt
d, h = 200, 1000 # Pixeldichte (= Bildbreite) und Bildhöhe
n, r = 800, 5000 # Anzahl der Iterationen und Fluchtradius (r > 2)
x = np.linspace(0, 2, num=d+1)
y = np.linspace(0, 2 * h / d, num=h+1)
A, B = np.meshgrid(x * np.pi, y * np.pi)
C = 4.0 * np.exp((A + B * 1j) * 1j) + (- 1.748764520194788535 + 3e-13 * 1j)
Z, dZ = np.zeros_like(C), np.zeros_like(C)
D = np.zeros(C.shape)
for k in range(n):
M = Z.real ** 2 + Z.imag ** 2 < r ** 2
Z[M], dZ[M] = Z[M] ** 2 + C[M], 2 * Z[M] * dZ[M] + 1
N = abs(Z) > 2 # Distanzschätzung des Außenbereichs
D[N] = np.log(abs(Z[N])) * abs(Z[N]) / abs(dZ[N])
plt.imshow(D.T ** 0.05, cmap=plt.cm.nipy_spectral, origin="lower")
plt.savefig("Mercator_Mandelbrot_map.png", dpi=200)
</syntaxhighlight>
</div>
When estimating the distance, the derivative <math>dz_n = z_n\!'(c)</math> is also required.
The first polynomials are
* <math>z_0 = 0</math>
* <math>z_1 = c</math>
* <math>z_2 = c^2+c</math>
* <math>z_3 = (c^2+c)^2+c</math>,
the corresponding derivatives are
* <math>dz_0 = 0</math>
* <math>dz_1 = 1</math>
* <math>dz_2 = 2c+1</math>
* <math>dz_3 = 2(c^2+c)(2c +1)+1</math>.
All other polynomials and derivatives result from the iteration rule <math>z_{k+1} = z_k^2+c</math> and the derivation rule <math >dz_{k+1} = 2z_k dz_k+1</math>.
To use the estimation formula
:<math>\delta_n = \log(|z_n|) \cdot |z_n| / |dz_n|</math>
you can use the simplified sequences <math>z_{k+1}=z_k^2+0</math> and <math>dz_{k+1} = 2z_k dz_k+0</math> with the starting values
* <math>z_0 = c</math>
* <math>dz_0 = 1</math>
can be considered.
The first polynomials are
* <math>z_0 = c</math>
* <math>z_1 = c^2</math>
* <math>z_2 = c^4</math>
* <math>z_3 = c^8</math>,
the corresponding derivatives are <math>dz_0 = 1</math>, <math> dz_1 = 2c</math>, <math>dz_2 = 4c^3</math> and <math>dz_3 = 8c^7</math>.
In general, this is how you get the polynomial <math>z_n = c^{2^n}</math> and the derivative <math>dz_n = 2^n c^{2^n-1}</math>.
The associated Julia set is exactly the edge of the unit circle (cf. the [[Julia-Menge#Dynamik_am_Example_f(z)_=_z²|Example on the dynamics of ''f(z) = z²'']] in the article on Julia -Quantity, the short justification in van den Doel or the comprehensive analysis in Dang, [[Louis H. Kauffman|Kauffman]] and Sandin).<ref>[https://persianney.com/fractal/fractalNotes.pdf Notes on Mandelbrot set (Draft) by Kees van den Doel]</ref><ref>[https://www.evl.uic.edu/hypercomplex/html/book/book.pdf Hypercomplex Iterations: Distance Estimation and Higher Dimensional Fractals by Yumei Dang, Louis Kauffman, Daniel Sandin]</ref>
The estimation formula results in
:<math>\delta_n = \log(|c|^{2^n}) \cdot |c|^{2^n} / (2^n |c|^{2^n -1}) = \ln(|c|) \cdot |c|</math>
which is a good approximation for the distance to the unit circle when the point <math>c</math> is close to the edge:
:<math>|c| = 1{,}1</math>
gives
:<math>\delta_n = \ln(1{,}1) \cdot 1{,}1 \approx 0{,}1</math>
and
:<math>|c | = 1{,}01</math> gives <math>\delta_n = \ln(1{,}01) \cdot 1{,}01 \approx 0{,}01</math>.
So if the real distance to the Mandelbrot set is <math>\delta</math>, the estimation formula gives the value
:<math>\delta_n = \log(|z_n|) \cdot |z_n| / |dz_n| \approx \ln(1+\delta) \cdot (1+\delta) \approx \delta</math>.
However, it is not true that the limit <math>\lim_{n \to \infty} \delta_n</math> converges to the real distance <math>\delta</math>; in fact, only weaker inequalities apply. You will often find a factor <math>2</math> or <math>0{.}5</math> in the estimation formula, depending on whether the distances are overestimated or underestimated.<ref>[https://www.math.univ-toulouse.fr/~cheritat/wiki-draw/index.php/Mandelbrot_set#Boundary_detection_methods_via_distance_estimators Boundary detection methods via distance estimators by Arnaud Chéritat at the Institute of Mathematics, Toulouse date=2016 access=2023-07-02]</ref>
<ref>[http://blog.hvidtfeldts.net/index.php/2011/09/distance-estimated-3d-fractals-v-the-mandelbulb-different-de-approximations/ Distance Estimated 3D Fractals (V) |titlerg=The Mandelbulb & Different DE Approximations by Mikael Hvidtfeldt Christensen Syntopia: Generative Art, 3D Fractals, Creative Computing 2011]</ref>
[[File:Mandelbrot numpy set 4.png|thumb|Deep zoom of the Mandelbrot set in logarithmic projection (more details in the image description)]]
=References=
<references/>
{{BookCat}}
5iq8xgat6jjdsad96jlxducx20200mx
Lombard/How to ask and express the weather
0
451530
4676026
4621626
2026-10-14T11:46:55Z
~2026-55101-91
3628399
/* How to ask for the weather */
4676026
wikitext
text/x-wiki
{{Lombard/Sentence syntax}}
{{Lombard-NOL}}
==How to ask for the weather==
<div style="letter-spacing:0px; font-size:120%">'''Che''' (interrogative adjective) + '''temp''' + ([[Lombard/Subject personal pronouns|weak pronouns of 3^ person singular]]) + '''3^''' person in the present indicative mood of the verb '''fà''' + '''?'''</div>
::Example (in [[Lombard/The dialects of Lombard|Milanese dialect]])
::'''Che temp el fà?''' ( {{Wt/lmo/-MI}} )
==How to express the weather==
{| class="wikitable"
!Expression
!In English!!Immagine di esempio!!Dialects
|-
|''(el) fà [[wiktionary:lmo:cald|cald]]'' (1)<br> ''fà [[wiktionary:lmo:cold|cold]]'' (2)
|It’s warm
|[[File:20050501_1315_2558-Bimetall-Zeigerthermometer.jpg|thumb|150px]]
|(1) {{Wt/lmo/-MI}}<br>(2) {{Wt/lmo/-Lagh}}
|-
|''(a) fà on cald de s'ceppà i sass''
|(A way of saying that it is very hot)
|
|
|-
|''l'è [[wiktionary:lmo:sofegh|sofegh]]''/a gh'è [[wiktionary:lmo:sofegh|sofegh]]"
|It’s sultry
| -
|
|-
|''(el) fà [[wiktionary:lmo:fregg|fregg]]''
|It’s cold
| -
|
|-
|''fà on frecc de biss''
|(A way of saying that it is very hot)
|
|
|-
|''se stà ben''
|
(way of saying it's mild)
| -
|
|-
|''l'è sech''
|It’s dry
|
||
|-
|''l'è bell''
| the weather is nice
(way to say that the sun shines)
|[[File:Monza-Parco-Villa-Reale-Cascina-del-Sole-00.jpg|thumb|150px]]
|
|-
|''(a) gh'è el sol''
|It’s sunny
|[[File:Monza-Parco-Villa-Reale-Cascina-del-Sole-00.jpg|thumb|150px]]
|
|-
|''(a) gh'è foeura la [[wiktionary:lmo:luna|luna]]'' (1)<ref>Claudio Beretta, A lezione di grammatica milanese, Circolo Filologico Milanese, pag.165</ref>
|There’s a moon
|[[File:Lisbona_notturna.JPG|thumb|150px]]
|(1) {{Wt/lmo/-MI}}
|-
|''l'è seren''
|the wether is clear
|[[File:Monza-Parco-Villa-Reale-Cascina-del-Sole-00.jpg|thumb|150px]]
|
|-
|''l'è nivol''
|It’s cloudy
|[[File:La_Spezia_-_L'arsenale.JPG|thumb|150px]]
|
|-
|''l'è fosch''
|It’s dark
|[[File:Cloudy_Sky2.JPG|thumb|150px]]
|
|-
|''el và e el vegn''
|It’s changeable
|[[File:SunshowerCarPark.jpg|thumb|150px|temp variabel]]
|
|-
|''(a) gh'è la [[wiktionary:lmo:scighera|scighera]]'' (1)
''(a) gh'è la [[wiktionary:lmo:nebia|nebia]]'' (2)
|It’s foggy
|[[File:NebbiaCassano2.JPG|thumb|150px]]
|
|-
|''el và a [[wiktionary:lmo:pioeuver|pioeuver]]''
|It’s going to rain
|
|
|-
|''el [[wiktionary:lmo:comenzà|comenza]] a pioeuver''
|It start sto rain
|
|
|-
|''l'è adree a [[wiktionary:lmo:pioeuver|pioeuver]]''
|It’s raining
|[[File:22_Regen_ubt.jpeg|thumb|150px]]
|
|-
|''el seguita a [[wiktionary:lmo:pioeuver|pioeuver]]''(1)<br>''el suguta a pioeuver'' (2)
|It continue sto rain
|[[File:22_Regen_ubt.jpeg|thumb|150px]]
|
|-
|''vegn giò una gotta'' (1)<br> ''el fà finta de pioeuver'' (2)
|(way to say that it rains very little)
|
|
|-
|''(el) [[wiktionary:lmo:piovisnà|piovisna]]''
|It drizzle / It’s drizzling
|[[File:Row_of_poplars_in_the_drizzle_-_geograph.org.uk_-_591822.jpg|thumb|150px]]
|
|-
|'' (el) pioeuv''
|It rains / It’s raining
|[[File:22_Regen_ubt.jpeg|thumb|150px]]
|
|-
|''(el) pioeuv che Dio le manda'' (1)<ref name=val369>Circolo Filologico Milanese (2018). dizionario Milanese. Antonio Vallardi, pag. 369. {{#isbn:978-88-6987-846-6}}.</ref><br>
''(el) pioeuv a la roversa'' (2)<ref name=val369/><br>
''la ven sgiò a segge'' (3)<ref name=val369/><br>
''(el) pioeiv che 'l se inversa'' (4)<ref name=val369/>
|(ways to say it rains very hard)
|
|(1-2-3-4){{Wt/lmo/-MI}}
|-
|''(el) [[wiktionary:lmo:fiocà|fioca]]''
|It snows / It’s snowing
|[[File:Falling_Snow_-_stuck_at_home_(3234280718).jpg|thumb|150px]]
|
|-
|''el fà [[wiktionary:lmo:tempesta|tempesta]]'' ...
|It hails /It’s hailing
|[[File:Bogota_hailstorm.jpg|thumb|150px]]
|
|-
|''gh'è el [[wiktionary:lmo:vent/vent|vent]]'', ''el tira vent''
|It’s windy
|[[File:Cherry_tree_moving_in_the_wind_1.gif|thumb|150px]]
|
|-
|''balca el vent'' (1) ''cessa el vent'' (2)
|The wind ceases
|
|(2) italianism
|-
|''l'ha cambiad el [[wiktionary:lmo:cribi|cribi]]''
|the intensity of the rain has changed
|► see on the Wiktionary ►►►[[wiktionary:lmo:cribbi|cribi]]
|
|-
|''(a) gh'è la sguazza''(1)<br>''gh'è la prina'' (2)
|there’s frost
|[[File:Frostw.jpg|thumb|150px]]
|
|-
|''(a) gh'è la [[wiktionary:lmo:rosada|rosada]]''
|there is dew
|[[File:Rugiada_su_erba.jpg|thumb|150px]]
|
|-
|''(a) gh'è foeura i trii [[wiktionary:lmo:sol|sol]]''<ref name=val199>Circolo Filologico Milanese (2018). dizionario Milanese. Antonio Vallardi, pag. 199. {{#isbn:978-88-6987-846-6}}.</ref><br>
|(way to say the weather it’s a beautiful day)
|
|{{Wt/lmo/-MI}}
|-
|''el temp el s'è giustad''<ref name=val218/>
|(way to say that the weather is nice again)
|
|{{Wt/lmo/-MI}}
|-
|''temp de lader''<ref name=val218>Circolo Filologico Milanese (2018). dizionario Milanese. Antonio Vallardi, pag. 218. {{#isbn:978-88-6987-846-6}}.</ref><br>
|(way to say there’s rain and wind)
|
|{{Wt/lmo/-MI}}
|-
|''el temp el stà su''<ref name=val218>Circolo Filologico Milanese (2018). dizionario Milanese. Antonio Vallardi, pag. 218. {{#isbn:978-88-6987-846-6}}.</ref><br>
|the weather stays good
|
|{{Wt/lmo/-MI}}
|}
==References==
fc4z4x2p0ows0b9pr1k1hyfu45masmm
Template:Warning
10
453843
4675824
4271496
2026-10-13T13:02:54Z
~2026-55040-66
3628329
4675824
wikitext
text/x-wiki
{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{Mbox
| name = 6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!
| demospace = {{{demospace|}}}
| style = {{#if:{{{style|}}} |{{{style}}} }}
| subst = <includeonly>{{subst:substcheck}}</includeonly>
| type = content
| image = {{#if:{{{image|}}}| [[File:{{{image}}}|{{{imagesize|40px}}}|Warning]] }}
| small = {{{small|}}}
| smallimage = {{#if:{{{image|}}}| [[File:{{{image}}}|30px|Warning]]}}
| imageright = {{#if:{{{imageright|}}} |{{{imageright}}} |{{#if:{{{shortcut|{{{shortcut1|}}}}}} |{{Ombox/shortcut|{{{shortcut|{{{shortcut1|}}}}}}|{{{shortcut2|}}}|{{{shortcut3|}}}|{{{shortcut4|}}}|{{{shortcut5|}}}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}}}} }}
| textstyle = {{{textstyle|text-align: {{#if:{{{center|}}}|center|{{{align|left}}}}};}}}
| text = {{#if:{{{header|{{{heading|{{{title|}}}}}}}}} |<div style="{{{headstyle|text-align: {{#if:{{{center|}}}|center|left}};}}}">'''{{{header|{{{heading|{{{title|}}}}}}}}}'''</div>}}<!--
-->{{{text|{{{content|{{{reason|{{{1}}}}}}}}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}}}}
}}<noinclude>
<!-- Add categories to the /doc subpage; interwikis go to Wikidata. -->
{{Documentation}}
</noinclude>
94jhjxvrdpg2nu4zeliyfylao3inrto
4675825
4675824
2026-10-13T13:03:20Z
Veritas Sapientiae
3399623
[[WB:REVERT|Reverted]] edit by [[Special:Contributions/~2026-55040-66|~2026-55040-66]] ([[User talk:~2026-55040-66|talk]]) to last version by Leaderboard
4271125
wikitext
text/x-wiki
{{Mbox
| name = Warning
| demospace = {{{demospace|}}}
| style = {{#if:{{{style|}}} |{{{style}}} }}
| subst = <includeonly>{{subst:substcheck}}</includeonly>
| type = content
| image = {{#if:{{{image|}}}| [[File:{{{image}}}|{{{imagesize|40px}}}|Warning]] }}
| small = {{{small|}}}
| smallimage = {{#if:{{{image|}}}| [[File:{{{image}}}|30px|Warning]]}}
| imageright = {{#if:{{{imageright|}}} |{{{imageright}}} |{{#if:{{{shortcut|{{{shortcut1|}}}}}} |{{Ombox/shortcut|{{{shortcut|{{{shortcut1|}}}}}}|{{{shortcut2|}}}|{{{shortcut3|}}}|{{{shortcut4|}}}|{{{shortcut5|}}}}}}} }}
| textstyle = {{{textstyle|text-align: {{#if:{{{center|}}}|center|{{{align|left}}}}};}}}
| text = {{#if:{{{header|{{{heading|{{{title|}}}}}}}}} |<div style="{{{headstyle|text-align: {{#if:{{{center|}}}|center|left}};}}}">'''{{{header|{{{heading|{{{title|}}}}}}}}}'''</div>}}<!--
-->{{{text|{{{content|{{{reason|{{{1}}}}}}}}}}}}
}}<noinclude>
<!-- Add categories to the /doc subpage; interwikis go to Wikidata. -->
{{Documentation}}
</noinclude>
6vzaqvd2g0rpbfp6wqapmrxa5l2mdjy
4675828
4675825
2026-10-13T13:04:51Z
~2026-55040-66
3628329
Undid revision [[Special:Diff/4675825|4675825]] by [[Special:Contributions/Veritas Sapientiae|Veritas Sapientiae]] ([[User talk:Veritas Sapientiae|discuss]])
4675828
wikitext
text/x-wiki
{6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!{Mbox
| name = 6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!
| demospace = {{{demospace|}}}
| style = {{#if:{{{style|}}} |{{{style}}} }}
| subst = <includeonly>{{subst:substcheck}}</includeonly>
| type = content
| image = {{#if:{{{image|}}}| [[File:{{{image}}}|{{{imagesize|40px}}}|Warning]] }}
| small = {{{small|}}}
| smallimage = {{#if:{{{image|}}}| [[File:{{{image}}}|30px|Warning]]}}
| imageright = {{#if:{{{imageright|}}} |{{{imageright}}} |{{#if:{{{shortcut|{{{shortcut1|}}}}}} |{{Ombox/shortcut|{{{shortcut|{{{shortcut1|}}}}}}|{{{shortcut2|}}}|{{{shortcut3|}}}|{{{shortcut4|}}}|{{{shortcut5|}}}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}}}} }}
| textstyle = {{{textstyle|text-align: {{#if:{{{center|}}}|center|{{{align|left}}}}};}}}
| text = {{#if:{{{header|{{{heading|{{{title|}}}}}}}}} |<div style="{{{headstyle|text-align: {{#if:{{{center|}}}|center|left}};}}}">'''{{{header|{{{heading|{{{title|}}}}}}}}}'''</div>}}<!--
-->{{{text|{{{content|{{{reason|{{{1}}}}}}}}6776767676776767676 DRIIZZZZZY AHHHHHHHHHH!!!!!!!!}}}}
}}<noinclude>
<!-- Add categories to the /doc subpage; interwikis go to Wikidata. -->
{{Documentation}}
</noinclude>
94jhjxvrdpg2nu4zeliyfylao3inrto
4675835
4675828
2026-10-13T13:06:30Z
CptViraj
3232362
[[WB:REVERT|Reverted]] edit by [[Special:Contributions/~2026-55040-66|~2026-55040-66]] ([[User talk:~2026-55040-66|talk]]) to last version by Veritas Sapientiae
4271125
wikitext
text/x-wiki
{{Mbox
| name = Warning
| demospace = {{{demospace|}}}
| style = {{#if:{{{style|}}} |{{{style}}} }}
| subst = <includeonly>{{subst:substcheck}}</includeonly>
| type = content
| image = {{#if:{{{image|}}}| [[File:{{{image}}}|{{{imagesize|40px}}}|Warning]] }}
| small = {{{small|}}}
| smallimage = {{#if:{{{image|}}}| [[File:{{{image}}}|30px|Warning]]}}
| imageright = {{#if:{{{imageright|}}} |{{{imageright}}} |{{#if:{{{shortcut|{{{shortcut1|}}}}}} |{{Ombox/shortcut|{{{shortcut|{{{shortcut1|}}}}}}|{{{shortcut2|}}}|{{{shortcut3|}}}|{{{shortcut4|}}}|{{{shortcut5|}}}}}}} }}
| textstyle = {{{textstyle|text-align: {{#if:{{{center|}}}|center|{{{align|left}}}}};}}}
| text = {{#if:{{{header|{{{heading|{{{title|}}}}}}}}} |<div style="{{{headstyle|text-align: {{#if:{{{center|}}}|center|left}};}}}">'''{{{header|{{{heading|{{{title|}}}}}}}}}'''</div>}}<!--
-->{{{text|{{{content|{{{reason|{{{1}}}}}}}}}}}}
}}<noinclude>
<!-- Add categories to the /doc subpage; interwikis go to Wikidata. -->
{{Documentation}}
</noinclude>
6vzaqvd2g0rpbfp6wqapmrxa5l2mdjy
Chess Opening Theory/1. e4/1...c6/2. d3/2...d5/3. Nf3/3...dxe4/4. Ng5
0
474666
4675989
4533308
2026-10-14T07:56:46Z
Volvox
2222311
/* Sample game */ Correcting typo -> it's the bishop on d3 guarding f1
4675989
wikitext
text/x-wiki
{{Chess Opening Theory/Position
|Dinic gambit
|parent=[[../|Endgame offer]]
}}
== 4. Ng5!? · Dinic gambit ==
White gambits their d-pawn while targeting Black's weak f7-pawn.
The most critical line is to accept the gambit with [[/4...exd3|'''4...exd3''']] and Black is up material but must be careful not to fall into any traps. After 5. Bxd3, White threatens attacks on h7 and f7. If Black is not careful and plays a natural move like 5...Nf6?? they are soon lost: 6. Nxf7! (forking queen and rook) Kxf7!? 7. Bg6+ hxg6 8. Qxd8 wins Black's queen for two minor pieces.
Alternatively Black may find declining the gambit to be more straight-forward: e.g. '''4...e5''' 5. Nxe4 or '''4...Nf6''' 5. Nxe4 Nxe4 6. dxe4 Qxd1+ 7. Kxd1{{Chess/not|}}.
=== History ===
4. Ng5!? first appeared in a 1936 blindfolded simul, where the pawn was declined with 4...Nf6 (continuing 5. Nc3 Bf5 6. dxe4 Qxd1+ 7. Kxd1 Bg6...).<ref>[https://www.chessgames.com/perl/chessgame?gid=1080650 Koltanowski v Janssens & van Geyt, 1936 - Chessgames.com]</ref>
It was revived in the 1990s and 2000s by Serbian FM [https://ratings.fide.com/profile/908347 Dragan Dinic]<ref>[https://www.chessgames.com/perl/chess.pl?pid=63577&playercomp=white&opening=B10-B19&title=Dragan%20Dinic%20playing%20the%20Caro-Kann%20as%20White Dragan Dinic playing the Caro-Kann as White - Chessgames.com], non-exhaustive list.</ref>, after whom we may gave it the unofficial name, the '''Dinic gambit'''.
== Sample game ==
'''Dragan Dinic vs Branko Komnenic''', Serbian Championship. 26 February 2000.<ref>[https://www.chessgames.com/perl/chessgame?gid=2363209 Dinic vs Komnenic, 2000 - Chessgames.com]</ref>
'''1. e4 c6 2. Nf3 d5 3. d3 dxe4 4. Ng5'''
Dinic preferred to reach the position via 2. Nf3 and 3. d3, rather than 2. d3 (known as the the Breyer variation) and 3. Nf3.
'''4...exd3 5. Bxd3'''
Accepting the free material is most critical. White gets compensation in the form of development.
In this position White's threat is, firstly, to take on h7 and win a pawn. A second threat is created by both queens being on the d-file: White can choose when to move their bishop and allow the queens to see each other. If they can move their bishop with tempo they have a chance to gain material.
'''5...Nf6??'''
This looks to be a natural developing move and adds a defender to h7.
{{clear}}
{{Chess/board|moves=1. e4 c6 2. Nf3 d5 3. d3 dxe4 4. Ng5 exd3 5. Bxd3 Nf6 6. Nxf7|caption=Position after 6. Nxf7|float=right|frame=1}}
'''6. Nxf7!'''
However White can take on f7 and fork Black's queen and rook.
'''6...Qd5'''
If 6...Kxf7!? then White can move their bishop away with check. 7. Bg6+ is a discovered attack on the queen: 7...hxg6 8. Qxd8 and White is up a queen for two minor pieces.
The text move is the most resourceful. It saves Black's queen and counterattacks g2.
'''7. Nxh8 Qxg2 8. Rf1'''
White is up a rook for a pawn.
{{clear}}
{{Chess/board|moves=1. e4 c6 2. Nf3 d5 3. d3 dxe4 4. Ng5 exd3 5. Bxd3 Nf6 6. Nxf7 Qd5 7. Nxh8 Qxg2 8. Rf1 Bh3|caption=Position after 8...Bh3|float=right|frame=1}}
'''8...Bh3'''
Black isn't quite threatening to win the rook while White's bishop is on d3 guarding f1, but this serves to tie down White's bishop.
If 8...Qxh7, White could have extricated their knight with 9. Ng6, because 9...hxg6?? 10. Bg6#!.
If e.g. 8...Nd7, White had the idea of 9. Bxh7 and Black cannot retake because 9...Nxh7? 10. Qh4+ picking up the knight.
'''9. Bf4 Nbd7 10. Nd2'''
Black is prepared to castle queenside, though doing so will allow White's knight back into the game. White's other knight,
developed to d2 rather than c3, guards f1 and so frees up White's bishop and threatens Bxh7.
{{clear}}
{{Chess/board|moves=1. e4 c6 2. Nf3 d5 3. d3 dxe4 4. Ng5 exd3 5. Bxd3 Nf6 6. Nxf7 Qd5 7. Nxh8 Qxg2 8. Rf1 Bh3 9. Bf4 Nbd7 10. Nd2 e5 11. Bg3 e4 12. Bc4 Bb4 13. c3 Nb6|caption=Position after 13...Nb6|float=right|frame=1}}
'''10...e5 11. Bg3 e4 12. Bc4 Bb4 13. c3 Nb6'''
Black threatens to take on c4 as White's knight on d2 is overloaded defending both c4 and f1.
'''14. Qb3 Nxc4 15. Qxc4'''
White brings an extra defender to c4, so that after the trade they keep f1 defended.
'''15...O-O-O 16. Nf7 e3 17. Nxd8 1-0'''
Black resigns.
==Theory table==
{{Chess Opening Theory/Table}}.
:'''1.e4 c6 2.d3 d5 3. Nf3 dxe4 4. Ng5'''
<table border="0" cellspacing="0" cellpadding="4">
<tr>
<th></th>
</tr>
<tr>
<th align="right"></th>
<td>..<br>[[/2...d5|d5]]</td>
</tr>
<tr>
<th align="right"></th>
<td>..<br>[[/2...e5|e5]]</td>
</tr>
<tr>
<th align="right"></th>
<td>..<br>[[/2...g6|g6]]</td>
</tr>
<tr>
<th align="right"></th>
<td>..<br>[[/2...d6|d6]]</td>
</tr>
</table>
{{ChessMid}}
==References==
{{reflist}}
===See also===
{{NCO}}
{{MCO14}}
{{BCO2}}
==External links==
*[https://www.youtube.com/watch?v=xhjSpXORK0E Beat the Caro-Kann in 5 moves], Jonathan Schrantz (Youtube).
{{Chess Opening Theory/Footer}}
r4l2x0xh42jtccvb14ag2g10luc5184
User:Dom walden/Multivariate Analytic Combinatorics/Homology of Critical Points
2
480750
4675863
4675518
2026-10-13T16:10:52Z
Dom walden
3209423
/* Step 3 */
4675863
wikitext
text/x-wiki
== Introduction ==
Morse theory tells us that the topology of M only changes at its critical points.
The "Morse data" tells us the topology at each critical point.
Attaching this Morse data together gives us a space which is homopotically eqivalent to M.
This space is a "cell complex", which has an easy to calculate homology.
Theorem: Our domain of convergence is homotopic to a cell complex of dimension at most <math display="inline">2n - d - 1</math>.<ref>This is theorem D.23 in Pemantle, Wilson and Melczer 2024, pp. 546. Also theorem in section 1.2*/5.2* in SMT pp. 200.</ref>
Proof:
# <math display="inline">X</math> is our entire domain, <math display="inline">\mathcal{V}</math> our variety
# Project our entire domain to complex projective space <math display="inline">Z = \pi(X) \subset \C\mathbb{P}^n - H</math> [define H]
# Define a linear subspace <math display="inline">G \subset \C\mathbb{P}^n</math> of dimension <math display="inline">d - 1</math>
# Define a Morse function on <math display="inline">f: \C\mathbb{P}^n \to \R</math> which approximates the distance from <math display="inline">G</math> and such that <math display="inline">f^{-1}(0) = G</math> and <math display="inline">f^{-1}(1) = H</math>
# We "build" <math display="inline">X - \mathcal{V}</math> from <math display="inline">\pi^{-1}(G \cap Z) \cap (X - \mathcal{V})</math> by attaching CW complexes at critical points which are of at most dimension <math display="inline">2n - d - 1</math>
# At a critical point, the normal Morse data is <math display="inline">(J, K) = \coprod_x (J_x, K_x)</math> and the relative complex link is <math display="inline">\mathcal{L}^\pi = \coprod_x \mathcal{L}_x</math>
# We show that the quotient <math display="inline">J_x/K_x</math> is homotopic to a CW complex of dimension <math display="inline">\leq 2n - d - 1</math>
# The neighbourhood of <math display="inline">x</math> in <math display="inline">J_x</math> is homeomorphic to the cone in <math display="inline">L_x(X - \mathcal{V})</math>, and removing the point <math display="inline">x</math> increases the homotopy dimension to at most the homotopy dimension of <math display="inline">L_x</math>
# <math display="inline">(J_x \cup \{x\}, K_x)</math> is homotopic to <math display="inline">(\text{cone}(\mathcal{L}_x), \mathcal{L}_x)</math>
# <math display="inline">\mathcal{L}_x</math> is homotopic to a CW complex of dimension at most <math display="inline">2n - d - 1</math>
# The tangential Morse data at the critical point is homotopic to the pair <math display="inline">(D^\lambda, \partial D^\lambda)</math>
# Therefore, at each critical point a space has been added homotopic to a CW complex of dimension at most <math display="inline">2n - d - 1</math>.
Theorem: If <math display="inline">X</math> is the complement in <math display="inline">\C^n</math> of a complex variety <math display="inline">\mathcal{V}</math> of dimension <math display="inline">d</math> then <math display="inline">X</math> is homotopic to a CW complex of dimension at most <math display="inline">2n - d - 1</math>.<ref>Pemantle, Wilson and Melczer 2024, pp. 546.</ref>
Proof:
# We build <math display="inline">X</math> by attaching cells of dimension at most <math display="inline">2n - d - 1</math> at each critical point.
## Prove that we can do this without changing the homotopy(?)
## We use Thom's Isotopy Lemma to prove that there is a strong deformation retraction, stopping only at critical points.
# Prove these cells are a product of the normal and tangential Morse data.
## Normal data: <math display="inline">(\mathcal{L}(S), \partial \mathcal{L}(S)) \times (D^1, \partial D^1)</math> [GM pp. 18]
## Tangential data: <math display="inline">(B_\delta \cap f^{-1}[v - \epsilon, v + \epsilon], B_\delta \cap f^{-1}(v - \epsilon))</math> for <math display="inline">f</math> restricted to <math display="inline">X</math> (or <math display="inline">\mathcal{V}</math>?) [GM pp. 63-64]
# If <math display="inline">k</math> is the dimension of the strata, then
## If <math display="inline">k = d</math> then it is a smooth point and the cell is the product of <math display="inline">S^{2(n-d)-1}</math> and the tangential data is dimension at most <math display="inline">d</math>.
## If <math display="inline">k < d</math>, ...
<ref>Pemantle, Wilson and Melczer 2024, pp. 547.</ref>
== Example in one dimension ==
Domain with singularities v_1, v_2, ..., v_i
Define our height function f...
Start with our entire domain X
Reduce from X to X_i+ by using Thom's Isotopy lemma to do a strong deformation retract
== Thom's isotopy lemma ==
We present a modified version of Thom's (first) isotopy lemma, less general than the original but more obviously relevant to our situation.
Theorem: Suppose <math display="inline">Z</math> is a closed subset of a smooth manifold <math display="inline">M</math> which admits a Whitney stratification and <math display="inline">h : M \to \R</math> is a proper Morse function which has no critical values on <math display="inline">Z</math>. Then, the level sets of <math display="inline">Z</math> are homeomorphic by a homeomorphism that preserves the strata of <math display="inline">Z</math>.<ref>For various versions of the full statement of the theorem, see Mather 2012, pp. 499, Goresky and MacPherson 1988, pp. 41, or Pemantle, Wilson and Melczer 2024, pp. 541.</ref>
Proof:
# Construct control data for <math display="inline">Z</math> compatible with <math display="inline">h</math>.
## [Prop 7.1] If <math display="inline">h</math> is smooth on <math display="inline">Z</math> and is a submersion for each strata then there exists a family of control data for <math display="inline">Z</math> compatible with <math display="inline">h</math>.<ref>Mather 2012, pp. 488.</ref>
# This makes <math display="inline">Z</math> an abstract stratified set and <math display="inline">f</math> a controlled submersion.
# A controlled submersion has, for any smooth vector field on <math display="inline">\R</math>, a controlled vector field on <math display="inline">Z</math> (a "lift"?)<ref>Mather 2012, pp. 493.</ref>
# A controlled vector field has a unique one-parameter family of homeomorphisms of <math display="inline">Z</math> which commute with <math display="inline">h</math>.<ref>Mather 2012, pp. 496.</ref>
# This makes <math display="inline">h</math> a locally trivial fibration. [Prop 10.2]<ref>Mather 2012, pp. 499.</ref>
Control data:
A system of '''control data''' for <math display="inline">Z</math> consists of, for each stratum <math display="inline">X</math> of <math display="inline">Z</math>,
* a '''tubular neighbourhood''' <math display="inline">T_X</math> of <math display="inline">X</math>
* a '''tubular projection function''' <math display="inline">\pi_X: T_X \to X</math>, and
* a '''tubular distance function''' <math display="inline">\rho_X: T_X \to \R</math> such that <math display="inline">\rho_X^{-1}(0) = X</math><ref>Goresky and MacPherson 1988, pp. 42.</ref>
[illustration]
such that if <math display="inline">X < Y</math> are strata in <math display="inline">Z</math>, then
<math display="block">\pi_X \pi_Y(m) = \pi_X(m),</math>
<math display="block">\rho_X \pi_Y(m) = \rho_X(m)</math>
for all <math display="inline">m \in |T_X| \cap |T_Y|</math> such that <math display="inline">\pi_Y(m) \in |T_X|</math>.
If, for all strata <math display="inline">X</math> and all <math display="inline">m \in |T_X|</math>, we have <math display="inline">h \pi_X(m) = h(m)</math>, then this control data will be said to be compatible with <math display="inline">h</math>.<ref>Mather 2012, pp. 488.</ref>
We prove that if <math display="inline">h</math> is smooth on <math display="inline">Z</math> and is a submersion for each strata then there exists a family of control data for <math display="inline">Z</math> compatible with <math display="inline">h</math>.<ref>Mather 2012, pp. 488, prop 7.1.</ref>
Let <math display="inline">Z_k</math> be the union of strata of <math display="inline">Z</math> of dimension less than <math display="inline">k</math>. We prove by induction on <math display="inline">k</math>.
To construct the tubular neighbourhood <math display="inline">T_X</math> of a stratum <math display="inline">X</math> of dimension less than <math display="inline">k</math>. For <math display="inline">l \leq k</math>, let <math display="inline">U_l</math> denote the union of all <math display="inline">|T_Y|</math> for <math display="inline">Y < X</math> and <math display="inline">\dim Y \geq l</math>. Let <math display="inline">X_l = U_l \cap X</math>.<ref>Mather 2012, pp. 489.</ref>
For <math display="inline">l = k</math>, <math display="inline">X_k = \empty</math>. Assume by induction that <math display="inline">T_{l+1}</math> has been constructed and that if <math display="inline">Y < X</math>, <math display="inline">\dim Y \geq l + 1</math>, <math display="inline">m \in |T_{l+1}| \cap |T_Y|</math> and <math display="inline">\pi_{l+1}(m) \in |T_Y|</math> (<math display="inline">\pi_{l+1} = \pi_{T_{l+1}}</math>) then<ref>Mather 2012, pp. 489-490.</ref>
<math display="block">\rho_Y \pi_{l+1}(m) = \rho_Y(m),</math>
<math display="block">\pi_Y \pi_{l+1}(m) = \pi_Y(m).</math>
We wish to construct a tubular neighbourhood <math display="inline">T_{X,Y}</math> of <math display="inline">|T_Y| \cap X</math> whose restriction to <math display="inline">|T_Y| \cap X_{l+1}</math> is isomorphic to the restriction of <math display="inline">T_{l+1}</math> such that if <math display="inline">m \in |T_{X,Y}| \cap |T_Y|</math> and <math display="inline">\pi_{X,Y}(m) \in |T_Y|</math> (<math display="inline">\pi_{X,Y} = \pi_{T_{X,Y}}</math>) then
<math display="block">\rho_Y \pi_{X,Y}(m) = \rho_Y(m),</math>
<math display="block">\pi_Y \pi_{X,Y}(m) = \pi_Y(m).</math>
By shrinking <math display="inline">|T_Y|</math> if necessary, this relation is already satisfied if <math display="inline">m \in |T_{l+1}| \cap |T_Y|</math> and <math display="inline">\pi_{l+1}(m) \in |T_Y|</math> with <math display="inline">T_{l+1}</math> in place of <math display="inline">T_{X,Y}</math> and <math display="inline">\pi_{l+1}</math> in place of <math display="inline">\pi_{X,Y}</math>. By the definition, if <math display="inline">m \in |T_{l+1}|</math> then there exists <math display="inline">Z < X</math> with <math display="inline">\dim Z > l</math>, <math display="inline">m \in |T_Z|</math> and <math display="inline">\pi_{l+1}(m) \in |T_Z|</math>. We have that <math display="inline">\pi_{l+1}(m) \in |T_Y| \cap |T_Z|</math> and therefore <math display="inline">Y < Z</math>. Therefore<ref>Mather 2012, pp. 490.</ref>
<math display="block">\rho_Y \pi_{l+1}(m) = \rho_Y \pi_Z \pi_{l+1}(m) = \rho_Y \pi_Z(m) = \rho_Y(m),</math>
<math display="block">\pi_Y \pi_{l+1}(m) = \pi_Y \pi_Z \pi_{l+1}(m) = \pi_Y \pi_Z(m) = \pi_Y(m).</math>
We can prove that, by shrinking <math display="inline">|T_Y|</math>, <math display="inline">(\rho_Y, \pi_Y): |T_Y| \cap X \to \R \times Y</math> is a submersion [prop 7.3?] and that <math display="inline">T_{X,Y}</math> is compatible with <math display="inline">(\rho_Y, \pi_Y): |T_Y| \cap X_{l+1} \to \R \times Y</math>, i.e. <math display="inline">(\rho_Y, \pi_Y) \pi_{X,Y}(m) = (\rho_Y, \pi_Y)(m)</math>(?).
To prove it is a submersion, for the tubular neighbourhood <math display="inline">T = (E, \epsilon, \psi)</math> there exists a smooth positive function <math display="inline">\epsilon'</math> such that
<math display="block">(\rho_T, \pi_T): Y \cap |T|_{\epsilon'}^0 \to \R \times X,</math>
where <math display="inline">|T|_{\epsilon'}^0 = \psi(B_\epsilon \cap B_{\epsilon'})</math>, is a submersion. If <math display="inline">\Sigma</math> is the set <math display="inline">y \in |T|</math> such that the rank of
<math display="block">(\rho_T, \pi_T): T \cap |T| \to \R \times X</math>
at <math display="inline">y</math> is less than <math display="inline">\dim(\R \times X)</math>. We need to prove that for any <math display="inline">x \in X</math> there exists a neighbourhood of <math display="inline">x</math> which does not intersect with <math display="inline">\Sigma</math>, i.e. the map is not a submersion in this neighbourhood. It follows from [lemma 7.2] that it is enough to prove for <math display="inline">M = \R^m</math>, <math display="inline">X = \R^{m-c} \times 0_c</math> and <math display="inline">T</math> is the '''standard tubular neighbourhood'''.<ref>Mather 2012, pp. 489.</ref>
By standard tubular neighbourhood, we mean the trivial bundle with base <math display="inline">\R^{m-c}</math> and fibre <math display="inline">\R^c</math> where <math display="inline">\pi: \R^m \to \R^{m-c}</math>...<ref>Mather 2012, pp. 488.</ref>
For <math display="inline">y \in |T| - \R^{m-c}</math>, the kernal of the differential of <math display="inline">(\pi_T, \rho_T)</math> at <math display="inline">y</math> is the orthogonal complement of <math display="inline">(\R^{m-c} \times 0_c) \oplus \stackrel{\frown}{y \pi_T(y)}</math> in <math display="inline">\R^m</math>. By the Whitney conditions, we have that for <math display="inline">y</math> near <math display="inline">\R^{m-c}</math>, <math display="inline">(\R^{m-c} \times 0_c) \oplus \stackrel{\frown}{y \pi_T(y)}</math> is close to the set of <math display="inline">m - c + 1</math> planes in <math display="inline">m-</math>space to an <math display="inline">m - c + 1</math> plane in <math display="inline">TY_y</math>. Therefore, for <math display="inline">y</math> near enough to <math display="inline">\R^{m-c}</math>, <math display="inline">TY_y</math> is transverse to the kernal of the differential of <math display="inline">(\pi_T, \rho_T)</math> and, therefore, is a submersion when restricted to <math display="inline">Y</math>.<ref>Mather 2012, pp. 489.</ref>
To prove that <math display="inline">T_{X,Y}</math> is compatible with <math display="inline">(\rho_Y, \pi_Y): |T_Y| \cap X_{l+1} \to \R \times Y</math>...<ref>Mather 2012, pp. 490.</ref>
Therefore, there exists a tubular neighbourhood <math display="inline">T_0</math> of <math display="inline">X_0</math> satisfying
<math display="block">\rho_Y \pi_0(m) = \rho_Y(m),</math>
<math display="block">\pi_Y \pi_0(m) = \pi_Y(m).</math>
From this we can prove that <math display="inline">T_0</math> is compatible with <math display="inline">h</math>. Replacing <math display="inline">T_0</math> with a smaller tubular neighbourhood if necessary we can assume <math display="inline">m \in |T_0|</math> such that for some <math display="inline">Y < X</math>, <math display="inline">m \in |T_Y|</math> and <math display="inline">\pi_0(m) \in |T_Y|</math>, then<ref>Mather 2012, pp. 490.</ref>
<math display="block">h \pi_0(m) = h \pi_Y \pi_0(m) = h \pi_Y(m) = h(m).</math>
By the generalised tubular neighourhood theorem [prop 7.2?], we can replace <math display="inline">T_0</math> with a tubular neighbourhood <math display="inline">T</math> of <math display="inline">X</math> compatible with <math display="inline">h</math>. This completes the construction of <math display="inline">T_X</math>.<ref>Mather 2012, pp. 491.</ref>
This makes <math display="inline">Z</math> an '''abstract stratified set''' with axioms...<ref>Mather 2012, pp. 491-492.</ref>
This also makes <math display="inline">h</math> a '''controlled submersion''' because
# <math display="inline">h|X: X \to \R</math> is a smooth submersion on each strata <math display="inline">X</math> of <math display="inline">Z</math>, and
# for each stratum <math display="inline">X</math> there is a tubular neighbourhood <math display="inline">T'_X</math> such that <math display="inline">h(v) = h \pi_X(v)</math> for all <math display="inline">v \in T'_X</math>.<ref>Mather 2012, pp. 493.</ref>
The core of this is the concept of a '''vector field'''. A vector field is a function which assigns, for each point <math display="inline">p</math> in a space, a '''vector''', which can be represented by an arrow whose tail starts at <math display="inline">p</math>.<ref>Henle 1979, pp. 33.</ref>
[picture]
Imagine we have a vector field <math display="inline">v(x)</math> defined in a space and draw a line through our space. At each point along this line the vector field assigns a vector. If we move each point in this line along the arrow defined by this vector in the direction of the arrow head. This "flows" the entire line along the vectors.
[picture]
We define a '''stratified vector field''' <math display="inline">\eta</math> on <math display="inline">Z</math> to be a family of smooth vector fields <math display="inline">\eta_X</math>, one for each strata <math display="inline">X</math> of <math display="inline">Z</math>.<ref>Mather 2012, pp. 493.</ref>
We define a '''controlled vector field''' <math display="inline">\eta</math> on <math display="inline">Z</math> to be a stratified vector field such that for any strata <math display="inline">Y</math> there exists a tubular neighbourhood <math display="inline">T'_Y</math> such that for any <math display="inline">X > Y</math> and any <math display="inline">v \in T'_X \cap X</math><ref>Mather 2012, pp. 493.</ref>
<math display="block">\eta_X \rho_{Y,X}(v) = 0,</math>
<math display="block">(\pi_{Y,X})_* \eta_X(v) = \eta_Y (\pi_{Y,X}(v)).</math>
We prove that if <math display="inline">h</math> is a controlled submersion then, for any smooth vector field <math display="inline">\zeta</math> on <math display="inline">\R</math> there is a controlled vector field <math display="inline">\eta</math> on <math display="inline">Z</math> such that <math display="inline">h_* \eta(v) = \zeta(h(v))</math> for all <math display="inline">v \in Z</math>.<ref>Mather 2012, pp. 493.</ref>
Proceeding by induction on the maximum dimension of the strata of <math display="inline">Z</math>, we define <math display="inline">Z_k</math> to be the union of strata of <math display="inline">Z</math> of dimension at most <math display="inline">k</math>. The tubular neighbourhood of <math display="inline">Z_k</math> is the intersection of the tubular neighbourhoods of each strata in <math display="inline">Z_k</math> with <math display="inline">Z</math>. The projection and distance functions are the restrictions of the respective functions of <math display="inline">Z</math>.
It is trivially true when the maximum dimension of strata in <math display="inline">Z</math> is zero. Assume it is true for <math display="inline">k</math> and construct each <math display="inline">\eta_X</math> separately for each stratum <math display="inline">X</math> of dimension <math display="inline">k + 1</math>.
By the assumption that we have controlled vector fields for all strata <math display="inline">Y</math> of dimension at most <math display="inline">k</math>, we have the two control conditions defined above for any <math display="inline">X > Y</math> and that there is a neighbourhood <math display="inline">T^1_Y</math> such that <math display="inline">h(v) = h \pi_Y(v)</math> for <math display="inline">v \in T^1_Y</math>.
We want to prove that for all <math display="inline">Y < X</math>, the control conditions are satisfied for all <math display="inline">v \in T^2_Y</math> and that <math display="inline">h_*\eta_X(v) = \zeta(v)</math> for all <math display="inline">v \in X</math>.
Take a point <math display="inline">x \in X</math> and define the set <math display="inline">S_v</math> of strata <math display="inline">Y < X</math> such that <math display="inline">v \in T^2_Y</math>. <math display="inline">S_v</math> is totally ordered since if <math display="inline">Y_1</math> and <math display="inline">Y_2</math> are not comparable then <math display="inline">T^2_{Y_1} \cap T^2_{Y_2} = \empty</math>. Therefore, there is a largest member <math display="inline">Y = Y_v</math>.
Assume the control conditions hold for <math display="inline">Y = Y_v</math>. Then they hold for all <math display="inline">Y_i \in S_v</math>. For, either <math display="inline">Y_i = Y</math> or <math display="inline">Y_i < Y</math>. In the latter case, <math display="inline">\pi_Y(v) \in T^1_{Y_i}</math> (by the choice of <math display="inline">T^2_Y</math>'s [is this why?]. Then
<math display="block">\begin{align}
\eta_X(v) \rho_{Y_i,X}(v) &= \eta_X \rho_{Y_i,Y} \pi_{Y,X}(v) \\
&= (\pi_{Y,X})_* \eta_X(v) \rho_{Y_i,Y} \\
&= \eta_Y(\pi_{Y,X}(v)) \rho_{Y_i,Y} \\
&= 0
\end{align}</math>
and
<math display="block">\begin{align}
(\pi_{Y_i,X})_* \eta_X(v) &= (\pi_{Y_i,Y})_* (\pi_{Y,X})_* \eta_X(v) \\
&= (\pi_{Y_i,Y})_* \eta_Y(v) (\pi_{Y,X}) \\
&= \eta_{Y_i}(\pi_{Y_i,Y} \pi_{Y,X}(v)) \\
&= \eta_{Y_i}(\pi_{Y_i,X}(v))
\end{align}</math>
and, therefore, condition holds for all <math display="inline">Y_i \in S_v</math>. Also,
<math display="block">\begin{align}
h_* \eta_X(v) &= (h \circ \pi_{Y,X})_* \eta_X(v) \\
&= h_* \eta_Y (\pi_{Y,X}(v)) \\
&= \zeta(f(v))
\end{align}</math>
and, therefore, the conclusion of the theorem holds at <math display="inline">v</math>.
This shows we can construct <math display="inline">\eta_X</math> satisfying the control conditions when <math display="inline">S_v</math> is non-empty and satisfying the theorem when <math display="inline">S_v</math> is empty. The set of vectors satisfying these conditions is convex in <math display="inline">TX_v</math>, and so we construct <math display="inline">\eta_X</math> globally via a partition of unity.<ref>Mather 2012, pp. 493-495.</ref>
Finally, we prove that a controlled vector field has a unique one-parameter family of homeomorphisms of <math display="inline">Z</math> which commute with <math display="inline">h</math>.<ref>Mather 2012, this combines Proposition 10.1 and Corollary 10.2 on pp. 496 and 497, respectively.</ref>
For each stratum <math display="inline">X</math> of <math display="inline">Z</math>, <math display="inline">\eta_X</math> generates a unique smooth local one-parameter group <math display="inline">(J_X, \alpha_X)</math> of diffeomorphisms of <math display="inline">X</math> (by standard results of differential geometry), such that <math display="inline">\frac{d}{dt} \alpha(t, v)|_{t=0} = \eta_X(v)</math>, <math display="inline">J_X</math> is an open subset of <math display="inline">\R \times Z</math>, ...
If we define <math display="inline">(J, \alpha)</math> by
<math display="block">J = \bigcup_{X \in S} J_X</math>
<math display="block">\alpha = \bigcup_{X \in S} \alpha_X</math>
we can prove that this is a local one-parameter family of homeomorphisms.<ref>Mather 2012, pp. 496.</ref>
Firstly, it is clear that
# <math display="inline">0 \times Z \subseteq J</math> and <math display="inline">\alpha(0, v) = v</math> for all <math display="inline">v \in Z</math>.
# If <math display="inline">v \in Z</math> then <math display="inline">J_v = J \cap (\R \times v) \subseteq \R</math> is an open interval <math display="inline">(a_v, b_v)</math>, possibly infinite at one or both ends.
# If <math display="inline">v \in Z</math> and <math display="inline">t, s, t + s</math> are in <math display="inline">(a_v, b_v)</math> then <math display="inline">\alpha(t + s, v) = \alpha(t, \alpha(s, v))</math>.<ref>Mather 2012, pp. 495.</ref>
Secondly, it is clear that <math display="inline">\eta</math> generates <math display="inline">\alpha</math> because
# Each stratum <math display="inline">X</math> of <math display="inline">Z</math> is invariant under <math display="inline">\alpha</math>, i.e. <math display="inline">\alpha[J \cap (\R \times X)] \subseteq X</math>.
# For each <math display="inline">v \in Z</math>, the map <math display="inline">t \to \alpha(t, v)</math> of <math display="inline">(a_v, b_v)</math> into the stratum which contains <math display="inline">v</math> is <math display="inline">C^1</math>.
# For any <math display="inline">(t, v) \in Z</math>(?) we have <math display="inline">d/dt \alpha(t, v) = \eta(\alpha(t, v))</math>.<ref>Mather 2012, pp. 495.</ref>
It is unique because each <math display="inline">(J_X, \alpha_X)</math> is unique. We just need to prove that <math display="inline">J</math> is open, <math display="inline">\alpha</math> is continuous, and for any <math display="inline">v \in Z</math> and any compact set <math display="inline">K \subseteq Z</math> there exists <math display="inline">\epsilon > 0</math> such that <math display="inline">\alpha(t, v) \notin K</math> if <math display="inline">t \in (a_v, a_v + \epsilon) \cup (b_v - \epsilon, b_v)</math>.<ref>Mather 2012, pp. 495.</ref>
For the latter-most condition, if it did not hold then there exists...<ref>Mather 2012, pp. 496-497.</ref>
We prove there is a homeomorphism <math display="inline">f: Z \to h^{-1}(0) \times \R</math> such that <math display="inline">\pi \circ f = h</math>, where <math display="inline">\pi: h^{-1}(0) \times \R \to \R</math> is projection to the second factor.
For the coordinate vector field <math display="inline">\partial</math> on <math display="inline">\R</math>, by [prop 9.1] there is a controlled vector field <math display="inline">\tilde\partial</math> such that <math display="inline">f_* \tilde\partial(v) = \partial(h(v))</math> for <math display="inline">v \in Z</math>. By [prop 10.1], <math display="inline">\tilde\partial</math> generates a local one-parameter group <math display="inline">(J, \alpha)</math> such that
<math display="block">h(\alpha(t,v)) = h(v) + t</math>
<math display="inline">h</math> is proper and [d] holds, so <math display="inline">J = \R \times Z</math>. If we define <math display="inline">f</math> as
<math display="block">f(v) = (\alpha(-t, v), h(v))</math>
then <math display="inline">f</math> maps <math display="inline">Z</math> into <math display="inline">h^{-1}(0) \times \R</math> and <math display="inline">\pi \circ f = h</math>. If we define <math display="inline">\bar f: h^{-1}(0) \times \R \to Z</math> as
<math display="block">\bar f(v, t) = \alpha(t, v)</math>
then <math display="inline">f \bar f = \bar f f = Id</math> and <math display="inline">f</math> is a homeomorphism.<ref>Mather 2012, pp. 497.</ref>
== Topology at critical points ==
Theorem: If there is a critical point <math display="inline">p</math> in the singular variety <math display="inline">\mathcal{V}</math> with critical value <math display="inline">v \in (a, b)</math> then the space <math display="inline">X_{\leq b}</math> is homotopic to<ref>Goresky and MacPherson 1988, pp. 174.</ref>
<math display="block">X_{\leq a} \cup [(D^{\lambda+1}, \partial D^{\lambda+1}) \times (\mathcal{L}_X, \partial \mathcal{L}_X)].</math>
Proof:<ref>Proof outline comes from Goresky and MacPherson 1988, pp. 174.</ref>
# <math display="inline">(X_{\leq b}, X_{\leq a})</math> is homeomorphic to <math display="inline">(X_{\leq v + \epsilon}, X_{\leq v -\epsilon})</math>. We can prove this by "moving wall" or Thom's Isotopy Lemma.<ref>Goresky and MacPherson 1988, pp. 90-91, 120.</ref>
# <math display="inline">X_{\leq v + \epsilon}</math> is homeomorphic to <math display="inline">X_{\leq v - \epsilon} \cup (J, K)</math>, where the latter is the local Morse data for <math display="inline">h</math> at <math display="inline">p</math>. We do this by moving the wall...<ref>Goresky and MacPherson 1988, pp. 95-96, 120-121.</ref>
# <math display="inline">(J, K)</math> is homeomorphic to <math display="inline">(D^{\lambda+1}, \partial D^{\lambda+1}) \times (\mathcal{L}_X, \partial \mathcal{L}_X)</math> (tangential data, normal data). Again, moving the wall...<ref>Goresky and MacPherson 1988, pp. 65-66, chapter 8, 121.</ref>
# The normal Morse data depends only on the differential <math display="inline">df(p)</math>.<ref>Goresky and MacPherson 1988, pp. 93.</ref>
# The normal Morse data has the homotopy type of <math display="inline">(\mathcal{L}_X, \partial \mathcal{L}_X)</math>.<ref>Goresky and MacPherson 1988, pp. 169.</ref>
=== Step 1 ===
We get this immediately(?) by Thom's Isotopy Lemma.
=== Step 2 ===
<ref>Goresky and MacPherson 1988, complex case on pp. 120-121 is extension of real case on pp. 95-96.</ref>
Step 1 works because <math display="inline">h</math> is a submersion at each point of the regions we are homeomorphing. This is not the case at critical points. We need some way by which a homeomorphism can pass through a critical point.
To prove a homeomorphism between two subsets <math display="inline">A</math> and <math display="inline">B</math> of <math display="inline">Z</math>, we project <math display="inline">Z</math> to some other space <math display="inline">N</math> (in our case <math display="inline">\R^n</math>) using some function <math display="inline">F</math>. We take subsets <math display="inline">Y_0</math> and <math display="inline">Y_1</math> of <math display="inline">N</math> such that <math display="inline">A = Z \cap F^{-1}(Y_0)</math> and <math display="inline">B = Z \cap F^{-1}(Y_1)</math>. We need to prove <math display="inline">Y_0</math> and <math display="inline">Y_1</math> are connected by a one-parameter family of regions <math display="inline">Y_t</math> [explain one-parameter family]. The criterion for such a family to exist is that the '''characteristic covectors''' of <math display="inline">F</math> are all nonzero on each stratum of <math display="inline">Y_t</math>.<ref>Goresky and MacPherson 1988, pp. 70.</ref>
At each point <math display="inline">x \in M</math> and <math display="inline">y \in N</math> there are '''tangent spaces''' <math display="inline">T_xM</math> and <math display="inline">T_yN</math>, a vector space whose zero is at the point <math display="inline">x</math> or <math display="inline">y</math> (resp.)
[picture of various tangent spaces]
In the case the <math display="inline">N = \R</math>, the tangent space <math display="inline">T_x\R</math> is just <math display="inline">\R</math> but whose origin is at <math display="inline">x</math>.
[picture of T_x\R]
Say <math display="inline">F(x) = y</math>, then the differential of the map <math display="inline">F</math> can be seen as a function whose input is a vector in the tangent space <math display="inline">T_xM</math> and whose output is a vector in the tangent space <math display="inline">T_yM</math>. [If I move this far on the tangent space of M how do I move in the tangent space of N?]
[picture]
[example for M = \R and N = \R?]
A function which takes as input a vector in the tangent space <math display="inline">T_xM</math> (say) and outputs a scalar (usually <math display="inline">\R</math>) is called a '''covector'''. The set of all covectors on <math display="inline">T_xM</math> is called the dual space of <math display="inline">T_xM</math> and is denoted <math display="inline">T^*_xM</math>. There are only a limited number of ways to express a covectors. For example, if our tangent space is two-dimensional then all covectors are of the form <math display="inline">ax + by</math> where <math display="inline">(x, y) \in T_xM</math>.
We take our space <math display="inline">M</math> and map it onto <math display="inline">\R^2</math> with the map <math display="inline">F(z) = (r(z), h(z))</math>, where <math display="inline">z \in M</math> and <math display="inline">r</math> is the square of the distance of <math display="inline">z</math> to the critical point <math display="inline">p</math>.
[graph of mapping]
In this case, the covectors on the tangent space <math display="inline">T_xM</math> are of the form <math display="inline">adf(x) + bdr(x)</math> (in this case <math display="inline">df</math> and <math display="inline">dr</math> are maps to <math display="inline">\R</math>) and on <math display="inline">T_y\R^2</math> are of the form <math display="inline">cu + dv</math> (for <math display="inline">(u, v) \in \R^2</math>). A covector <math display="inline">cu + dv \in T^*_{(u, v)}\R^2</math> is called a '''characteristic covector''' of <math display="inline">F</math> if <math display="inline">F(x) = (u, v)</math> and <math display="inline">cdf(x) + ddr(x) = 0</math> for all vectors in the tangent space of the stratum containing <math display="inline">p</math>.<ref>Goresky and MacPherson 1988, pp. 82.</ref> [explain adf(x) + bdr(x) in terms of this being a function which takes a vector input]
[example of where covectors do and do not vanish on a stratified space, pp. 71?]
What we want is a homeomorphism in <math display="inline">M</math> between the space <math display="inline">Z_{\leq \epsilon}</math> and <math display="inline">Z_{\leq \epsilon} \cup B</math>, where <math display="inline">B</math> is a small region of the critical point <math display="inline">p</math>. The '''local Morse data''' is
<math display="block">((B_\delta \cap Z) \cap f^{-1}[v-\epsilon, v+\epsilon], (B_\delta \cap Z) \cap f^{-1}(v-\epsilon))</math>
where <math display="inline">B_\delta</math> is a closed disc in <math display="inline">M</math> of radius <math display="inline">\delta</math>.<ref>Goresky and MacPherson 1988, pp. 63-64.</ref> Observe that this is the pair <math display="inline">(F^{-1}(\text{Box}(\delta, \epsilon)), F^{-1}(\text{Bottom}(\delta, \epsilon)))</math><ref>Goresky and MacPherson 1988, pp. 91.</ref> [explain Box, Bottom, etc.]
[picture of the two subspaces of Z in M]
We use our map <math display="inline">F</math> to convert these two subspaces to subspaces of <math display="inline">\R^2</math> which are of the form <math display="inline">Y_1 = \{(x,y) \in \R^2 | y \leq \epsilon\}</math> and <math display="inline">Y_0 = \{(x,y) \in \R^2 | y \leq -\epsilon\} \cup \{(x,y) \in \R^2 | x \leq \delta, y \leq \epsilon\}</math>, such that <math display="inline">Z_{\leq \epsilon} = F^{-1}(Y_1)</math> and <math display="inline">Z_{\leq \epsilon} \cup B = F^{-1}(Y_0)</math>.<ref>Goresky and MacPherson 1988, pp. 95-96.</ref>
We use a homeomorphism between <math display="inline">Y_1</math> and <math display="inline">Y_0</math> using the technique of "moving the wall" and Thom's Isotopy Lemma. Such a homeomorphism exists when the characteristic covectors of <math display="inline">F</math> are all nonzero on each stratum of <math display="inline">Y_t</math>.<ref>Goresky and MacPherson 1988, chapter 4, particularly pp. 71-72.</ref>
Given a smooth mapping between manifolds <math display="inline">F: M \to N</math> (for example, in our case we could have <math display="inline">N = \R^2</math>) and that <math display="inline">F|Z: Z \to N</math> is proper. Let <math display="inline">Y \subset N \times \R</math> be a closed Whitney stratified subset such that the projection to the second factor <math display="inline">\pi: Y \to \R</math> is a proper stratified submersion.<ref>Goresky and MacPherson 1988, pp. 71.</ref>
Suppose for each <math display="inline">t \in \R</math>, for each <math display="inline">p \in F(Z) \cap Y_t</math>, and for each nonzero characteristic covector <math display="inline">\lambda \in T^*_pN</math> of <math display="inline">F|Z</math>, the restriction of <math display="inline">\lambda</math> to the subspace <math display="inline">T_pS_t = \ker(d\pi(p)) \cap T_pS</math> is nonzero, where <math display="inline">S</math> is a stratum of <math display="inline">Y</math> which contains <math display="inline">(p, t)</math> and <math display="inline">S_t = \pi^{-1}(t) \cap S</math> is the stratum of <math display="inline">Y_t = \pi^{-1}(t) \cap Y</math> which contains <math display="inline">p</math>. This is equivalent to the statement that, for each <math display="inline">t \in \R</math>, the restriction <math display="inline">F|Z</math> is transverse to <math display="inline">Y_t</math>.<ref>Goresky and MacPherson 1988, pp. 71-72.</ref>
This means that, for each <math display="inline">t \in \R</math>, <math display="inline">Z \cap F^{-1}(Y_t)</math> is stratified by its intersection with the strata of <math display="inline">Z</math>...
We finally prove there is a homeomorphism between <math display="inline">Z \cap F^{-1}(Y_0) \cong Z \cap F^{-1}(Y_1)</math> which preserves the Whitney stratification of both sides and is smooth on each stratum.
For the composition
<math display="block">Z \times \R \subset M \times \R \to_{F \times I} Y \subset \R^2 \times \R \to_{\pi} \R</math>
where <math display="inline">Y(t, z) = Y_t(z)</math>, <math display="inline">I</math> is the identity and <math display="inline">\pi</math> is projection to the second factor.
<math display="inline">Z \times \R</math> is transverse to <math display="inline">(F \times I)^{-1}(Y)</math>...
The composition <math display="inline">\pi \circ (F \times I): Z \times \R \cap (F \times I)^{-1}(Y) \to \R</math> is a stratified submersion because
* The input domain is stratified as above...,
* We have defined <math display="inline">F|Z</math> to be transverse to <math display="inline">Y</math>, and therefore it preserves the stratification (unless <math display="inline">F(Z) \cap Y = \empty</math>), and
* We defined above the projection on <math display="inline">Y</math> to be a stratified submersion, meaning it is a submersion on each stratum of <math display="inline">F(Z) \cap Y</math>.<ref>Goresky and MacPherson 1988, pp. 43.</ref>
Therefore, we can apply Thom's Isotopy Lemma which says there is a homeomorphism between the level sets of <math display="inline">Z \times \R</math>...<ref>Goresky and MacPherson 1988, pp. 72.</ref>
=== Step 3 ===
We prove there is a stratum preserving homeomorphism between<ref>Goresky and MacPherson 1988, pp. 65.</ref>
<math display="block">\text{Local Morse Data} \cong (\text{Tangential Morse Data}) \times (\text{Normal Morse Data})</math>
We first prove that there is a homeomorphism between the product of the normal and tangential Morse data and the '''realisation''' of the following diagram
[diagram from pp. 102]
where realisation means
<math display="block">Z \cap (g_1, h_1)^{-1}(P_a) \cap (g_2, h_2)^{-1}(P_b)</math>
where all the intersections of strata (of <math display="inline">Z</math>?) are transverse.<ref>Goresky and MacPherson 1988, pp. 100-102.</ref>
The realisation of the above diagram is equal to
<math display="block">(V_1, V_2) \cap (W_1, W_2) = (V_1 \cap W_1, V_1 \cap W_2 \cup V_2 \cap W_1)</math>
where
<math display="block">V_1 = \{ z \in Z : |f(z) - f\pi(z)| \leq \epsilon/4, r\pi(z) \leq \delta, \rho(z) \leq \delta \}</math>
<math display="block">V_2 = \{ z \in Z : f(z) - f\pi(z) = -\epsilon/4, r\pi(z) \leq \delta, \rho(z) \leq \delta \}</math>
<math display="block">W_1 = \{ z \in Z : |f\pi(z)| \leq 3\epsilon/4, r\pi(z) \leq \delta \}</math>
<math display="block">W_1 = \{ z \in Z : f\pi(z) = -3\epsilon/4, r\pi(z) \leq \delta \}</math>
where <math display="inline">\pi</math> is the projection from the tubular neighbourhood to <math display="inline">Z</math>, <math display="inline">r(z)</math> is the square of the distance between <math display="inline">z</math> and the critical point <math display="inline">p</math> and <math display="inline">\rho(z)</math> is the square of the distance between <math display="inline">z</math> and <math display="inline">\pi(z)</math>.<ref>Goresky and MacPherson 1988, pp. 100-101.</ref> <math display="inline">\epsilon \ll \delta</math> are chosen so that <math display="inline">(\delta, \epsilon)</math> is in the set <math display="inline">A^\flat_6</math> which consists of <math display="inline">A_6 \subset \R^+ \times \R^+</math> with the properties that for <math display="inline">(\epsilon, \delta) \in A_6</math> and <math display="inline">z</math> such that <math display="inline">\rho(z) = \delta</math>, <math display="inline">r\pi(z) = \delta</math>, <math display="inline">|f(z)| \leq \epsilon</math> and <math display="inline">|f\pi(z)| \leq \epsilon</math> then the covectors <math display="inline">d\rho(z)</math>, <math display="inline">dr\pi(z)</math>, <math display="inline">df(z)</math> and <math display="inline">df\pi(z)</math> are linearly independent when restricted to <math display="inline">T_zY</math> (where <math display="inline">Y</math> is the stratum containing <math display="inline">z</math>). We can prove such a set exists.<ref>Goresky and MacPherson 1988, pp. 89.</ref> <math display="inline">A^\flat_6</math> is this plus its reflection about the <math display="inline">x</math> axis.<ref>Goresky and MacPherson 1988, pp. 82.</ref>
Let <math display="inline">D = \{ x \in X | r(x) \leq \delta \}</math> for stratum <math display="inline">X</math>. We will show there is a local trivial fibration of the configuration: <math display="inline">(V_1, V_2)</math> fibres over <math display="inline">D</math> and is homeomorphic to <math display="inline">D \times (\text{normal Morse data})</math>
(V_1, V_2) -> D \times (normal Morse data)
| /
--> D <---
and that <math display="inline">(W_1, W_2)</math> fibres over the tangential Morse data and is homeomorphic to <math display="inline">(\text{tangential Morse data}) \times (\text{normal slice})</math>.
For <math display="inline">Z_1 = \{ z \in Z : r\pi(z) \leq \delta \}</math>, the map <math display="inline">F(z): Z_1 \to \R^2 = (\rho(z), f(z) - f\pi(z))</math> is transverse to each stratum of <math display="inline">\text{Box}(\delta, \epsilon/4)</math>, [list], [by lemma 6.5]. <math display="inline">(V_1, V_2) = F^{-1}(\text{Box}(\delta, \epsilon/4), \text{Bottom}(\delta, \epsilon/4))</math>. For each stratum <math display="inline">S</math> of Box and each <math display="inline">x \in D</math>, we have transverse intersection <math display="inline">F^{-1}(S) \pitchfork \pi^{-1}(x)</math>. Therefore, <math display="inline">\pi|F^{-1}(S)</math> is a submersion and by Thom's isotopy lemma the projection <math display="inline">\pi|F^{-1}(\text{Box}(\delta, \epsilon/4): F^{-1}(\text{Box}(\delta, \epsilon/4)) \to X</math> is a stratified fibre bundle over <math display="inline">D</math>. The fibre over the critical point <math display="inline">p</math> is <math display="inline">\pi^{-1}(p) \cap (F^{-1}(\text{Box}(\delta, \epsilon/4), F^{-1}(\text{Bottom}(\delta, \epsilon/4))</math> and is equal to the normal Morse data...<ref>Goresky and MacPherson 1988, pp. 101.</ref>
Take <math display="inline">G: X \to \R^2 = (r(x), f(x))</math>. <math display="inline">\delta</math> and <math display="inline">\epsilon</math> have been chosen so that <math display="inline">(G^{-1}(\text{Box}(\delta, \epsilon/4), G^{-1}(\text{Bottom}(\delta, \epsilon/4))</math> is the tangential Morse data for <math display="inline">f</math> and is contained in the region <math display="inline">D</math> over which <math display="inline">\pi|(V_1, V_2)</math> is a stratified fibre bundle. Therefore, <math display="inline">(W_1, W_2) = \pi^{-1} G^{-1}(\text{Box}(\delta, \epsilon/4), \text{Bottom}(\delta, \epsilon/4))</math> is transverse to <math display="inline">(V_1, V_2)</math>.<ref>Goresky and MacPherson 1988, pp. 101-102.</ref>
Finally, this means that <math display="inline">(V_1, V_2) \cap (W_1, W_2)</math> is homeomorphic (by stratum preserving homeomorphism) to <math display="inline">(\pi^{-1}(p), \cap (V_1, V_2)) \times \pi(W_1, W_2)</math>, the product of normal and tangential Morse data.<ref>Goresky and MacPherson 1988, pp. 102.</ref>
We use a succession of such diagrams to interpolate between the box diagram which defines local Morse data [explain] and the above diagram whose realisation we have just proven is <math display="inline">(\text{normal Morse data}) \times (\text{tangential Morse data})</math>.
[diagram_d0.py]
The realisation is the local Morse data. This is equal to the realisation of the diagram below.<ref>Goresky and MacPherson 1988, pp. 103, 106.</ref>
[diagram_d11.py]
The realisation of the first diagram [d0] is equivalent to the realisation of the below diagram.
[diagram_d1.py]
In the right-hand picture of the above diagram, we have put a dotted outline around the region <math display="inline">A^{\flat}_1</math>. We prove that there are no characteristic covectors for <math display="inline">(r, f): Z \to \R^2</math> in this region and can, therefore, move the wall in this region...<ref>Goresky and MacPherson 1988, pp. 82-83.</ref>
By adding a zero-dimensional stratum at the top right corner of the right-hand picture. A one-parameter family of pictures <math display="inline">P_b(t)</math> gives rise to a stratified space <math display="inline">Y \subset M \times \R</math> such that
<math display="block">Y = \{ (z, t) \in M \times \R : (r, f)(z) \in P_b(t) \}.</math>
<math display="inline">(r, f)</math> takes each stratum of <math display="inline">Z</math> transversally to each stratum of each <math display="inline">Y_t</math>. <math display="inline">(f \circ \pi, f)^{-1}(P_a) = f^{-1}[-\epsilon, \infty)</math> is transverse to each stratum of <math display="inline">Y_t \cap Z</math>. Therefore, there is a homeomorphism between<ref>Goresky and MacPherson 1988, pp. 107.</ref>
<math display="block">Z(D_1) = Z \cap (f \circ \pi, f)^{-1}(P_a) \cap (r, f)^{-1}(P_b(0))</math>
and
<math display="block">Z(D_1) = Z \cap (f \circ \pi, f)^{-1}(P_a) \cap (r, f)^{-1}(P_b(1)).</math>
To go from D_2 to D_3 we find the characteristic covectors of <math display="inline">(f\pi, f): V \to \R^2</math> where <math display="inline">V = (r, f)^{-1}(P_b(1))</math>. We stratify <math display="inline">P_b(1)</math> by its interior <math display="inline">P</math> and boundary <math display="inline">\partial P</math>.<ref>Goresky and MacPherson 1988, pp. 107.</ref>
The strata of <math display="inline">V</math> come in four types:
# <math display="inline">(r, f)^{-1}(P) \cap X</math>
# <math display="inline">(r, f)^{-1}(P) \cap Y</math>
# <math display="inline">(r, f)^{-1}(\partial P) \cap X</math>
# <math display="inline">(r, f)^{-1}(\partial P) \cap Y</math>
where <math display="inline">X</math> is the strata that contains the critical point and <math display="inline">Y</math> is any other strata such that <math display="inline">Y > X</math>.
All characteristic covectors are of the form <math display="inline">\lambda = (u, v, adu + bdv) \in T^*\R^2</math>.
For strata 1 and 3, the image of <math display="inline">X</math> under <math display="inline">(f\pi, f)</math> is the diagonal <math display="inline">f\pi = f</math> (dotted outline). Therefore, the characteristic covectors of any point <math display="inline">z</math> in <math display="inline">X</math> are either where <math display="inline">z = p</math>, in which case the covector is zero(?), or where <math display="inline">z \neq p</math>, in which case <math display="inline">u = v</math> and <math display="inline">a = b</math>.<ref>Goresky and MacPherson 1988, pp. 107-108.</ref>
== Morse theory ==
Steps(?)
* Explain topology
* Every point of a stratum is locally like a product structure (proved by Thom's Isotopy Lemma) [GM pp. 41-42]
** Including those around critical points, which are the product of normal and tangential Morse data (these are our quasi-local cycles?)
* Thom's Isotopy Lemma proves a strong deformation retraction (which only stops at critical points) [PWM pp. 541-542]
=== Homotopy ===
We want to replace our domain of convergence <math display="inline">M</math>, which is the complement of our singular variety <math display="inline">\mathcal{V}</math>, with an "equivalent" space <math display="inline">M'</math> which has better understood properties. We say "equivalent" because there are several different things we could mean by "equivalent" in this context. The equivalence we are referring to in this section is called '''homotopy'''.
Imagine two subspaces <math display="inline">\gamma_0</math> and <math display="inline">\gamma_1</math> of a space <math display="inline">Y</math> which are defined respectively by smooth functions <math display="inline">f, g: X \to Y</math>. If there exists a smooth function <math display="inline">h_s: X \times [0, 1] \to Y</math>, called a homotopy, such that <math display="inline">h_0 = f</math>, <math display="inline">h_1 = g</math> and for any <math display="inline">\epsilon > 0</math> there exists a <math display="inline">\delta_a</math> and <math display="inline">\delta_b</math> such that when <math display="inline">|s - s_0| < \delta_a</math> and <math display="inline">|x - x_0| < \delta_b</math> we have <math display="inline">|h_s(x) - h_{s_0}(x_0)| < \epsilon</math>, then we say <math display="inline">\gamma_0</math> and <math display="inline">\gamma_1</math> are '''homotopic'''.<ref>Henle 1979, pp. 251-252.</ref>
Below is an example where <math display="inline">\gamma_0</math> and <math display="inline">\gamma_1</math> are one-dimensional curves and <math display="inline">H(t, s) = h_s(t)</math>.
[[File:Homotopy_curves.png|300px]]
In [[#Homotopy_equivalence|Appendix A]], we formally prove that we can construct an equivalent space <math display="inline">M'</math>. We provide only an example to give some intuition before describing how to construct the space <math display="inline">M'</math> in terms of local cycles around critical points.
=== Motivating example ===
Imagine a torus and a height function which is just the z value of the point.
[[File:3D-Leveltorus.png|200px]]
It has four critical points: two at the top and bottom of the outer circle (<math display="inline">p_1, p_4</math>) and two at the top and bottom of the inner circle (<math display="inline">p_2, p_3</math>).
[picture]
When the height is between the <math display="inline">p_1</math> and <math display="inline">p_2</math>, the space is a two-cell, which can be retracted to a point.
[picture]
When the height is between <math display="inline">p_2</math> and <math display="inline">p_3</math>, the space is a cylinder, which can be retracted to a two-cell with a one-cell attached.
[[File:3D-Cylinder_and_disk_with_handle.png|200px]]
When the height is between <math display="inline">p_3</math> and <math display="inline">p_4</math>, the space is a torus with a disc removed, which can be retracted to a cylinder with a one-cell attached.
[[File:3D-Cylinder_with_handle_and_torus_with_hole.png|200px]]
When the height is greater than <math display="inline">p_4</math>, then the full torus is constructed by attaching a two-cell.
[Explain in terms of Morse data and Morse index?]
=== Morse data and quasi-local cycles ===
As in the above example, we start at the "bottom" of <math display="inline">M</math> and build upwards until just before we reach our first critical point <math display="inline">p</math>.
;Smooth points
:This is a tube around a <math display="inline">(d-1)</math>-chain <math display="inline">\gamma</math> where the height function <math display="inline">h</math> is maximised at <math display="inline">p</math>.<ref>Pemantle, Wilson and Melczer 2024, pp. 223.</ref>
:For example, if <math display="inline">F(x, y) = \frac{1}{1 - x - y}</math> then <math display="inline">\lambda = 1</math> and <math display="inline">B^\lambda</math> is an arc reaching its highest point at <math display="inline">p</math>.
:The normal plane <math display="inline">N</math> at <math display="inline">p</math> is a plane orthogonal to <math display="inline">B^1</math>(?).
:Its normal link <math display="inline">L(S)</math> is a circle with two points missing where it intersects <math display="inline">\mathcal{V}</math>.
:We make our quasi-local cycle out of the product of the arc and circle joined to <math display="inline">M_-</math> at points below <math display="inline">M_-</math>.
:With the exception of degenerate points, such as monkey saddles...<ref>e.g. Pemantle, Wilson and Melczer 2024, pp. 211.</ref>
;Transverse multiple points
:This is the product of a <math display="inline">k</math>-torus and a <math display="inline">(d-k)</math>-chain <math display="inline">\gamma</math>. The torus is the product of circles about <math display="inline">p</math> in the complex normal space to each strata which intersects <math display="inline">p</math>. The chain <math display="inline">\gamma</math> is supported in the stratum which is the common intersection of the varieties defined by the factors vanishing at <math display="inline">p</math>, and achieves its maximum height at <math display="inline">p</math>.<ref>Pemantle, Wilson and Melczer 2024, pp. 223-224.</ref>
;Arrangement multiple point
:This is the product of a <math display="inline">(d-k)</math>-chain <math display="inline">\gamma</math> and several <math display="inline">k</math>-tori, one for each pair of sheets which intersect transversely, where the torus is the product of circles about <math display="inline">p</math> in each sheet.<ref>Pemantle, Wilson and Melczer 2024, pp. 226.</ref>
;Cone point
:A cone point is zero-dimensional so there is no <math display="inline">\gamma</math>, just a <math display="inline">d</math>-torus about <math display="inline">p</math>.<ref>Pemantle, Wilson and Melczer 2024, pp. 227.</ref>
== Notes ==
{{Reflist}}
== References ==
* {{cite book | last1=Goresky | first1=Mark | last2=MacPherson | first2=Robert | title=Stratified Morse Theory | publisher=Springer-Verlag | year=1988 | url=https://www.math.ias.edu/~goresky/pdf/SMT.djvu }}
* {{cite book | last=Henle | first1=Michael | title=A Combinatorial Introduction to Topology | publisher=Dover Publications Inc. New York | year=1979 }}
* {{citation | last=Mather | first=John | title=Notes on Topological Stability | year=2012 | journal=Bulletin of the American Mathematical Society | volume=49 | number=4 | pages=475-506 | url=https://www.ams.org/journals/bull/2012-49-04/S0273-0979-2012-01383-6/S0273-0979-2012-01383-6.pdf }}.
* {{cite book | last1=Pemantle | first1=Robin | last2=Wilson | first2=Mark C. | last3=Melczer | first3=Stephen | title=Analytic Combinatorics in Several Variables | publisher=Cambridge University Press | year=2024 | edition=2nd | url=https://acsvproject.com/PemantleWilsonMelczer23.pdf }}
4v8hr4lrmgo1w1pz11vzyczrab2q40h
4675908
4675863
2026-10-13T19:05:11Z
Dom walden
3209423
/* Step 3 */
4675908
wikitext
text/x-wiki
== Introduction ==
Morse theory tells us that the topology of M only changes at its critical points.
The "Morse data" tells us the topology at each critical point.
Attaching this Morse data together gives us a space which is homopotically eqivalent to M.
This space is a "cell complex", which has an easy to calculate homology.
Theorem: Our domain of convergence is homotopic to a cell complex of dimension at most <math display="inline">2n - d - 1</math>.<ref>This is theorem D.23 in Pemantle, Wilson and Melczer 2024, pp. 546. Also theorem in section 1.2*/5.2* in SMT pp. 200.</ref>
Proof:
# <math display="inline">X</math> is our entire domain, <math display="inline">\mathcal{V}</math> our variety
# Project our entire domain to complex projective space <math display="inline">Z = \pi(X) \subset \C\mathbb{P}^n - H</math> [define H]
# Define a linear subspace <math display="inline">G \subset \C\mathbb{P}^n</math> of dimension <math display="inline">d - 1</math>
# Define a Morse function on <math display="inline">f: \C\mathbb{P}^n \to \R</math> which approximates the distance from <math display="inline">G</math> and such that <math display="inline">f^{-1}(0) = G</math> and <math display="inline">f^{-1}(1) = H</math>
# We "build" <math display="inline">X - \mathcal{V}</math> from <math display="inline">\pi^{-1}(G \cap Z) \cap (X - \mathcal{V})</math> by attaching CW complexes at critical points which are of at most dimension <math display="inline">2n - d - 1</math>
# At a critical point, the normal Morse data is <math display="inline">(J, K) = \coprod_x (J_x, K_x)</math> and the relative complex link is <math display="inline">\mathcal{L}^\pi = \coprod_x \mathcal{L}_x</math>
# We show that the quotient <math display="inline">J_x/K_x</math> is homotopic to a CW complex of dimension <math display="inline">\leq 2n - d - 1</math>
# The neighbourhood of <math display="inline">x</math> in <math display="inline">J_x</math> is homeomorphic to the cone in <math display="inline">L_x(X - \mathcal{V})</math>, and removing the point <math display="inline">x</math> increases the homotopy dimension to at most the homotopy dimension of <math display="inline">L_x</math>
# <math display="inline">(J_x \cup \{x\}, K_x)</math> is homotopic to <math display="inline">(\text{cone}(\mathcal{L}_x), \mathcal{L}_x)</math>
# <math display="inline">\mathcal{L}_x</math> is homotopic to a CW complex of dimension at most <math display="inline">2n - d - 1</math>
# The tangential Morse data at the critical point is homotopic to the pair <math display="inline">(D^\lambda, \partial D^\lambda)</math>
# Therefore, at each critical point a space has been added homotopic to a CW complex of dimension at most <math display="inline">2n - d - 1</math>.
Theorem: If <math display="inline">X</math> is the complement in <math display="inline">\C^n</math> of a complex variety <math display="inline">\mathcal{V}</math> of dimension <math display="inline">d</math> then <math display="inline">X</math> is homotopic to a CW complex of dimension at most <math display="inline">2n - d - 1</math>.<ref>Pemantle, Wilson and Melczer 2024, pp. 546.</ref>
Proof:
# We build <math display="inline">X</math> by attaching cells of dimension at most <math display="inline">2n - d - 1</math> at each critical point.
## Prove that we can do this without changing the homotopy(?)
## We use Thom's Isotopy Lemma to prove that there is a strong deformation retraction, stopping only at critical points.
# Prove these cells are a product of the normal and tangential Morse data.
## Normal data: <math display="inline">(\mathcal{L}(S), \partial \mathcal{L}(S)) \times (D^1, \partial D^1)</math> [GM pp. 18]
## Tangential data: <math display="inline">(B_\delta \cap f^{-1}[v - \epsilon, v + \epsilon], B_\delta \cap f^{-1}(v - \epsilon))</math> for <math display="inline">f</math> restricted to <math display="inline">X</math> (or <math display="inline">\mathcal{V}</math>?) [GM pp. 63-64]
# If <math display="inline">k</math> is the dimension of the strata, then
## If <math display="inline">k = d</math> then it is a smooth point and the cell is the product of <math display="inline">S^{2(n-d)-1}</math> and the tangential data is dimension at most <math display="inline">d</math>.
## If <math display="inline">k < d</math>, ...
<ref>Pemantle, Wilson and Melczer 2024, pp. 547.</ref>
== Example in one dimension ==
Domain with singularities v_1, v_2, ..., v_i
Define our height function f...
Start with our entire domain X
Reduce from X to X_i+ by using Thom's Isotopy lemma to do a strong deformation retract
== Thom's isotopy lemma ==
We present a modified version of Thom's (first) isotopy lemma, less general than the original but more obviously relevant to our situation.
Theorem: Suppose <math display="inline">Z</math> is a closed subset of a smooth manifold <math display="inline">M</math> which admits a Whitney stratification and <math display="inline">h : M \to \R</math> is a proper Morse function which has no critical values on <math display="inline">Z</math>. Then, the level sets of <math display="inline">Z</math> are homeomorphic by a homeomorphism that preserves the strata of <math display="inline">Z</math>.<ref>For various versions of the full statement of the theorem, see Mather 2012, pp. 499, Goresky and MacPherson 1988, pp. 41, or Pemantle, Wilson and Melczer 2024, pp. 541.</ref>
Proof:
# Construct control data for <math display="inline">Z</math> compatible with <math display="inline">h</math>.
## [Prop 7.1] If <math display="inline">h</math> is smooth on <math display="inline">Z</math> and is a submersion for each strata then there exists a family of control data for <math display="inline">Z</math> compatible with <math display="inline">h</math>.<ref>Mather 2012, pp. 488.</ref>
# This makes <math display="inline">Z</math> an abstract stratified set and <math display="inline">f</math> a controlled submersion.
# A controlled submersion has, for any smooth vector field on <math display="inline">\R</math>, a controlled vector field on <math display="inline">Z</math> (a "lift"?)<ref>Mather 2012, pp. 493.</ref>
# A controlled vector field has a unique one-parameter family of homeomorphisms of <math display="inline">Z</math> which commute with <math display="inline">h</math>.<ref>Mather 2012, pp. 496.</ref>
# This makes <math display="inline">h</math> a locally trivial fibration. [Prop 10.2]<ref>Mather 2012, pp. 499.</ref>
Control data:
A system of '''control data''' for <math display="inline">Z</math> consists of, for each stratum <math display="inline">X</math> of <math display="inline">Z</math>,
* a '''tubular neighbourhood''' <math display="inline">T_X</math> of <math display="inline">X</math>
* a '''tubular projection function''' <math display="inline">\pi_X: T_X \to X</math>, and
* a '''tubular distance function''' <math display="inline">\rho_X: T_X \to \R</math> such that <math display="inline">\rho_X^{-1}(0) = X</math><ref>Goresky and MacPherson 1988, pp. 42.</ref>
[illustration]
such that if <math display="inline">X < Y</math> are strata in <math display="inline">Z</math>, then
<math display="block">\pi_X \pi_Y(m) = \pi_X(m),</math>
<math display="block">\rho_X \pi_Y(m) = \rho_X(m)</math>
for all <math display="inline">m \in |T_X| \cap |T_Y|</math> such that <math display="inline">\pi_Y(m) \in |T_X|</math>.
If, for all strata <math display="inline">X</math> and all <math display="inline">m \in |T_X|</math>, we have <math display="inline">h \pi_X(m) = h(m)</math>, then this control data will be said to be compatible with <math display="inline">h</math>.<ref>Mather 2012, pp. 488.</ref>
We prove that if <math display="inline">h</math> is smooth on <math display="inline">Z</math> and is a submersion for each strata then there exists a family of control data for <math display="inline">Z</math> compatible with <math display="inline">h</math>.<ref>Mather 2012, pp. 488, prop 7.1.</ref>
Let <math display="inline">Z_k</math> be the union of strata of <math display="inline">Z</math> of dimension less than <math display="inline">k</math>. We prove by induction on <math display="inline">k</math>.
To construct the tubular neighbourhood <math display="inline">T_X</math> of a stratum <math display="inline">X</math> of dimension less than <math display="inline">k</math>. For <math display="inline">l \leq k</math>, let <math display="inline">U_l</math> denote the union of all <math display="inline">|T_Y|</math> for <math display="inline">Y < X</math> and <math display="inline">\dim Y \geq l</math>. Let <math display="inline">X_l = U_l \cap X</math>.<ref>Mather 2012, pp. 489.</ref>
For <math display="inline">l = k</math>, <math display="inline">X_k = \empty</math>. Assume by induction that <math display="inline">T_{l+1}</math> has been constructed and that if <math display="inline">Y < X</math>, <math display="inline">\dim Y \geq l + 1</math>, <math display="inline">m \in |T_{l+1}| \cap |T_Y|</math> and <math display="inline">\pi_{l+1}(m) \in |T_Y|</math> (<math display="inline">\pi_{l+1} = \pi_{T_{l+1}}</math>) then<ref>Mather 2012, pp. 489-490.</ref>
<math display="block">\rho_Y \pi_{l+1}(m) = \rho_Y(m),</math>
<math display="block">\pi_Y \pi_{l+1}(m) = \pi_Y(m).</math>
We wish to construct a tubular neighbourhood <math display="inline">T_{X,Y}</math> of <math display="inline">|T_Y| \cap X</math> whose restriction to <math display="inline">|T_Y| \cap X_{l+1}</math> is isomorphic to the restriction of <math display="inline">T_{l+1}</math> such that if <math display="inline">m \in |T_{X,Y}| \cap |T_Y|</math> and <math display="inline">\pi_{X,Y}(m) \in |T_Y|</math> (<math display="inline">\pi_{X,Y} = \pi_{T_{X,Y}}</math>) then
<math display="block">\rho_Y \pi_{X,Y}(m) = \rho_Y(m),</math>
<math display="block">\pi_Y \pi_{X,Y}(m) = \pi_Y(m).</math>
By shrinking <math display="inline">|T_Y|</math> if necessary, this relation is already satisfied if <math display="inline">m \in |T_{l+1}| \cap |T_Y|</math> and <math display="inline">\pi_{l+1}(m) \in |T_Y|</math> with <math display="inline">T_{l+1}</math> in place of <math display="inline">T_{X,Y}</math> and <math display="inline">\pi_{l+1}</math> in place of <math display="inline">\pi_{X,Y}</math>. By the definition, if <math display="inline">m \in |T_{l+1}|</math> then there exists <math display="inline">Z < X</math> with <math display="inline">\dim Z > l</math>, <math display="inline">m \in |T_Z|</math> and <math display="inline">\pi_{l+1}(m) \in |T_Z|</math>. We have that <math display="inline">\pi_{l+1}(m) \in |T_Y| \cap |T_Z|</math> and therefore <math display="inline">Y < Z</math>. Therefore<ref>Mather 2012, pp. 490.</ref>
<math display="block">\rho_Y \pi_{l+1}(m) = \rho_Y \pi_Z \pi_{l+1}(m) = \rho_Y \pi_Z(m) = \rho_Y(m),</math>
<math display="block">\pi_Y \pi_{l+1}(m) = \pi_Y \pi_Z \pi_{l+1}(m) = \pi_Y \pi_Z(m) = \pi_Y(m).</math>
We can prove that, by shrinking <math display="inline">|T_Y|</math>, <math display="inline">(\rho_Y, \pi_Y): |T_Y| \cap X \to \R \times Y</math> is a submersion [prop 7.3?] and that <math display="inline">T_{X,Y}</math> is compatible with <math display="inline">(\rho_Y, \pi_Y): |T_Y| \cap X_{l+1} \to \R \times Y</math>, i.e. <math display="inline">(\rho_Y, \pi_Y) \pi_{X,Y}(m) = (\rho_Y, \pi_Y)(m)</math>(?).
To prove it is a submersion, for the tubular neighbourhood <math display="inline">T = (E, \epsilon, \psi)</math> there exists a smooth positive function <math display="inline">\epsilon'</math> such that
<math display="block">(\rho_T, \pi_T): Y \cap |T|_{\epsilon'}^0 \to \R \times X,</math>
where <math display="inline">|T|_{\epsilon'}^0 = \psi(B_\epsilon \cap B_{\epsilon'})</math>, is a submersion. If <math display="inline">\Sigma</math> is the set <math display="inline">y \in |T|</math> such that the rank of
<math display="block">(\rho_T, \pi_T): T \cap |T| \to \R \times X</math>
at <math display="inline">y</math> is less than <math display="inline">\dim(\R \times X)</math>. We need to prove that for any <math display="inline">x \in X</math> there exists a neighbourhood of <math display="inline">x</math> which does not intersect with <math display="inline">\Sigma</math>, i.e. the map is not a submersion in this neighbourhood. It follows from [lemma 7.2] that it is enough to prove for <math display="inline">M = \R^m</math>, <math display="inline">X = \R^{m-c} \times 0_c</math> and <math display="inline">T</math> is the '''standard tubular neighbourhood'''.<ref>Mather 2012, pp. 489.</ref>
By standard tubular neighbourhood, we mean the trivial bundle with base <math display="inline">\R^{m-c}</math> and fibre <math display="inline">\R^c</math> where <math display="inline">\pi: \R^m \to \R^{m-c}</math>...<ref>Mather 2012, pp. 488.</ref>
For <math display="inline">y \in |T| - \R^{m-c}</math>, the kernal of the differential of <math display="inline">(\pi_T, \rho_T)</math> at <math display="inline">y</math> is the orthogonal complement of <math display="inline">(\R^{m-c} \times 0_c) \oplus \stackrel{\frown}{y \pi_T(y)}</math> in <math display="inline">\R^m</math>. By the Whitney conditions, we have that for <math display="inline">y</math> near <math display="inline">\R^{m-c}</math>, <math display="inline">(\R^{m-c} \times 0_c) \oplus \stackrel{\frown}{y \pi_T(y)}</math> is close to the set of <math display="inline">m - c + 1</math> planes in <math display="inline">m-</math>space to an <math display="inline">m - c + 1</math> plane in <math display="inline">TY_y</math>. Therefore, for <math display="inline">y</math> near enough to <math display="inline">\R^{m-c}</math>, <math display="inline">TY_y</math> is transverse to the kernal of the differential of <math display="inline">(\pi_T, \rho_T)</math> and, therefore, is a submersion when restricted to <math display="inline">Y</math>.<ref>Mather 2012, pp. 489.</ref>
To prove that <math display="inline">T_{X,Y}</math> is compatible with <math display="inline">(\rho_Y, \pi_Y): |T_Y| \cap X_{l+1} \to \R \times Y</math>...<ref>Mather 2012, pp. 490.</ref>
Therefore, there exists a tubular neighbourhood <math display="inline">T_0</math> of <math display="inline">X_0</math> satisfying
<math display="block">\rho_Y \pi_0(m) = \rho_Y(m),</math>
<math display="block">\pi_Y \pi_0(m) = \pi_Y(m).</math>
From this we can prove that <math display="inline">T_0</math> is compatible with <math display="inline">h</math>. Replacing <math display="inline">T_0</math> with a smaller tubular neighbourhood if necessary we can assume <math display="inline">m \in |T_0|</math> such that for some <math display="inline">Y < X</math>, <math display="inline">m \in |T_Y|</math> and <math display="inline">\pi_0(m) \in |T_Y|</math>, then<ref>Mather 2012, pp. 490.</ref>
<math display="block">h \pi_0(m) = h \pi_Y \pi_0(m) = h \pi_Y(m) = h(m).</math>
By the generalised tubular neighourhood theorem [prop 7.2?], we can replace <math display="inline">T_0</math> with a tubular neighbourhood <math display="inline">T</math> of <math display="inline">X</math> compatible with <math display="inline">h</math>. This completes the construction of <math display="inline">T_X</math>.<ref>Mather 2012, pp. 491.</ref>
This makes <math display="inline">Z</math> an '''abstract stratified set''' with axioms...<ref>Mather 2012, pp. 491-492.</ref>
This also makes <math display="inline">h</math> a '''controlled submersion''' because
# <math display="inline">h|X: X \to \R</math> is a smooth submersion on each strata <math display="inline">X</math> of <math display="inline">Z</math>, and
# for each stratum <math display="inline">X</math> there is a tubular neighbourhood <math display="inline">T'_X</math> such that <math display="inline">h(v) = h \pi_X(v)</math> for all <math display="inline">v \in T'_X</math>.<ref>Mather 2012, pp. 493.</ref>
The core of this is the concept of a '''vector field'''. A vector field is a function which assigns, for each point <math display="inline">p</math> in a space, a '''vector''', which can be represented by an arrow whose tail starts at <math display="inline">p</math>.<ref>Henle 1979, pp. 33.</ref>
[picture]
Imagine we have a vector field <math display="inline">v(x)</math> defined in a space and draw a line through our space. At each point along this line the vector field assigns a vector. If we move each point in this line along the arrow defined by this vector in the direction of the arrow head. This "flows" the entire line along the vectors.
[picture]
We define a '''stratified vector field''' <math display="inline">\eta</math> on <math display="inline">Z</math> to be a family of smooth vector fields <math display="inline">\eta_X</math>, one for each strata <math display="inline">X</math> of <math display="inline">Z</math>.<ref>Mather 2012, pp. 493.</ref>
We define a '''controlled vector field''' <math display="inline">\eta</math> on <math display="inline">Z</math> to be a stratified vector field such that for any strata <math display="inline">Y</math> there exists a tubular neighbourhood <math display="inline">T'_Y</math> such that for any <math display="inline">X > Y</math> and any <math display="inline">v \in T'_X \cap X</math><ref>Mather 2012, pp. 493.</ref>
<math display="block">\eta_X \rho_{Y,X}(v) = 0,</math>
<math display="block">(\pi_{Y,X})_* \eta_X(v) = \eta_Y (\pi_{Y,X}(v)).</math>
We prove that if <math display="inline">h</math> is a controlled submersion then, for any smooth vector field <math display="inline">\zeta</math> on <math display="inline">\R</math> there is a controlled vector field <math display="inline">\eta</math> on <math display="inline">Z</math> such that <math display="inline">h_* \eta(v) = \zeta(h(v))</math> for all <math display="inline">v \in Z</math>.<ref>Mather 2012, pp. 493.</ref>
Proceeding by induction on the maximum dimension of the strata of <math display="inline">Z</math>, we define <math display="inline">Z_k</math> to be the union of strata of <math display="inline">Z</math> of dimension at most <math display="inline">k</math>. The tubular neighbourhood of <math display="inline">Z_k</math> is the intersection of the tubular neighbourhoods of each strata in <math display="inline">Z_k</math> with <math display="inline">Z</math>. The projection and distance functions are the restrictions of the respective functions of <math display="inline">Z</math>.
It is trivially true when the maximum dimension of strata in <math display="inline">Z</math> is zero. Assume it is true for <math display="inline">k</math> and construct each <math display="inline">\eta_X</math> separately for each stratum <math display="inline">X</math> of dimension <math display="inline">k + 1</math>.
By the assumption that we have controlled vector fields for all strata <math display="inline">Y</math> of dimension at most <math display="inline">k</math>, we have the two control conditions defined above for any <math display="inline">X > Y</math> and that there is a neighbourhood <math display="inline">T^1_Y</math> such that <math display="inline">h(v) = h \pi_Y(v)</math> for <math display="inline">v \in T^1_Y</math>.
We want to prove that for all <math display="inline">Y < X</math>, the control conditions are satisfied for all <math display="inline">v \in T^2_Y</math> and that <math display="inline">h_*\eta_X(v) = \zeta(v)</math> for all <math display="inline">v \in X</math>.
Take a point <math display="inline">x \in X</math> and define the set <math display="inline">S_v</math> of strata <math display="inline">Y < X</math> such that <math display="inline">v \in T^2_Y</math>. <math display="inline">S_v</math> is totally ordered since if <math display="inline">Y_1</math> and <math display="inline">Y_2</math> are not comparable then <math display="inline">T^2_{Y_1} \cap T^2_{Y_2} = \empty</math>. Therefore, there is a largest member <math display="inline">Y = Y_v</math>.
Assume the control conditions hold for <math display="inline">Y = Y_v</math>. Then they hold for all <math display="inline">Y_i \in S_v</math>. For, either <math display="inline">Y_i = Y</math> or <math display="inline">Y_i < Y</math>. In the latter case, <math display="inline">\pi_Y(v) \in T^1_{Y_i}</math> (by the choice of <math display="inline">T^2_Y</math>'s [is this why?]. Then
<math display="block">\begin{align}
\eta_X(v) \rho_{Y_i,X}(v) &= \eta_X \rho_{Y_i,Y} \pi_{Y,X}(v) \\
&= (\pi_{Y,X})_* \eta_X(v) \rho_{Y_i,Y} \\
&= \eta_Y(\pi_{Y,X}(v)) \rho_{Y_i,Y} \\
&= 0
\end{align}</math>
and
<math display="block">\begin{align}
(\pi_{Y_i,X})_* \eta_X(v) &= (\pi_{Y_i,Y})_* (\pi_{Y,X})_* \eta_X(v) \\
&= (\pi_{Y_i,Y})_* \eta_Y(v) (\pi_{Y,X}) \\
&= \eta_{Y_i}(\pi_{Y_i,Y} \pi_{Y,X}(v)) \\
&= \eta_{Y_i}(\pi_{Y_i,X}(v))
\end{align}</math>
and, therefore, condition holds for all <math display="inline">Y_i \in S_v</math>. Also,
<math display="block">\begin{align}
h_* \eta_X(v) &= (h \circ \pi_{Y,X})_* \eta_X(v) \\
&= h_* \eta_Y (\pi_{Y,X}(v)) \\
&= \zeta(f(v))
\end{align}</math>
and, therefore, the conclusion of the theorem holds at <math display="inline">v</math>.
This shows we can construct <math display="inline">\eta_X</math> satisfying the control conditions when <math display="inline">S_v</math> is non-empty and satisfying the theorem when <math display="inline">S_v</math> is empty. The set of vectors satisfying these conditions is convex in <math display="inline">TX_v</math>, and so we construct <math display="inline">\eta_X</math> globally via a partition of unity.<ref>Mather 2012, pp. 493-495.</ref>
Finally, we prove that a controlled vector field has a unique one-parameter family of homeomorphisms of <math display="inline">Z</math> which commute with <math display="inline">h</math>.<ref>Mather 2012, this combines Proposition 10.1 and Corollary 10.2 on pp. 496 and 497, respectively.</ref>
For each stratum <math display="inline">X</math> of <math display="inline">Z</math>, <math display="inline">\eta_X</math> generates a unique smooth local one-parameter group <math display="inline">(J_X, \alpha_X)</math> of diffeomorphisms of <math display="inline">X</math> (by standard results of differential geometry), such that <math display="inline">\frac{d}{dt} \alpha(t, v)|_{t=0} = \eta_X(v)</math>, <math display="inline">J_X</math> is an open subset of <math display="inline">\R \times Z</math>, ...
If we define <math display="inline">(J, \alpha)</math> by
<math display="block">J = \bigcup_{X \in S} J_X</math>
<math display="block">\alpha = \bigcup_{X \in S} \alpha_X</math>
we can prove that this is a local one-parameter family of homeomorphisms.<ref>Mather 2012, pp. 496.</ref>
Firstly, it is clear that
# <math display="inline">0 \times Z \subseteq J</math> and <math display="inline">\alpha(0, v) = v</math> for all <math display="inline">v \in Z</math>.
# If <math display="inline">v \in Z</math> then <math display="inline">J_v = J \cap (\R \times v) \subseteq \R</math> is an open interval <math display="inline">(a_v, b_v)</math>, possibly infinite at one or both ends.
# If <math display="inline">v \in Z</math> and <math display="inline">t, s, t + s</math> are in <math display="inline">(a_v, b_v)</math> then <math display="inline">\alpha(t + s, v) = \alpha(t, \alpha(s, v))</math>.<ref>Mather 2012, pp. 495.</ref>
Secondly, it is clear that <math display="inline">\eta</math> generates <math display="inline">\alpha</math> because
# Each stratum <math display="inline">X</math> of <math display="inline">Z</math> is invariant under <math display="inline">\alpha</math>, i.e. <math display="inline">\alpha[J \cap (\R \times X)] \subseteq X</math>.
# For each <math display="inline">v \in Z</math>, the map <math display="inline">t \to \alpha(t, v)</math> of <math display="inline">(a_v, b_v)</math> into the stratum which contains <math display="inline">v</math> is <math display="inline">C^1</math>.
# For any <math display="inline">(t, v) \in Z</math>(?) we have <math display="inline">d/dt \alpha(t, v) = \eta(\alpha(t, v))</math>.<ref>Mather 2012, pp. 495.</ref>
It is unique because each <math display="inline">(J_X, \alpha_X)</math> is unique. We just need to prove that <math display="inline">J</math> is open, <math display="inline">\alpha</math> is continuous, and for any <math display="inline">v \in Z</math> and any compact set <math display="inline">K \subseteq Z</math> there exists <math display="inline">\epsilon > 0</math> such that <math display="inline">\alpha(t, v) \notin K</math> if <math display="inline">t \in (a_v, a_v + \epsilon) \cup (b_v - \epsilon, b_v)</math>.<ref>Mather 2012, pp. 495.</ref>
For the latter-most condition, if it did not hold then there exists...<ref>Mather 2012, pp. 496-497.</ref>
We prove there is a homeomorphism <math display="inline">f: Z \to h^{-1}(0) \times \R</math> such that <math display="inline">\pi \circ f = h</math>, where <math display="inline">\pi: h^{-1}(0) \times \R \to \R</math> is projection to the second factor.
For the coordinate vector field <math display="inline">\partial</math> on <math display="inline">\R</math>, by [prop 9.1] there is a controlled vector field <math display="inline">\tilde\partial</math> such that <math display="inline">f_* \tilde\partial(v) = \partial(h(v))</math> for <math display="inline">v \in Z</math>. By [prop 10.1], <math display="inline">\tilde\partial</math> generates a local one-parameter group <math display="inline">(J, \alpha)</math> such that
<math display="block">h(\alpha(t,v)) = h(v) + t</math>
<math display="inline">h</math> is proper and [d] holds, so <math display="inline">J = \R \times Z</math>. If we define <math display="inline">f</math> as
<math display="block">f(v) = (\alpha(-t, v), h(v))</math>
then <math display="inline">f</math> maps <math display="inline">Z</math> into <math display="inline">h^{-1}(0) \times \R</math> and <math display="inline">\pi \circ f = h</math>. If we define <math display="inline">\bar f: h^{-1}(0) \times \R \to Z</math> as
<math display="block">\bar f(v, t) = \alpha(t, v)</math>
then <math display="inline">f \bar f = \bar f f = Id</math> and <math display="inline">f</math> is a homeomorphism.<ref>Mather 2012, pp. 497.</ref>
== Topology at critical points ==
Theorem: If there is a critical point <math display="inline">p</math> in the singular variety <math display="inline">\mathcal{V}</math> with critical value <math display="inline">v \in (a, b)</math> then the space <math display="inline">X_{\leq b}</math> is homotopic to<ref>Goresky and MacPherson 1988, pp. 174.</ref>
<math display="block">X_{\leq a} \cup [(D^{\lambda+1}, \partial D^{\lambda+1}) \times (\mathcal{L}_X, \partial \mathcal{L}_X)].</math>
Proof:<ref>Proof outline comes from Goresky and MacPherson 1988, pp. 174.</ref>
# <math display="inline">(X_{\leq b}, X_{\leq a})</math> is homeomorphic to <math display="inline">(X_{\leq v + \epsilon}, X_{\leq v -\epsilon})</math>. We can prove this by "moving wall" or Thom's Isotopy Lemma.<ref>Goresky and MacPherson 1988, pp. 90-91, 120.</ref>
# <math display="inline">X_{\leq v + \epsilon}</math> is homeomorphic to <math display="inline">X_{\leq v - \epsilon} \cup (J, K)</math>, where the latter is the local Morse data for <math display="inline">h</math> at <math display="inline">p</math>. We do this by moving the wall...<ref>Goresky and MacPherson 1988, pp. 95-96, 120-121.</ref>
# <math display="inline">(J, K)</math> is homeomorphic to <math display="inline">(D^{\lambda+1}, \partial D^{\lambda+1}) \times (\mathcal{L}_X, \partial \mathcal{L}_X)</math> (tangential data, normal data). Again, moving the wall...<ref>Goresky and MacPherson 1988, pp. 65-66, chapter 8, 121.</ref>
# The normal Morse data depends only on the differential <math display="inline">df(p)</math>.<ref>Goresky and MacPherson 1988, pp. 93.</ref>
# The normal Morse data has the homotopy type of <math display="inline">(\mathcal{L}_X, \partial \mathcal{L}_X)</math>.<ref>Goresky and MacPherson 1988, pp. 169.</ref>
=== Step 1 ===
We get this immediately(?) by Thom's Isotopy Lemma.
=== Step 2 ===
<ref>Goresky and MacPherson 1988, complex case on pp. 120-121 is extension of real case on pp. 95-96.</ref>
Step 1 works because <math display="inline">h</math> is a submersion at each point of the regions we are homeomorphing. This is not the case at critical points. We need some way by which a homeomorphism can pass through a critical point.
To prove a homeomorphism between two subsets <math display="inline">A</math> and <math display="inline">B</math> of <math display="inline">Z</math>, we project <math display="inline">Z</math> to some other space <math display="inline">N</math> (in our case <math display="inline">\R^n</math>) using some function <math display="inline">F</math>. We take subsets <math display="inline">Y_0</math> and <math display="inline">Y_1</math> of <math display="inline">N</math> such that <math display="inline">A = Z \cap F^{-1}(Y_0)</math> and <math display="inline">B = Z \cap F^{-1}(Y_1)</math>. We need to prove <math display="inline">Y_0</math> and <math display="inline">Y_1</math> are connected by a one-parameter family of regions <math display="inline">Y_t</math> [explain one-parameter family]. The criterion for such a family to exist is that the '''characteristic covectors''' of <math display="inline">F</math> are all nonzero on each stratum of <math display="inline">Y_t</math>.<ref>Goresky and MacPherson 1988, pp. 70.</ref>
At each point <math display="inline">x \in M</math> and <math display="inline">y \in N</math> there are '''tangent spaces''' <math display="inline">T_xM</math> and <math display="inline">T_yN</math>, a vector space whose zero is at the point <math display="inline">x</math> or <math display="inline">y</math> (resp.)
[picture of various tangent spaces]
In the case the <math display="inline">N = \R</math>, the tangent space <math display="inline">T_x\R</math> is just <math display="inline">\R</math> but whose origin is at <math display="inline">x</math>.
[picture of T_x\R]
Say <math display="inline">F(x) = y</math>, then the differential of the map <math display="inline">F</math> can be seen as a function whose input is a vector in the tangent space <math display="inline">T_xM</math> and whose output is a vector in the tangent space <math display="inline">T_yM</math>. [If I move this far on the tangent space of M how do I move in the tangent space of N?]
[picture]
[example for M = \R and N = \R?]
A function which takes as input a vector in the tangent space <math display="inline">T_xM</math> (say) and outputs a scalar (usually <math display="inline">\R</math>) is called a '''covector'''. The set of all covectors on <math display="inline">T_xM</math> is called the dual space of <math display="inline">T_xM</math> and is denoted <math display="inline">T^*_xM</math>. There are only a limited number of ways to express a covectors. For example, if our tangent space is two-dimensional then all covectors are of the form <math display="inline">ax + by</math> where <math display="inline">(x, y) \in T_xM</math>.
We take our space <math display="inline">M</math> and map it onto <math display="inline">\R^2</math> with the map <math display="inline">F(z) = (r(z), h(z))</math>, where <math display="inline">z \in M</math> and <math display="inline">r</math> is the square of the distance of <math display="inline">z</math> to the critical point <math display="inline">p</math>.
[graph of mapping]
In this case, the covectors on the tangent space <math display="inline">T_xM</math> are of the form <math display="inline">adf(x) + bdr(x)</math> (in this case <math display="inline">df</math> and <math display="inline">dr</math> are maps to <math display="inline">\R</math>) and on <math display="inline">T_y\R^2</math> are of the form <math display="inline">cu + dv</math> (for <math display="inline">(u, v) \in \R^2</math>). A covector <math display="inline">cu + dv \in T^*_{(u, v)}\R^2</math> is called a '''characteristic covector''' of <math display="inline">F</math> if <math display="inline">F(x) = (u, v)</math> and <math display="inline">cdf(x) + ddr(x) = 0</math> for all vectors in the tangent space of the stratum containing <math display="inline">p</math>.<ref>Goresky and MacPherson 1988, pp. 82.</ref> [explain adf(x) + bdr(x) in terms of this being a function which takes a vector input]
[example of where covectors do and do not vanish on a stratified space, pp. 71?]
What we want is a homeomorphism in <math display="inline">M</math> between the space <math display="inline">Z_{\leq \epsilon}</math> and <math display="inline">Z_{\leq \epsilon} \cup B</math>, where <math display="inline">B</math> is a small region of the critical point <math display="inline">p</math>. The '''local Morse data''' is
<math display="block">((B_\delta \cap Z) \cap f^{-1}[v-\epsilon, v+\epsilon], (B_\delta \cap Z) \cap f^{-1}(v-\epsilon))</math>
where <math display="inline">B_\delta</math> is a closed disc in <math display="inline">M</math> of radius <math display="inline">\delta</math>.<ref>Goresky and MacPherson 1988, pp. 63-64.</ref> Observe that this is the pair <math display="inline">(F^{-1}(\text{Box}(\delta, \epsilon)), F^{-1}(\text{Bottom}(\delta, \epsilon)))</math><ref>Goresky and MacPherson 1988, pp. 91.</ref> [explain Box, Bottom, etc.]
[picture of the two subspaces of Z in M]
We use our map <math display="inline">F</math> to convert these two subspaces to subspaces of <math display="inline">\R^2</math> which are of the form <math display="inline">Y_1 = \{(x,y) \in \R^2 | y \leq \epsilon\}</math> and <math display="inline">Y_0 = \{(x,y) \in \R^2 | y \leq -\epsilon\} \cup \{(x,y) \in \R^2 | x \leq \delta, y \leq \epsilon\}</math>, such that <math display="inline">Z_{\leq \epsilon} = F^{-1}(Y_1)</math> and <math display="inline">Z_{\leq \epsilon} \cup B = F^{-1}(Y_0)</math>.<ref>Goresky and MacPherson 1988, pp. 95-96.</ref>
We use a homeomorphism between <math display="inline">Y_1</math> and <math display="inline">Y_0</math> using the technique of "moving the wall" and Thom's Isotopy Lemma. Such a homeomorphism exists when the characteristic covectors of <math display="inline">F</math> are all nonzero on each stratum of <math display="inline">Y_t</math>.<ref>Goresky and MacPherson 1988, chapter 4, particularly pp. 71-72.</ref>
Given a smooth mapping between manifolds <math display="inline">F: M \to N</math> (for example, in our case we could have <math display="inline">N = \R^2</math>) and that <math display="inline">F|Z: Z \to N</math> is proper. Let <math display="inline">Y \subset N \times \R</math> be a closed Whitney stratified subset such that the projection to the second factor <math display="inline">\pi: Y \to \R</math> is a proper stratified submersion.<ref>Goresky and MacPherson 1988, pp. 71.</ref>
Suppose for each <math display="inline">t \in \R</math>, for each <math display="inline">p \in F(Z) \cap Y_t</math>, and for each nonzero characteristic covector <math display="inline">\lambda \in T^*_pN</math> of <math display="inline">F|Z</math>, the restriction of <math display="inline">\lambda</math> to the subspace <math display="inline">T_pS_t = \ker(d\pi(p)) \cap T_pS</math> is nonzero, where <math display="inline">S</math> is a stratum of <math display="inline">Y</math> which contains <math display="inline">(p, t)</math> and <math display="inline">S_t = \pi^{-1}(t) \cap S</math> is the stratum of <math display="inline">Y_t = \pi^{-1}(t) \cap Y</math> which contains <math display="inline">p</math>. This is equivalent to the statement that, for each <math display="inline">t \in \R</math>, the restriction <math display="inline">F|Z</math> is transverse to <math display="inline">Y_t</math>.<ref>Goresky and MacPherson 1988, pp. 71-72.</ref>
This means that, for each <math display="inline">t \in \R</math>, <math display="inline">Z \cap F^{-1}(Y_t)</math> is stratified by its intersection with the strata of <math display="inline">Z</math>...
We finally prove there is a homeomorphism between <math display="inline">Z \cap F^{-1}(Y_0) \cong Z \cap F^{-1}(Y_1)</math> which preserves the Whitney stratification of both sides and is smooth on each stratum.
For the composition
<math display="block">Z \times \R \subset M \times \R \to_{F \times I} Y \subset \R^2 \times \R \to_{\pi} \R</math>
where <math display="inline">Y(t, z) = Y_t(z)</math>, <math display="inline">I</math> is the identity and <math display="inline">\pi</math> is projection to the second factor.
<math display="inline">Z \times \R</math> is transverse to <math display="inline">(F \times I)^{-1}(Y)</math>...
The composition <math display="inline">\pi \circ (F \times I): Z \times \R \cap (F \times I)^{-1}(Y) \to \R</math> is a stratified submersion because
* The input domain is stratified as above...,
* We have defined <math display="inline">F|Z</math> to be transverse to <math display="inline">Y</math>, and therefore it preserves the stratification (unless <math display="inline">F(Z) \cap Y = \empty</math>), and
* We defined above the projection on <math display="inline">Y</math> to be a stratified submersion, meaning it is a submersion on each stratum of <math display="inline">F(Z) \cap Y</math>.<ref>Goresky and MacPherson 1988, pp. 43.</ref>
Therefore, we can apply Thom's Isotopy Lemma which says there is a homeomorphism between the level sets of <math display="inline">Z \times \R</math>...<ref>Goresky and MacPherson 1988, pp. 72.</ref>
=== Step 3 ===
We prove there is a stratum preserving homeomorphism between<ref>Goresky and MacPherson 1988, pp. 65.</ref>
<math display="block">\text{Local Morse Data} \cong (\text{Tangential Morse Data}) \times (\text{Normal Morse Data})</math>
We first prove that there is a homeomorphism between the product of the normal and tangential Morse data and the '''realisation''' of the following diagram
[diagram from pp. 102]
where realisation means
<math display="block">Z \cap (g_1, h_1)^{-1}(P_a) \cap (g_2, h_2)^{-1}(P_b)</math>
where all the intersections of strata (of <math display="inline">Z</math>?) are transverse.<ref>Goresky and MacPherson 1988, pp. 100-102.</ref>
The realisation of the above diagram is equal to
<math display="block">(V_1, V_2) \cap (W_1, W_2) = (V_1 \cap W_1, V_1 \cap W_2 \cup V_2 \cap W_1)</math>
where
<math display="block">V_1 = \{ z \in Z : |f(z) - f\pi(z)| \leq \epsilon/4, r\pi(z) \leq \delta, \rho(z) \leq \delta \}</math>
<math display="block">V_2 = \{ z \in Z : f(z) - f\pi(z) = -\epsilon/4, r\pi(z) \leq \delta, \rho(z) \leq \delta \}</math>
<math display="block">W_1 = \{ z \in Z : |f\pi(z)| \leq 3\epsilon/4, r\pi(z) \leq \delta \}</math>
<math display="block">W_1 = \{ z \in Z : f\pi(z) = -3\epsilon/4, r\pi(z) \leq \delta \}</math>
where <math display="inline">\pi</math> is the projection from the tubular neighbourhood to <math display="inline">Z</math>, <math display="inline">r(z)</math> is the square of the distance between <math display="inline">z</math> and the critical point <math display="inline">p</math> and <math display="inline">\rho(z)</math> is the square of the distance between <math display="inline">z</math> and <math display="inline">\pi(z)</math>.<ref>Goresky and MacPherson 1988, pp. 100-101.</ref> <math display="inline">\epsilon \ll \delta</math> are chosen so that <math display="inline">(\delta, \epsilon)</math> is in the set <math display="inline">A^\flat_6</math> which consists of <math display="inline">A_6 \subset \R^+ \times \R^+</math> with the properties that for <math display="inline">(\epsilon, \delta) \in A_6</math> and <math display="inline">z</math> such that <math display="inline">\rho(z) = \delta</math>, <math display="inline">r\pi(z) = \delta</math>, <math display="inline">|f(z)| \leq \epsilon</math> and <math display="inline">|f\pi(z)| \leq \epsilon</math> then the covectors <math display="inline">d\rho(z)</math>, <math display="inline">dr\pi(z)</math>, <math display="inline">df(z)</math> and <math display="inline">df\pi(z)</math> are linearly independent when restricted to <math display="inline">T_zY</math> (where <math display="inline">Y</math> is the stratum containing <math display="inline">z</math>). We can prove such a set exists.<ref>Goresky and MacPherson 1988, pp. 89.</ref> <math display="inline">A^\flat_6</math> is this plus its reflection about the <math display="inline">x</math> axis.<ref>Goresky and MacPherson 1988, pp. 82.</ref>
Let <math display="inline">D = \{ x \in X | r(x) \leq \delta \}</math> for stratum <math display="inline">X</math>. We will show there is a local trivial fibration of the configuration: <math display="inline">(V_1, V_2)</math> fibres over <math display="inline">D</math> and is homeomorphic to <math display="inline">D \times (\text{normal Morse data})</math>
(V_1, V_2) -> D \times (normal Morse data)
| /
--> D <---
and that <math display="inline">(W_1, W_2)</math> fibres over the tangential Morse data and is homeomorphic to <math display="inline">(\text{tangential Morse data}) \times (\text{normal slice})</math>.
For <math display="inline">Z_1 = \{ z \in Z : r\pi(z) \leq \delta \}</math>, the map <math display="inline">F(z): Z_1 \to \R^2 = (\rho(z), f(z) - f\pi(z))</math> is transverse to each stratum of <math display="inline">\text{Box}(\delta, \epsilon/4)</math>, [list], [by lemma 6.5]. <math display="inline">(V_1, V_2) = F^{-1}(\text{Box}(\delta, \epsilon/4), \text{Bottom}(\delta, \epsilon/4))</math>. For each stratum <math display="inline">S</math> of Box and each <math display="inline">x \in D</math>, we have transverse intersection <math display="inline">F^{-1}(S) \pitchfork \pi^{-1}(x)</math>. Therefore, <math display="inline">\pi|F^{-1}(S)</math> is a submersion and by Thom's isotopy lemma the projection <math display="inline">\pi|F^{-1}(\text{Box}(\delta, \epsilon/4): F^{-1}(\text{Box}(\delta, \epsilon/4)) \to X</math> is a stratified fibre bundle over <math display="inline">D</math>. The fibre over the critical point <math display="inline">p</math> is <math display="inline">\pi^{-1}(p) \cap (F^{-1}(\text{Box}(\delta, \epsilon/4), F^{-1}(\text{Bottom}(\delta, \epsilon/4))</math> and is equal to the normal Morse data...<ref>Goresky and MacPherson 1988, pp. 101.</ref>
Take <math display="inline">G: X \to \R^2 = (r(x), f(x))</math>. <math display="inline">\delta</math> and <math display="inline">\epsilon</math> have been chosen so that <math display="inline">(G^{-1}(\text{Box}(\delta, \epsilon/4), G^{-1}(\text{Bottom}(\delta, \epsilon/4))</math> is the tangential Morse data for <math display="inline">f</math> and is contained in the region <math display="inline">D</math> over which <math display="inline">\pi|(V_1, V_2)</math> is a stratified fibre bundle. Therefore, <math display="inline">(W_1, W_2) = \pi^{-1} G^{-1}(\text{Box}(\delta, \epsilon/4), \text{Bottom}(\delta, \epsilon/4))</math> is transverse to <math display="inline">(V_1, V_2)</math>.<ref>Goresky and MacPherson 1988, pp. 101-102.</ref>
Finally, this means that <math display="inline">(V_1, V_2) \cap (W_1, W_2)</math> is homeomorphic (by stratum preserving homeomorphism) to <math display="inline">(\pi^{-1}(p), \cap (V_1, V_2)) \times \pi(W_1, W_2)</math>, the product of normal and tangential Morse data.<ref>Goresky and MacPherson 1988, pp. 102.</ref>
We use a succession of such diagrams to interpolate between the box diagram which defines local Morse data [explain] and the above diagram whose realisation we have just proven is <math display="inline">(\text{normal Morse data}) \times (\text{tangential Morse data})</math>.
[diagram_d0.py]
The realisation is the local Morse data. This is equal to the realisation of the diagram below.<ref>Goresky and MacPherson 1988, pp. 103, 106.</ref>
[diagram_d11.py]
The realisation of the first diagram [d0] is equivalent to the realisation of the below diagram.
[diagram_d1.py]
In the right-hand picture of the above diagram, we have put a dotted outline around the region <math display="inline">A^{\flat}_1</math>. We prove that there are no characteristic covectors for <math display="inline">(r, f): Z \to \R^2</math> in this region and can, therefore, move the wall in this region...<ref>Goresky and MacPherson 1988, pp. 82-83.</ref>
By adding a zero-dimensional stratum at the top right corner of the right-hand picture. A one-parameter family of pictures <math display="inline">P_b(t)</math> gives rise to a stratified space <math display="inline">Y \subset M \times \R</math> such that
<math display="block">Y = \{ (z, t) \in M \times \R : (r, f)(z) \in P_b(t) \}.</math>
<math display="inline">(r, f)</math> takes each stratum of <math display="inline">Z</math> transversally to each stratum of each <math display="inline">Y_t</math>. <math display="inline">(f \circ \pi, f)^{-1}(P_a) = f^{-1}[-\epsilon, \infty)</math> is transverse to each stratum of <math display="inline">Y_t \cap Z</math>. Therefore, there is a homeomorphism between<ref>Goresky and MacPherson 1988, pp. 107.</ref>
<math display="block">Z(D_1) = Z \cap (f \circ \pi, f)^{-1}(P_a) \cap (r, f)^{-1}(P_b(0))</math>
and
<math display="block">Z(D_1) = Z \cap (f \circ \pi, f)^{-1}(P_a) \cap (r, f)^{-1}(P_b(1)).</math>
To go from D_2 to D_3 we find the characteristic covectors of <math display="inline">(f\pi, f): V \to \R^2</math> where <math display="inline">V = (r, f)^{-1}(P_b(1))</math>. We stratify <math display="inline">P_b(1)</math> by its interior <math display="inline">P</math> and boundary <math display="inline">\partial P</math>.<ref>Goresky and MacPherson 1988, pp. 107.</ref>
The strata of <math display="inline">V</math> come in four types:
# <math display="inline">(r, f)^{-1}(P) \cap X</math>
# <math display="inline">(r, f)^{-1}(P) \cap Y</math>
# <math display="inline">(r, f)^{-1}(\partial P) \cap X</math>
# <math display="inline">(r, f)^{-1}(\partial P) \cap Y</math>
where <math display="inline">X</math> is the strata that contains the critical point and <math display="inline">Y</math> is any other strata such that <math display="inline">Y > X</math>.
All characteristic covectors are of the form <math display="inline">\lambda = (u, v, adu + bdv) \in T^*\R^2</math>.
For strata 1 and 3, the image of <math display="inline">X</math> under <math display="inline">(f\pi, f)</math> is the diagonal <math display="inline">f\pi = f</math> (dotted outline). Therefore, the characteristic covectors of any point <math display="inline">z</math> in <math display="inline">X</math> are either where <math display="inline">z = p</math>, in which case the covector is zero(?), or where <math display="inline">z \neq p</math>, in which case <math display="inline">u = v</math> and <math display="inline">a = b</math>.<ref>Goresky and MacPherson 1988, pp. 107-108.</ref>
For strata 2, being that the critical point is isolated and non-degenerate, which means it, and any neighbourhood, is not zero on any limit of tangent spaces in strata <math display="inline">Y > X</math>. Therefore, <math display="inline">f</math> and <math display="inline">f\pi</math> are linearly independent.<ref>Goresky and MacPherson 1988, pp. 84.</ref> Unless <math display="inline">\pi(z) = p</math>, in which case <math display="inline">d(f\pi)(z) = f\pi(z) = 0</math>, so they are covectors where <math display="inline">u = 0</math> and <math display="inline">b = 0</math>.<ref>Goresky and MacPherson 1988, pp. 108.</ref>
For strata 4, ...
== Morse theory ==
Steps(?)
* Explain topology
* Every point of a stratum is locally like a product structure (proved by Thom's Isotopy Lemma) [GM pp. 41-42]
** Including those around critical points, which are the product of normal and tangential Morse data (these are our quasi-local cycles?)
* Thom's Isotopy Lemma proves a strong deformation retraction (which only stops at critical points) [PWM pp. 541-542]
=== Homotopy ===
We want to replace our domain of convergence <math display="inline">M</math>, which is the complement of our singular variety <math display="inline">\mathcal{V}</math>, with an "equivalent" space <math display="inline">M'</math> which has better understood properties. We say "equivalent" because there are several different things we could mean by "equivalent" in this context. The equivalence we are referring to in this section is called '''homotopy'''.
Imagine two subspaces <math display="inline">\gamma_0</math> and <math display="inline">\gamma_1</math> of a space <math display="inline">Y</math> which are defined respectively by smooth functions <math display="inline">f, g: X \to Y</math>. If there exists a smooth function <math display="inline">h_s: X \times [0, 1] \to Y</math>, called a homotopy, such that <math display="inline">h_0 = f</math>, <math display="inline">h_1 = g</math> and for any <math display="inline">\epsilon > 0</math> there exists a <math display="inline">\delta_a</math> and <math display="inline">\delta_b</math> such that when <math display="inline">|s - s_0| < \delta_a</math> and <math display="inline">|x - x_0| < \delta_b</math> we have <math display="inline">|h_s(x) - h_{s_0}(x_0)| < \epsilon</math>, then we say <math display="inline">\gamma_0</math> and <math display="inline">\gamma_1</math> are '''homotopic'''.<ref>Henle 1979, pp. 251-252.</ref>
Below is an example where <math display="inline">\gamma_0</math> and <math display="inline">\gamma_1</math> are one-dimensional curves and <math display="inline">H(t, s) = h_s(t)</math>.
[[File:Homotopy_curves.png|300px]]
In [[#Homotopy_equivalence|Appendix A]], we formally prove that we can construct an equivalent space <math display="inline">M'</math>. We provide only an example to give some intuition before describing how to construct the space <math display="inline">M'</math> in terms of local cycles around critical points.
=== Motivating example ===
Imagine a torus and a height function which is just the z value of the point.
[[File:3D-Leveltorus.png|200px]]
It has four critical points: two at the top and bottom of the outer circle (<math display="inline">p_1, p_4</math>) and two at the top and bottom of the inner circle (<math display="inline">p_2, p_3</math>).
[picture]
When the height is between the <math display="inline">p_1</math> and <math display="inline">p_2</math>, the space is a two-cell, which can be retracted to a point.
[picture]
When the height is between <math display="inline">p_2</math> and <math display="inline">p_3</math>, the space is a cylinder, which can be retracted to a two-cell with a one-cell attached.
[[File:3D-Cylinder_and_disk_with_handle.png|200px]]
When the height is between <math display="inline">p_3</math> and <math display="inline">p_4</math>, the space is a torus with a disc removed, which can be retracted to a cylinder with a one-cell attached.
[[File:3D-Cylinder_with_handle_and_torus_with_hole.png|200px]]
When the height is greater than <math display="inline">p_4</math>, then the full torus is constructed by attaching a two-cell.
[Explain in terms of Morse data and Morse index?]
=== Morse data and quasi-local cycles ===
As in the above example, we start at the "bottom" of <math display="inline">M</math> and build upwards until just before we reach our first critical point <math display="inline">p</math>.
;Smooth points
:This is a tube around a <math display="inline">(d-1)</math>-chain <math display="inline">\gamma</math> where the height function <math display="inline">h</math> is maximised at <math display="inline">p</math>.<ref>Pemantle, Wilson and Melczer 2024, pp. 223.</ref>
:For example, if <math display="inline">F(x, y) = \frac{1}{1 - x - y}</math> then <math display="inline">\lambda = 1</math> and <math display="inline">B^\lambda</math> is an arc reaching its highest point at <math display="inline">p</math>.
:The normal plane <math display="inline">N</math> at <math display="inline">p</math> is a plane orthogonal to <math display="inline">B^1</math>(?).
:Its normal link <math display="inline">L(S)</math> is a circle with two points missing where it intersects <math display="inline">\mathcal{V}</math>.
:We make our quasi-local cycle out of the product of the arc and circle joined to <math display="inline">M_-</math> at points below <math display="inline">M_-</math>.
:With the exception of degenerate points, such as monkey saddles...<ref>e.g. Pemantle, Wilson and Melczer 2024, pp. 211.</ref>
;Transverse multiple points
:This is the product of a <math display="inline">k</math>-torus and a <math display="inline">(d-k)</math>-chain <math display="inline">\gamma</math>. The torus is the product of circles about <math display="inline">p</math> in the complex normal space to each strata which intersects <math display="inline">p</math>. The chain <math display="inline">\gamma</math> is supported in the stratum which is the common intersection of the varieties defined by the factors vanishing at <math display="inline">p</math>, and achieves its maximum height at <math display="inline">p</math>.<ref>Pemantle, Wilson and Melczer 2024, pp. 223-224.</ref>
;Arrangement multiple point
:This is the product of a <math display="inline">(d-k)</math>-chain <math display="inline">\gamma</math> and several <math display="inline">k</math>-tori, one for each pair of sheets which intersect transversely, where the torus is the product of circles about <math display="inline">p</math> in each sheet.<ref>Pemantle, Wilson and Melczer 2024, pp. 226.</ref>
;Cone point
:A cone point is zero-dimensional so there is no <math display="inline">\gamma</math>, just a <math display="inline">d</math>-torus about <math display="inline">p</math>.<ref>Pemantle, Wilson and Melczer 2024, pp. 227.</ref>
== Notes ==
{{Reflist}}
== References ==
* {{cite book | last1=Goresky | first1=Mark | last2=MacPherson | first2=Robert | title=Stratified Morse Theory | publisher=Springer-Verlag | year=1988 | url=https://www.math.ias.edu/~goresky/pdf/SMT.djvu }}
* {{cite book | last=Henle | first1=Michael | title=A Combinatorial Introduction to Topology | publisher=Dover Publications Inc. New York | year=1979 }}
* {{citation | last=Mather | first=John | title=Notes on Topological Stability | year=2012 | journal=Bulletin of the American Mathematical Society | volume=49 | number=4 | pages=475-506 | url=https://www.ams.org/journals/bull/2012-49-04/S0273-0979-2012-01383-6/S0273-0979-2012-01383-6.pdf }}.
* {{cite book | last1=Pemantle | first1=Robin | last2=Wilson | first2=Mark C. | last3=Melczer | first3=Stephen | title=Analytic Combinatorics in Several Variables | publisher=Cambridge University Press | year=2024 | edition=2nd | url=https://acsvproject.com/PemantleWilsonMelczer23.pdf }}
9ivg2tdqyalcudxne1yaoymcnxcpor5
Wikibooks:Speedy deletion
4
482855
4675887
4634510
2026-10-13T18:01:46Z
Codename Noreste
3441010
Removing all of that since I will do this with the current deletion criteria.
4675887
wikitext
text/x-wiki
{{draft}}
'''Speedy deletion''' is a deletion request where reasonable opposition is not expected or possible. Anyone can request speedy deletion, and anyone who objects or believes more discussion is needed can turn a speedy deletion candidate into a [[Wikibooks:Deletion policy#Requests for deletion|request for deletion]]. A speedy deletion nomination where there is '''any''' doubt that the criterion may not apply to the page should instead be a request for deletion. Speedy deletion requests made in bad faith can be removed by anyone.
Add <code><nowiki>{{</nowiki>[[Template:Delete|delete]]<nowiki>|reasons for speedy deletion}}</nowiki></code> to the top of a page to request speedy deletion. That page will then appear in [[:Category:Candidates for speedy deletion]] for administrators to address whenever time is available.
Pages that satisfy any of the following criteria below can be considered for speedy deletion.
== See also ==
* [[Wikibooks:Deletion policy]]
{{Wikibooks policies and guidelines}}
9v2qo0rgs6zoz3j21l65ul4mti4vywd
4675888
4675887
2026-10-13T18:03:35Z
Codename Noreste
3441010
+
4675888
wikitext
text/x-wiki
{{draft}}
'''Speedy deletion''' is a deletion request where reasonable opposition is not expected or possible. Anyone can request speedy deletion, and anyone who objects or believes more discussion is needed can turn a speedy deletion candidate into a [[Wikibooks:Deletion policy#Requests for deletion|request for deletion]]. A speedy deletion nomination where there is '''any''' doubt that the criterion may not apply to the page should instead be a request for deletion. Speedy deletion requests made in bad faith can be removed by anyone.
Add <code><nowiki>{{</nowiki>[[Template:Delete|delete]]<nowiki>|reasons for speedy deletion}}</nowiki></code> to the top of a page to request speedy deletion. That page will then appear in [[:Category:Candidates for speedy deletion]] for administrators to address whenever time is available.
Pages that satisfy any of the following criteria below can be considered for speedy deletion.
# Pages nominated for speedy deletion by the only significant contributor.
# Pages in the nominator's user namespace (their user page, talk page, or any sub-page thereof).
# Pages with no [[#Meaningful content|meaningful content]]. Always check and revert if good content in the revision history was replaced.
# Pages in a book where current book contributors support deletion. Always link to the discussion page where consensus was reached.
# Pages that cannot comply with the [[Wikibooks:What is Wikibooks|scope]] or [[Wikibooks:Policies and guidelines|policies]] of the project. Should there be '''any''' doubt, [[#Requests for deletion|get community consensus]].
# Orphaned redirects that do not conform with [[Wikibooks:Naming policy]] or where the names are unlikely to be inadvertently searched for by anyone.
# A repost of work previously deleted as a result of a [[Wikibooks:Requests for deletion|request for deletion]] that has not successfully gone through [[Wikibooks:Requests for deletion#Undeletion|requests for undeletion]].
== See also ==
* [[Wikibooks:Deletion policy]]
{{Wikibooks policies and guidelines}}
2udfo8jx4pvjlosig7vipe5w39h9xug
Vehicle Identification Numbers (VIN codes)/Jaguar/VIN Codes
0
485791
4675871
4675745
2026-10-13T16:40:16Z
JustTheFacts33
3434282
/* General Template for Jaguar's VIN format (All models: 2016- EXCEPT F-Type '16-'17, XJ '16-'19) */
4675871
wikitext
text/x-wiki
{{Vehicle Identification Numbers (VIN codes)/Warning}}{{clear}}
This VIN number decoding and designation system is used primarily for the North American Market. European and Asian markets use other decoding and designation systems.
==General Template for Jaguar's VIN format (All models: 2016- EXCEPT F-Type '16-'17, XJ '16-'19)==
===Jaguar WMIs (2016-) (Position 1-3)===
* SAJ - Jaguar passenger car (UK)
* SAD - Jaguar SUV (UK & Europe)
* L2C - Chery Jaguar Land Rover (China)
===Model Line (Position 4)===
{| class="wikitable"
|+Position 4
!VIN code
!Description
|-
|A
|[[w:Jaguar XE|Jaguar XE]] ('17-'20)
|-
|B
|[[w:Jaguar XF (X260)|Jaguar XF]] ('16-'24)
|-
|C
|[[w:Jaguar F-Pace|Jaguar F-Pace]] ('17-'26)
|-
|D
|[[w:Jaguar F-Type|Jaguar F-Type]] ('18-'24)
|-
|E
|[[w:Jaguar Type 01|Jaguar Type 01]] ('28-)
|-
|F
|[[w:Jaguar E-Pace|Jaguar E-Pace]] ('18-'24)
|-
|H
|[[w:Jaguar I-Pace|Jaguar I-Pace EV]] ('19-'24)
|}
===Body Style (Position 6):===
* 1 = Coupe (F-Type coupe)
* 2 = 5-door wagon (XF Sportbrake wagon)
* 2 = 5-door (E-Pace, F-Pace, I-Pace EV)
* 4 = 4-door sedan (XE, XF sedan, Type 01)
* 5 = Convertible (F-Type convertible)
===Transmission (Position 7) 2016-2017:===
* B = Automatic (XE '17, XF '16-'17, F-Pace '17)
===Engine/Emissions Control System (Position 8) 2016-2017:===
{| class="wikitable"
|+Position 8
! VIN !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| G || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Gas || DOHC,<br /> 16 valve||Direct Injection. ULEV. Dual VVT. Ford EcoBoost engine (Mazda L engine-based).<br> Jaguar XE 25t ('17).
|-
| N || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Diesel || DOHC,<br /> 16 valve||Common-rail Direct Injection. Exhaust VVT. JLR Ingenium AJ20D engine. Jaguar XE 20d, XF 20d, F-Pace 20d ('17).
|-
| V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 35t ('16-'17) [If 5th pos. of VIN is NOT G, H, M, or N]. Jaguar XE 35t ('17). Jaguar F-Pace 35t ('17) [If 5th pos. of VIN is NOT M or P].
|-
| V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar XF S ('16-'17). If 5th pos. of VIN is G, H, M, or N. Jaguar F-Pace S ('17) [If 5th pos. of VIN is M or P].
|}
===Check Digit/Gearbox (Position 9)===
* USA /Canada [[Vehicle Identification Numbers (VIN codes)/Check digit|Check digit]]
===Model Year Code (Position 10)===
''See: [[Vehicle Identification Numbers (VIN codes)/Model year]]''
===Plant Codes (Position 11) 2016-===
* A - Solihull, West Midlands, England, UK (XE '17, F-Pace '17-'26, Type 01 '28-)
* C - Castle Bromwich, West Midlands, England, UK (XE '17-'20, XF '16-'24, F-Type '18-'24)
* S - Oxford Road plant, Ryton, West Midlands, England, UK (JLR SVO plant) (XE SV Project 8 '19)
* 1 - Graz, Austria (Magna Steyr plant) (E-Pace '18-'24, I-Pace EV '19-'24)
===Model (Position 12)===
* 9 - XE ('17) [Solihull plant]
* P - XE ('17-'20) [Castle Bromwich plant]
* Y - XF ('16-'24)
* K - F-Type ('18-'24)
* Z - E-Pace ('18-'20)
* 0 - E-Pace ('20-'24)
* F - I-Pace EV ('19-'20)
* 6 - I-Pace EV ('20-'24)
'''Positions 13–17, Serial Number'''
==General Template for Jaguar's VIN format (All models: 2000-2015 plus F-Type '16-'17, XJ '16-'19)==
===Jaguar WMIs (2000-) (Position 1-3)===
* SAJ - Jaguar passenger car (UK)
* SAD - Jaguar SUV (UK & Europe)
===Regional Spec/Restraint System (Position 4):===
* J = Manual seat belts, Dual front airbags (US: XK8 '00)
* B = Manual seat belts, Dual front airbags (Canada: XK8 '00)
* D = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (US: S-Type '00-'02, XJ8/XJR '00-'03, XK8/XKR '01-'06, XK/XKR Early '07)
* F = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (Canada: S-Type '00-'02, XJ8/XJR '00-'03, XK8/XKR '01-'06, XK/XKR Early '07)
* E = Manual seat belts, Depowered Dual front airbags w/occupant position sensing, & Front Side Airbags & Side Curtain Airbags (US: X-Type '02-'04, S-Type '03-'04, XJ8/XJR Early '04)
* G = Manual seat belts, Depowered Dual front airbags w/occupant position sensing, & Front Side Airbags & Side Curtain Airbags (Canada: X-Type '02-'04,<br> S-Type '03-'04, XJ8/XJR Early '04)
* W = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Airbags & Side Curtain Airbags <br> (US: X-Type '05-'08, S-Type '05-'08, XF '09-'15, XJ8/XJR '04-'09, XJ '10-)
* X = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Airbags & Side Curtain Airbags (Canada: X-Type '05-'08, S-Type '05-'08, XF '09-'15, XJ8/XJR '04-'09, XJ '10-)
* W = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Head/Thorax Airbags <br> (US: XK/XKR '07-'15, F-Type '14-)
* X = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Head/Thorax Airbags <br> (Canada: XK/XKR '07-'15, F-Type '14-)
===Transmission & Steering Location (Position 5 - '00-'12):===
* A = Automatic / LHD
* B = Manual / LHD (X-Type '02-'05, S-Type 3.0 '03-'04)
===Transmission & Drive Wheels (Position 5 - '13-):===
* A = Automatic / Rwd (XF '13-'15, XJ '13-'19, XK '13-'15, F-Type '14-'17)
* B = Manual / Rwd (F-Type '16-'17)
* J = Automatic / Awd (XF Awd '13-'15, XJ Awd '13-'19, F-Type Awd '16-'17)
===Model Line (Position 6-7)===
{| class="wikitable"
|+Position 6-7
!VIN code
!Description
|-
|51
|[[w:Jaguar X-Type|Jaguar X-Type sedan - High Series]] ('02-'08)
|-
|52
|[[w:Jaguar X-Type|Jaguar X-Type sedan - Entry Series]] ('03-'04)
|-
|53
|[[w:Jaguar X-Type|Jaguar X-Type sedan w/Sport Package]] ('02-'03)
|-
|54
|[[w:Jaguar X-Type|Jaguar X-Type Sportwagon]] ('05-'08)
|-
|01
|[[w:Jaguar S-Type (1999)|Jaguar S-Type]] ('00-'08)
|-
|03
|[[w:Jaguar S-Type (1999)|Jaguar S-Type Sport]] [3.0, 4.0] ('02)
|-
|03
|[[w:Jaguar S-Type (1999)|Jaguar S-Type Sport]] [3.0, 4.2] ('03)
|-
|03
|[[w:Jaguar S-Type (1999)|Jaguar S-Type R]] ('03-'08)
|-
|05
|[[w:Jaguar XF (X250)|Jaguar XF Luxury]] ('09)
|-
|06
|[[w:Jaguar XF (X250)|Jaguar XF Premium Luxury]] ('09)
|-
|07
|[[w:Jaguar XF (X250)|Jaguar XF Supercharged]] ('09)
|-
|0E
|[[w:Jaguar XF (X250)|Jaguar XF]] ('13-'14)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF]] ('10-'12)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF 2.0T Premium]] [8th pos. of VIN is S] ('15)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF 3.0 Sport Rwd or 3.0 Portfolio Rwd]] [8th pos. of VIN is 7] ('15)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF 3.0 Sport Awd or 3.0 Portfolio Awd]] [8th pos. of VIN is F] ('15)
|-
|0G
|[[w:Jaguar XF (X250)|Jaguar XF Premium]] ('10-'11)
|-
|0H
|[[w:Jaguar XF (X250)|Jaguar XF Portfolio]] [8th pos. of VIN is B] ('12)
|-
|0H
|[[w:Jaguar XF (X250)|Jaguar XF Supercharged]] [8th pos. of VIN is E: '10-'13 or P: '13-'15]
|-
|0J
|[[w:Jaguar XF (X250)|Jaguar XFR]] ('10-'15)
|-
|0K
|[[w:Jaguar XF (X250)|Jaguar XFR-S]] ('13-'15)
|-
|8J
|[[w:Jaguar XF (X250)|Jaguar XFR w/Speed Pack]] ('13-'15)
|-
|12
|[[w:Jaguar XJ (X308)#Sport|Jaguar XJ Sport]] ('02-'03)
|-
|14
|[[w:Jaguar XJ (X308)|Jaguar XJ8]] ('00-'03)
|-
|15
|[[w:Jaguar XJ (X308)#XJR|Jaguar XJR]] ('00-'03)
|-
|23
|[[w:Jaguar XJ (X308)|Jaguar XJ8L]] (LWB) ('00-'01)
|-
|24
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ8 Vanden Plas]] (LWB) ('00-'03)
|-
|25
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ8 Vanden Plas Supercharged]] (LWB) ('00-'01)
|-
|25
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ Super V8]] (LWB) ('02-'03)
|-
|71
|[[w:Jaguar XJ (X350)|Jaguar XJ8]] ('04-'09)
|-
|73
|[[w:Jaguar XJ (X350)|Jaguar XJR]] ('04-'09)
|-
|74
|[[w:Jaguar XJ (X350)|Jaguar XJ8 Vanden Plas]] (SWB) ('04)
|-
|79
|[[w:Jaguar XJ (X350)|Jaguar XJ8L]] (LWB) ('05-'09)
|-
|82
|[[w:Jaguar XJ (X350)|Jaguar XJ8 Vanden Plas]] (LWB) ('05-'09)
|-
|82
|[[w:Jaguar XJ (X350)|Jaguar XJ Super V8]] (LWB, 5-psgr.) ('05-'09)
|-
|86
|[[w:Jaguar XJ (X350)|Jaguar XJ Super V8 Portfolio]] (LWB, 4-psgr.) ('06)
|-
|94
|[[w:Jaguar XJ (X350)|Jaguar XJ Super V8 Portfolio]] (LWB, 5-psgr.) ('09)
|-
|1C
|[[w:Jaguar XJ (X351)|Jaguar XJ]] ('10-'15)
|-
|1C
|[[w:Jaguar XJ (X351)|Jaguar XJ R-Sport]] [8th pos. of VIN is 7 (Rwd) or D (Awd)] ('16-'19)
|-
|1C
|[[w:Jaguar XJ (X351)|Jaguar XJ Supercharged]] [8th pos. of VIN is E] ('16-'19)
|-
|1E
|[[w:Jaguar XJ (X351)|Jaguar XJR]] ('14-'17)
|-
|1G
|[[w:Jaguar XJ (X351)|Jaguar XJ Supercharged]] [8th pos. of VIN is E: '10-'13 or T: '13-'15]
|-
|1J
|[[w:Jaguar XJ (X351)|Jaguar XJ Supersport]] ('11-'12)
|-
|2E
|[[w:Jaguar XJ (X351)|Jaguar XJR LWB]] ('14-'17), XJR575 LWB ('18-'19)
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL]] [8th pos. of VIN is B] ('10-'11)
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Rwd]] [8th pos. of VIN is B: '12-'13 or 1: '13]
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Rwd]] [8th pos. of VIN is Z: '14-'15)
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Rwd]] [8th pos. of VIN is 7: '16-'19), XJ50 3.0 Rwd (LWB) '19
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Awd]] [8th pos. of VIN is D] ('13-'19), XJ50 3.0 Awd (LWB) '19
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Supercharged]] [8th pos. of VIN is E: '10-'13, '16-'19 or T: '13-'15], XJ50 5.0 Rwd (LWB) '19, XJ Collection (LWB) '19
|-
|2J
|[[w:Jaguar XJ (X351)|Jaguar XJL Supersport]] ('11-'13)
|-
|2K
|[[w:Jaguar XJ (X351)|Jaguar XJL Ultimate]] ('13)
|-
|3F
|[[w:Jaguar XJ (X351)|Jaguar XJ Supersport w/Speed Pack]] ('12-'13)
|-
|3G
|[[w:Jaguar XJ (X351)|Jaguar XJL Supersport w/Speed Pack]] ('12-'13)
|-
|3H
|[[w:Jaguar XJ (X351)|Jaguar XJ Supercharged w/Sport & Speed Pack]] ('12-'15)
|-
|3K
|[[w:Jaguar XJ (X351)|Jaguar XJL Supercharged w/Sport & Speed Pack]] ('12-'15)
|-
|41
|[[w:Jaguar XK (X100)|Jaguar XK8/XKR coupe]] ('00-'06)
|-
|42
|[[w:Jaguar XK (X100)|Jaguar XK8/XKR convertible]] ('00-'06)
|-
|43
|[[w:Jaguar XK (X150)|Jaguar XK/XKR coupe]] ('07-'09)
|-
|44
|[[w:Jaguar XK (X150)|Jaguar XK/XKR convertible]] ('07-'09)
|-
|45
|[[w:Jaguar XK (X150)|Jaguar XKR Portfolio Edition coupe]] ('09)
|-
|46
|[[w:Jaguar XK (X150)|Jaguar XKR Portfolio Edition convertible]] ('09)
|-
|4D
|[[w:Jaguar XK (X150)|Jaguar XK Touring coupe]] [8th pos. of VIN is B] ('13-'14)
|-
|4E
|[[w:Jaguar XK (X150)|Jaguar XK Touring convertible]] [8th pos. of VIN is B] ('13-'14)
|-
|4D
|[[w:Jaguar XK (X150)|Jaguar XKR coupe]] [8th pos. of VIN is C] ('10-'15)
|-
|4E
|[[w:Jaguar XK (X150)|Jaguar XKR convertible]] [8th pos. of VIN is C] ('10-'15)
|-
|4F
|[[w:Jaguar XK (X150)|Jaguar XK coupe]] (most Portfolio Edition features are std.) [8th pos. of VIN is B] ('10-'15)
|-
|4F
|[[w:Jaguar XK (X150)|Jaguar XKR175 coupe]] [8th pos. of VIN is C] ('11)
|-
|4F
|[[w:Jaguar XK (X150)|Jaguar XKR coupe w/Dynamic Pack]] [8th pos. of VIN is C] ('13-'15), XK Final Fifty Edition coupe ('15)
|-
|4G
|[[w:Jaguar XK (X150)|Jaguar XK convertible]] (most Portfolio Edition features are std.) [8th pos. of VIN is B] ('10-'15)
|-
|4G
|[[w:Jaguar XK (X150)|Jaguar XKR convertible w/Dynamic Pack]] [8th pos. of VIN is C] ('13-'15), XK Final Fifty Edition convertible ('15)
|-
|4H
|[[w:Jaguar XK (X150)|Jaguar XKR-S coupe]] ('12-'15), XKR-S GT coupe ('14)
|-
|4J
|[[w:Jaguar XK (X150)|Jaguar XKR-S convertible]] ('12-'15)
|-
|6A
|[[w:Jaguar F-Type)|Jaguar F-Type coupe]] ('15-'17), F-Type Premium coupe '17
|-
|6B
|[[w:Jaguar F-Type)|Jaguar F-Type S coupe]] ('15-'17), F-Type S British Design Edition coupe '17
|-
|6D
|[[w:Jaguar F-Type)|Jaguar F-Type R coupe]] ('15-'17)
|-
|6E
|[[w:Jaguar F-Type)|Jaguar F-Type convertible]] ('14-'17), F-Type Premium convertible '17
|-
|6F
|[[w:Jaguar F-Type)|Jaguar F-Type S convertible]] ('14-'17), F-Type S British Design Edition convertible '17
|-
|6G
|[[w:Jaguar F-Type)|Jaguar F-Type V8 S convertible]] ('14-'15)
|-
|6H
|[[w:Jaguar F-Type)|Jaguar F-Type R convertible]] ('16-'17)
|-
|6J
|[[w:Jaguar F-Type)|Jaguar F-Type SVR coupe]] ('17)
|-
|6K
|[[w:Jaguar F-Type)|Jaguar F-Type SVR convertible]] ('17)
|-
|7A
|[[w:Jaguar F-Type#Project 7)|Jaguar F-Type Project 7 convertible]] ('16)
|}
===Engine/Emissions Control System (Position 8)===
{| class="wikitable"
|+Position 8
! VIN !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| A || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. ULEV. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]].<br> Jaguar X-Type 3.0 (Mid '05-'08), S-Type 3.0 ('06-'08).
|-
| A || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. ULEV. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ34 V8 engine]]. Jaguar XF ('10).
|-
| A || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar XKR-S ('12-'15), XKR-S GT ('14), F-Type R coupe ('15).
|-
| B || 4.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. [[w:Jaguar AJ-V8 engine#Supercharged|Jaguar AJ-V8 - AJ27S V8 engine]].<br> Jaguar XJR ('00-'03), Vanden Plas Supercharged ('00-'01), Super V8 ('02-'03), XKR ('00-'02).
|-
| B || 4.2L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. [[w:Jaguar AJ-V8 engine#Supercharged_2|Jaguar AJ-V8 - AJ33S V8 engine]]. Jaguar XJR ('04-'05), Super V8 ('05), XKR ('03-'06).
|-
| B || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. ULEV. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ34 V8 engine]].<br> Jaguar S-Type ('06-'08), XF ('09), XJ8/Vanden Plas ('06-'09), XK ('07-'09).
|-
| B || 5.0L || V8 || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. Variable intake valve lift. Variable intake.<br> [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> Jaguar XF ('10-'12), XJ ('11-'12), XJL ('11), XJL Portfolio Rwd ('12-'13), XK ('10-'15), XK Touring ('13-'14).
|-
| C || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]].<br> Jaguar S-Type 3.0 ('00-'01), X-Type 3.0 ('02-Mid '05).
|-
| C || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ27 V8 engine]].<br> Jaguar XJ8/Vanden Plas ('00-'03), XJ Sport ('02-'03), XK8 ('00-'02).
|-
| C || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ33 V8 engine]]. Jaguar XJ8 ('04-'05), XK8 ('03-'06).
|-
| C || 4.2L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. ULEV. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#Supercharged_2|Jaguar AJ-V8 - AJ34S V8 engine]].<br> Jaguar S-Type R ('06-'08), XF Supercharged ('09), XJR ('06-'09), Super V8 ('06-'09), XKR ('07-'09).
|-
| C || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 510 PS/503 hp. Jaguar XFR ('10-'13), XJ/XJL Supersport ('11-'13), XKR ('10-'15).
|-
| C || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar F-Type S ('14-'15), F-Type S w/man. trans. ('16-'17).
|-
| D || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ28 V8 engine]]. Jaguar S-Type 4.0 ('00-'01).
|-
| D || 2.5L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ25|Jaguar AJ-V6 - AJ25 V6 engine]]. Jaguar X-Type 2.5 ('02-'05).
|-
| D || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XJ Awd, XJL Portfolio Awd ('13-'15).
|-
| D || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XJ R-Sport Awd, XJL Portfolio Awd ('16-'19), XJ50 3.0 Awd ('19).
|-
| E || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 470 PS/464 hp.<br> Jaguar XF Supercharged ('10-'13), XJ/XJL Supercharged ('11-'13, '16-'19), XJ50 5.0 Rwd ('19), XJ Collection ('19).
|-
| F || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Awd ('13-'14).
|-
| F || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Awd ('15).
|-
| H || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. 510 PS/503 hp. Jaguar XFR ('13-'15).
|-
| K || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar XJR/XJR LWB ('14-'17).
|-
| K || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 575 PS/567 hp. Jaguar XJR575 LWB ('18-'19).
|-
| L || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 495 PS/488 hp. Jaguar F-Type V8 S convertible ('14-'15).
|-
| L || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar F-Type R ('16-'17).
|-
| N || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]]. Jaguar S-Type 3.0 ('01-'02).
|-
| P || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ28 V8 engine]]. Jaguar S-Type 4.0 ('01-'02).
|-
| P || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. 470 PS/464 hp. Jaguar XF Supercharged ('13-'15).
|-
| S || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Gas || DOHC,<br /> 16 valve||Direct Injection. Dual VVT. Ford EcoBoost engine (Mazda L engine-based).<br> Jaguar XF 2.0T ('13-'14), XF 2.0T Premium ('15).
|-
| T || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]]. Jaguar S-Type 3.0 ('03-'05).
|-
| T || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. 470 PS/464 hp. Jaguar XJ/XJL Supercharged ('13-'15).
|-
| T || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar F-Type w/auto. trans. ('15-'17), F-Type Premium w/auto. trans. ('17).
|-
| U || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ33 V8 engine]]. Jaguar S-Type 4.2 ('03-'05).
|-
| U || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar F-Type S ('15), F-Type S Rwd w/auto. trans. ('16-'17).
|-
| V || 4.2L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. [[w:Jaguar AJ-V8 engine#Supercharged_2|Jaguar AJ-V8 - AJ33S V8 engine]]. Jaguar S-Type R ('03-'05).
|-
| V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar F-Type S Awd w/auto. trans. ('16-'17).
|-
| X || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 24 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Rwd ('14).
|-
| Z || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar XFR-S ('13-'15).
|-
| Z || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 24 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XJ Rwd, XJL Portfolio Rwd ('14-'15).
|-
| 1 || 5.0L || V8 || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. Variable intake valve lift. Variable intake. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. Jaguar XJL Portfolio Rwd ('13).
|-
| 6 || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar F-Type w/man. trans. ('16-'17), F-Type Premium w/man. trans. ('17).
|-
| 7 || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Rwd ('13), XJ Rwd ('13), F-Type ('14-'15).
|-
| 7 || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Rwd ('15), XJ R-Sport Rwd ('16-'19), XJL Portfolio Rwd ('16-'19), XJ50 3.0 Rwd ('19).
|-
| 8 || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 575 PS/567 hp. Jaguar F-Type Project 7 ('16), F-Type SVR ('17).
|}
===Check Digit/Gearbox (Position 9)===
* USA /Canada [[Vehicle Identification Numbers (VIN codes)/Check digit|Check digit]]
===Model Year Code (Position 10)===
''See: [[Vehicle Identification Numbers (VIN codes)/Model year]]''
===Plant Code/Model Line/Engine (Position 11) 2000-2019===
* X - Halewood, Merseyside, England, UK - X-Type 2.5 ('02-'05)
* W - Halewood, Merseyside, England, UK - X-Type 3.0 ('02-'08)
* F - Castle Bromwich, West Midlands, England, UK - S-Type 3.0 ('00-'08)
* G - Castle Bromwich, West Midlands, England, UK - S-Type 4.0 ('00-'02)
* H - Castle Bromwich, West Midlands, England, UK - S-Type 4.2 ('03-'08)
* 1 - Castle Bromwich, West Midlands, England, UK - S-Type R (4.2 supercharged) ('03-'08)
* H - Castle Bromwich, West Midlands, England, UK - XF 4.2 ('09-'10)
* 1 - Castle Bromwich, West Midlands, England, UK - XF Supercharged (4.2 supercharged) ('09)
* L - Castle Bromwich, West Midlands, England, UK - XF 5.0 ('10-'12)
* M - Castle Bromwich, West Midlands, England, UK - XF Supercharged, XFR (5.0 supercharged) ('10-'15), XFR-S (5.0 supercharged) ('13-'15)
* P - Castle Bromwich, West Midlands, England, UK - XF 2.0T ('13-'15)
* 8 - Castle Bromwich, West Midlands, England, UK - XF 3.0 supercharged ('13-'15)
* L - Browns Lane plant, Coventry, West Midlands, England, UK - XJ8 (4.0) ('00-'03), XJ8L (4.0) ('00-'01), XJ8 Vanden Plas (4.0) ('00-'03), XJ Sport (4.0) ('02-'03)
* M - Browns Lane plant, Coventry, West Midlands, England, UK - XJ8 Vanden Plas Supercharged (4.0 supercharged) ('00-'01),<br> Super V8 (4.0 supercharged) ('02-'03), XJR (4.0 supercharged) ('00-'03)
* S - Browns Lane plant, Coventry, West Midlands, England, UK - XJ8 (4.2) ('04-'06), XJ8L (4.2) ('05-'06), XJ8 Vanden Plas (4.0) ('04-'06)
* T - Browns Lane plant, Coventry, West Midlands, England, UK - Super V8 (4.2 supercharged) ('05-'06), Super V8 Portfolio (4.2 supercharged) ('06),<br> XJR (4.2 supercharged) ('04-'06)
* S - Castle Bromwich, West Midlands, England, UK - XJ8 (4.2) ('07-'09), XJ8L (4.2) ('07-'09), XJ8 Vanden Plas (4.0) ('07-'09)
* T - Castle Bromwich, West Midlands, England, UK - Super V8 (4.2 supercharged) ('07-'09), Super V8 Portfolio (4.2 supercharged) ('09),<br> XJR (4.2 supercharged) ('07-'09)
* L - Castle Bromwich, West Midlands, England, UK - XJ (5.0) ('10-'12), XJL (5.0) ('10-'11), XJL Portfolio (5.0) ('12-'13)
* M - Castle Bromwich, West Midlands, England, UK - XJ/XJL Supercharged (5.0 supercharged) ('10-'19), XJ/XJL Supersport (5.0 supercharged) ('11-'13),<br> XJL Ultimate (5.0 supercharged) ('13), XJR SWB/LWB (5.0 supercharged) ('14-'17), XJR575 LWB (5.0 supercharged) ('18-'19), XJ50 LWB (5.0 supercharged) ('19), XJ Collection Sp. Ed. LWB (5.0 supercharged) ('19)
* 8 - Castle Bromwich, West Midlands, England, UK - XJ base (3.0 supercharged) ('13-'15), XJ R-Sport (3.0 supercharged) ('16-'19),<br> XJL Portfolio AWD (3.0 supercharged) ('13-'19), XJL Portfolio RWD (3.0 supercharged) ('14-'19), XJ50 LWB (3.0 supercharged) ('19)
* N - Browns Lane plant, Coventry, West Midlands, England, UK - XK8 (4.0) ('00-'02)
* P - Browns Lane plant, Coventry, West Midlands, England, UK - XKR (4.0 supercharged) ('00-'02)
* 2 - Browns Lane plant, Coventry, West Midlands, England, UK - XK8 (4.2) ('03-'06)
* 3 - Browns Lane plant, Coventry, West Midlands, England, UK - XKR (4.2 supercharged) ('03-'06)
* 5 - Castle Bromwich, West Midlands, England, UK - XK (4.2) ('07-'09)
* 9 - Castle Bromwich, West Midlands, England, UK - XKR (4.2 supercharged) ('07-'09)
* L - Castle Bromwich, West Midlands, England, UK - XK (5.0) ('10-'15)
* M - Castle Bromwich, West Midlands, England, UK - XKR (5.0 supercharged) ('10-'15), XKR-S (5.0 supercharged) ('12-'15), XKR-S GT (5.0 supercharged) ('14)
* 8 - Castle Bromwich, West Midlands, England, UK - F-Type Base, S (3.0 supercharged) ('14-'17), F-Type Premium (3.0 supercharged) ('17)
* M - Castle Bromwich, West Midlands, England, UK - F-Type V8S (5.0 supercharged) ('14-'15), F-Type R (5.0 supercharged) ('15-'17),<br> F-Type Project 7 (5.0 supercharged) ('16), F-Type SVR (5.0 supercharged) ('17)
===Model (Position 12)===
* C - X-Type ('02-'03)
* D - X-Type ('03-'04)
* E - X-Type ('04-'06)
* J - X-Type ('06-'08)
* L - S-Type ('00-'01)
* M - S-Type ('01-'04)
* N - S-Type ('04-'08)
* R - XF ('09-'11)
* S - XF ('11-'13)
* U - XF ('13-'15)
* F - XJ ('00-'03)
* G - XJ ('04-'06) [Browns Lane plant]
* H - XJ ('06-'09) [Castle Bromwich plant]
* V - XJ ('10-'16)
* W - XJ ('16-'19)
* A - XK ('00-'06)
* B - XK ('07-'15)
* K - F-Type ('14-'17)
'''Positions 13–17, Serial Number'''
==General Template for Jaguar's VIN format (1981 - 1999)==
===Jaguar WMIs (1981-1999) (Position 1-3)===
* SAJ - Jaguar passenger car
===Model Line (Position 4)===
{| class="wikitable"
|+Position 4
!VIN code
!Description
|-
|A
|[[w:Jaguar XJ#Series 3 (1979–1992)|Jaguar XJ6]] ('81-'87), XJ6 Vanden Plas ('82-'87)
|-
|B
|[[w:Jaguar XJ#Series 3 (1979–1992)|Jaguar XJ12]] (Canada only: '81-'88)
|-
|D
|[[w:Jaguar XJ#Series 3 (1979–1992)|Jaguar XJ12]] (Canada only: '89-'92)
|-
|H
|[[w:Jaguar XJ (XJ40)|Jaguar XJ6]] ('88-'89, '93-'94)
|-
|F
|[[w:Jaguar XJ (XJ40)|Jaguar XJ6]] ('90-'92)
|-
|H
|[[w:Jaguar XJ (XJ40)|Jaguar XJ6 Sovereign]] ('90-'92)
|-
|K
|[[w:Jaguar XJ (XJ40)#Daimler/Vanden Plas|Jaguar XJ6 Vanden Plas]] ('88-'94)
|-
|M
|[[w:Jaguar XJ (XJ40)#Majestic (1989–1992 – SWB; 1993–1994 – LWB)|Jaguar XJ6 Vanden Plas Majestic]] ('89-'90, '92)
|-
|M
|[[w:Jaguar XJ (XJ40)#XJ12 and Daimler Double Six (XJ81)|Jaguar XJ12]] ('94)
|-
|H
|[[w:Jaguar XJ (X300)|Jaguar XJ6]] ('95-'97)
|-
|H
|[[w:Jaguar XJ (X300)|Jaguar XJ6L]] LWB [X330] ('97)
|-
|K
|[[w:Jaguar XJ (X300)#Daimler/Jaguar Vanden Plas|Jaguar XJ6 Vanden Plas]] SWB ('95)
|-
|K
|[[w:Jaguar XJ (X300)#Daimler/Jaguar Vanden Plas|Jaguar XJ6 Vanden Plas]] LWB [X330] ('96-'97)
|-
|M
|[[w:Jaguar XJ (X300)#XJ12 (X305)|Jaguar XJ12]] SWB ('95)
|-
|M
|[[w:Jaguar XJ (X300)#XJ12 (X305)|Jaguar XJ12]] LWB [X330] ('96)
|-
|P
|[[w:Jaguar XJ (X300)#XJR (X306)|Jaguar XJR]] ('95-'97)
|-
|H
|[[w:Jaguar XJ (X308)|Jaguar XJ8]] ('98-'99)
|-
|H
|[[w:Jaguar XJ (X308)|Jaguar XJ8L]] LWB ('98-'99)
|-
|K
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ8 Vanden Plas]] LWB ('98-'99)
|-
|P
|[[w:Jaguar XJ (X308)#XJR|Jaguar XJR]] ('98-'99)
|-
|N
|[[w:Jaguar XJS|Jaguar XJ-S]] ('82-'91), XJ-SC ('86-'88), XJS ('92-'96)
|-
|T
|[[w:Jaguar XJS|Jaguar XJ-S]] Rouge Collection ('89-'90), Classic Collection ('90-'91)
|-
|S
|[[w:Jaguar XJS#XJR-S|Jaguar XJR-S]] ('93)
|-
|G
|[[w:Jaguar XK (X100)|Jaguar XK8]] ('97-'99)
|}
===Class (Regional Spec)/Restraint System (Position 5):===
* V = N. American-spec (Manual seat belts)
* L = Canadian-spec (Manual seat belts)
* Y = XJ6 Vanden Plas [Series III] ('82-'87) (Manual seat belts)
* A = Motorized Shoulder Belts (XJ-S coupe '88-'89, XJ-SC '88)
* Y = Motorized Shoulder Belts (XJ-S coupe '89, XJ sedan '89-'92)
* W = Manual seat belts, Driver-side airbag (US: XJ-S '90-'93, XJ6 '93, XJ12 Early '94)
* X = Manual seat belts, Dual front airbags (US: XJS '94-'96, XJ6 '94-'97, XJ12 '94-'96, XJR '95-'97, XK8 '97-'99)
* X = Manual seat belts, Dual front airbags, & Front Side Airbags (US: XJ8/XJR '98-'99)
* D = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (US: XJ8/XJR '99)
* M = Manual seat belts, Driver-side airbag (Canada)
* N = Manual seat belts, Dual front airbags (Canada)
* F = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (Canada: XJ8/XJR '99)
===Body Style (Position 6):===
* 1 = 4-door sedan (XJ-series sedan '81-'99)
* 2 = 2-door convertible w/2+2 seating (XJS convertible '94-'96, XK8 convertible '97-'99)
* 3 = 2-door Cabriolet (XJ-SC '86-'88)
* 4 = 2-door convertible w/2-psgr. seating (factory-built XJS convertible '89-'94, XJR-S convertible '93)
* 5 = 2-door coupe (XJS coupe '82-'96, XJR-S coupe '93, XK8 coupe '97-'99)
* 5 = 2-door coupe (Hess & Eisenhardt-built XJS convertible '87-'88) [coupe conversion]
===Engine Type (Position 7):===
{| class="wikitable"
|+Position 7
|-
! VIN !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| 1 || 4.0L || I6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||MPI. [[w:Jaguar AJ6 engine#AJ16S|Jaguar AJ16S I6]]. Jaguar XJR ('95-'97).
|-
| 2 || 4.2L || I6 || Gas ||DOHC,<br /> 12 valve||CA & Canada-spec. MPI. [[w:Jaguar XK engine|Jaguar XK I6]]. Jaguar XJ6 ('81-'82).
|-
| 2 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||MPI. Dual-canister evaporative emissions system. [[w:Jaguar AJ6 engine#AJ16|Jaguar AJ16 I6]]. Jaguar XJ6 ('96-'97).
|-
| 2 || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Variable intake valve timing. Dual-canister evaporative emissions system. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ26 V8 engine]].<br> Jaguar XJ8 ('98), XK8 ('98).
|-
| 3 || 4.2L || I6 || Gas ||DOHC,<br /> 12 valve||N. America-spec. MPI. [[w:Jaguar XK engine|Jaguar XK I6]]. Jaguar XJ6 ('81-'87).
|-
| 3 || 6.0L || 60° V12 || Gas ||SOHC,<br /> 24 valve||MPI. [[w:Jaguar V12 engine|Jaguar V12]] modified by [[w:Tom Walkinshaw Racing|JaguarSport]]. Jaguar XJR-S ('93).
|-
| 3 || 6.0L || 60° V12 || Gas ||SOHC,<br /> 24 valve||MPI. [[w:Jaguar V12 engine|Jaguar V12]]. Jaguar XJS ('94-'95), XJ12 ('94-'96).
|-
| 5 || 3.6L || I6 || Gas ||DOHC,<br /> 24 valve||N. America-spec - Low Compression. MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('88-'89).
|-
| 6 || 3.6L || I6 || Gas ||DOHC,<br /> 24 valve||N. America-spec - High Compression. MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('88).
|-
| 7 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('90-'94), XJS ('93-'94).
|-
| 7 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||MPI. [[w:Jaguar AJ6 engine#AJ16|Jaguar AJ16 I6]]. Jaguar XJ6 ('95-'96), XJS ('95-'96).
|-
| 7 || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ26 V8 engine]]. Jaguar XK8 ('97).
|-
| 8 || 5.3L || 60° V12 || Gas ||SOHC,<br /> 24 valve||N. America-spec. MPI. [[w:Jaguar V12 engine|Jaguar V12]]. Jaguar XJ-S ('82-'92), XJ12 (Canada only: '88-'92).
|-
| 8 || 4.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. Dual-canister evaporative emissions system. [[w:Jaguar AJ-V8 engine#Supercharged|Jaguar AJ-V8 - AJ26S V8 engine]]. Jaguar XJR ('98-'99).
|-
| 9 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||Canada-spec. MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('90-'93), XJS ('93).
|-
| 0 || 5.3L || 60° V12 || Gas ||SOHC,<br /> 24 valve||Canada-spec. MPI. [[w:Jaguar V12 engine|Jaguar V12]]. Jaguar XJ-S ('82-'87), XJ12 (Canada only: '85-'87).
|-
| 0 || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. Dual-canister evaporative emissions system. Enhanced evaporative emissions control system. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ27 V8 engine]]. Jaguar XJ8 ('99), XK8 ('99).
|}
===Transmission & Steering Location (Position 8):===
* 4 = Automatic / LHD
* 8 = Manual / LHD ('93-'94 XJS 4.0 w/ optional 5-spd. manual)
===Check Digit/Gearbox (Position 9)===
* USA /Canada [[Vehicle Identification Numbers (VIN codes)/Check digit|Check digit]]
===Model Year Code (Position 10)===
''See: [[Vehicle Identification Numbers (VIN codes)/Model year]]''
===Plant Codes (Position 11)===
* C - Browns Lane plant, Coventry, West Midlands, England, UK
===Positions 12–17, Serial Number===
** 100001 and after - XJ-S/XJ-SC/XJS/XJR-S (XJ27)
** 300001 and after - XJ-series sedan Series III
** 500001 and after - XJ-series sedan (XJ40/XJ81)
** 720001 and after - XJ-series sedan (X300/X305/X306/X330)
** 810001 and after - XJ-series sedan (X308)
** 001001 and after - XK8 (X100)
izizrri5yp00ntgatuz186di3fcoyzr
4675953
4675871
2026-10-14T00:43:30Z
JustTheFacts33
3434282
/* Engine/Emissions Control System (Position 8) 2016-2017: */
4675953
wikitext
text/x-wiki
{{Vehicle Identification Numbers (VIN codes)/Warning}}{{clear}}
This VIN number decoding and designation system is used primarily for the North American Market. European and Asian markets use other decoding and designation systems.
==General Template for Jaguar's VIN format (All models: 2016- EXCEPT F-Type '16-'17, XJ '16-'19)==
===Jaguar WMIs (2016-) (Position 1-3)===
* SAJ - Jaguar passenger car (UK)
* SAD - Jaguar SUV (UK & Europe)
* L2C - Chery Jaguar Land Rover (China)
===Model Line (Position 4)===
{| class="wikitable"
|+Position 4
!VIN code
!Description
|-
|A
|[[w:Jaguar XE|Jaguar XE]] ('17-'20)
|-
|B
|[[w:Jaguar XF (X260)|Jaguar XF]] ('16-'24)
|-
|C
|[[w:Jaguar F-Pace|Jaguar F-Pace]] ('17-'26)
|-
|D
|[[w:Jaguar F-Type|Jaguar F-Type]] ('18-'24)
|-
|E
|[[w:Jaguar Type 01|Jaguar Type 01]] ('28-)
|-
|F
|[[w:Jaguar E-Pace|Jaguar E-Pace]] ('18-'24)
|-
|H
|[[w:Jaguar I-Pace|Jaguar I-Pace EV]] ('19-'24)
|}
===Body Style (Position 6):===
* 1 = Coupe (F-Type coupe)
* 2 = 5-door wagon (XF Sportbrake wagon)
* 2 = 5-door (E-Pace, F-Pace, I-Pace EV)
* 4 = 4-door sedan (XE, XF sedan, Type 01)
* 5 = Convertible (F-Type convertible)
===Transmission (Position 7) 2016-2017:===
* B = Automatic (XE '17, XF '16-'17, F-Pace '17)
===Engine/Emissions Control System (Position 8) 2016-2017:===
{| class="wikitable"
|+Position 8
! VIN !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| G || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Gas || DOHC,<br /> 16 valve||Direct Injection. ULEV. Dual VVT. Ford EcoBoost engine (Mazda L engine-based).<br> Jaguar XE 25t ('17).
|-
| N || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Diesel || DOHC,<br /> 16 valve||Common-rail Direct Injection. Exhaust VVT. JLR Ingenium AJ20D engine. Jaguar XE 20d, XF 20d, F-Pace 20d ('17).
|-
| V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 35t ('16-'17) [If 5th pos. of VIN is NOT G, H, M, or N]. Jaguar XE 35t ('17). Jaguar F-Pace 35t ('17) [If 5th pos. of VIN is NOT M or P].
|-
| V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar XF S ('16-'17). If 5th pos. of VIN is G, H, M, or N. Jaguar F-Pace S ('17) [If 5th pos. of VIN is M or P].
|}
===Engine (Position 7-8) 2018-:===
{| class="wikitable"
|+Position 7-8
! VIN Pos. 7 !! Power Level !! Transmission !! VIN Pos. 8 !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| F || 180 PS/178 hp || 8-spd. Auto. || N || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Diesel || DOHC,<br /> 16 valve||Common-rail Direct Injection. Exhaust VVT. JLR Ingenium AJ20D engine.<br> Jaguar XE 20d, XF 20d, F-Pace 20d ('18-).
|-
| E || 340 PS/335 hp || 8-spd. Auto. || V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> Jaguar XE 35t ('18-), XF 35t ('18-'19), F-Type ('18-), F-Pace 35t ('18-).
|-
| F || 380 PS/375 hp || 8-spd. Auto. || V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> Jaguar XF S ('18-'19), F-Type ('18-), F-Pace S ('18-).
|-
| G || 400 PS/395 hp || 8-spd. Auto. || V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> Jaguar F-Type 400 Sport ('18).
|-
| J || 340 PS/335 hp || 6-spd. Man. || V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> Jaguar F-Type ('18-).
|-
| K || 380 PS/375 hp || 6-spd. Man. || V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> Jaguar F-Type R-Dynamic ('18-).
|}
===Check Digit/Gearbox (Position 9)===
* USA /Canada [[Vehicle Identification Numbers (VIN codes)/Check digit|Check digit]]
===Model Year Code (Position 10)===
''See: [[Vehicle Identification Numbers (VIN codes)/Model year]]''
===Plant Codes (Position 11) 2016-===
* A - Solihull, West Midlands, England, UK (XE '17, F-Pace '17-'26, Type 01 '28-)
* C - Castle Bromwich, West Midlands, England, UK (XE '17-'20, XF '16-'24, F-Type '18-'24)
* S - Oxford Road plant, Ryton, West Midlands, England, UK (JLR SVO plant) (XE SV Project 8 '19)
* 1 - Graz, Austria (Magna Steyr plant) (E-Pace '18-'24, I-Pace EV '19-'24)
===Model (Position 12)===
* 9 - XE ('17) [Solihull plant]
* P - XE ('17-'20) [Castle Bromwich plant]
* Y - XF ('16-'24)
* K - F-Type ('18-'24)
* Z - E-Pace ('18-'20)
* 0 - E-Pace ('20-'24)
* F - I-Pace EV ('19-'20)
* 6 - I-Pace EV ('20-'24)
'''Positions 13–17, Serial Number'''
==General Template for Jaguar's VIN format (All models: 2000-2015 plus F-Type '16-'17, XJ '16-'19)==
===Jaguar WMIs (2000-) (Position 1-3)===
* SAJ - Jaguar passenger car (UK)
* SAD - Jaguar SUV (UK & Europe)
===Regional Spec/Restraint System (Position 4):===
* J = Manual seat belts, Dual front airbags (US: XK8 '00)
* B = Manual seat belts, Dual front airbags (Canada: XK8 '00)
* D = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (US: S-Type '00-'02, XJ8/XJR '00-'03, XK8/XKR '01-'06, XK/XKR Early '07)
* F = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (Canada: S-Type '00-'02, XJ8/XJR '00-'03, XK8/XKR '01-'06, XK/XKR Early '07)
* E = Manual seat belts, Depowered Dual front airbags w/occupant position sensing, & Front Side Airbags & Side Curtain Airbags (US: X-Type '02-'04, S-Type '03-'04, XJ8/XJR Early '04)
* G = Manual seat belts, Depowered Dual front airbags w/occupant position sensing, & Front Side Airbags & Side Curtain Airbags (Canada: X-Type '02-'04,<br> S-Type '03-'04, XJ8/XJR Early '04)
* W = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Airbags & Side Curtain Airbags <br> (US: X-Type '05-'08, S-Type '05-'08, XF '09-'15, XJ8/XJR '04-'09, XJ '10-)
* X = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Airbags & Side Curtain Airbags (Canada: X-Type '05-'08, S-Type '05-'08, XF '09-'15, XJ8/XJR '04-'09, XJ '10-)
* W = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Head/Thorax Airbags <br> (US: XK/XKR '07-'15, F-Type '14-)
* X = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Head/Thorax Airbags <br> (Canada: XK/XKR '07-'15, F-Type '14-)
===Transmission & Steering Location (Position 5 - '00-'12):===
* A = Automatic / LHD
* B = Manual / LHD (X-Type '02-'05, S-Type 3.0 '03-'04)
===Transmission & Drive Wheels (Position 5 - '13-):===
* A = Automatic / Rwd (XF '13-'15, XJ '13-'19, XK '13-'15, F-Type '14-'17)
* B = Manual / Rwd (F-Type '16-'17)
* J = Automatic / Awd (XF Awd '13-'15, XJ Awd '13-'19, F-Type Awd '16-'17)
===Model Line (Position 6-7)===
{| class="wikitable"
|+Position 6-7
!VIN code
!Description
|-
|51
|[[w:Jaguar X-Type|Jaguar X-Type sedan - High Series]] ('02-'08)
|-
|52
|[[w:Jaguar X-Type|Jaguar X-Type sedan - Entry Series]] ('03-'04)
|-
|53
|[[w:Jaguar X-Type|Jaguar X-Type sedan w/Sport Package]] ('02-'03)
|-
|54
|[[w:Jaguar X-Type|Jaguar X-Type Sportwagon]] ('05-'08)
|-
|01
|[[w:Jaguar S-Type (1999)|Jaguar S-Type]] ('00-'08)
|-
|03
|[[w:Jaguar S-Type (1999)|Jaguar S-Type Sport]] [3.0, 4.0] ('02)
|-
|03
|[[w:Jaguar S-Type (1999)|Jaguar S-Type Sport]] [3.0, 4.2] ('03)
|-
|03
|[[w:Jaguar S-Type (1999)|Jaguar S-Type R]] ('03-'08)
|-
|05
|[[w:Jaguar XF (X250)|Jaguar XF Luxury]] ('09)
|-
|06
|[[w:Jaguar XF (X250)|Jaguar XF Premium Luxury]] ('09)
|-
|07
|[[w:Jaguar XF (X250)|Jaguar XF Supercharged]] ('09)
|-
|0E
|[[w:Jaguar XF (X250)|Jaguar XF]] ('13-'14)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF]] ('10-'12)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF 2.0T Premium]] [8th pos. of VIN is S] ('15)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF 3.0 Sport Rwd or 3.0 Portfolio Rwd]] [8th pos. of VIN is 7] ('15)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF 3.0 Sport Awd or 3.0 Portfolio Awd]] [8th pos. of VIN is F] ('15)
|-
|0G
|[[w:Jaguar XF (X250)|Jaguar XF Premium]] ('10-'11)
|-
|0H
|[[w:Jaguar XF (X250)|Jaguar XF Portfolio]] [8th pos. of VIN is B] ('12)
|-
|0H
|[[w:Jaguar XF (X250)|Jaguar XF Supercharged]] [8th pos. of VIN is E: '10-'13 or P: '13-'15]
|-
|0J
|[[w:Jaguar XF (X250)|Jaguar XFR]] ('10-'15)
|-
|0K
|[[w:Jaguar XF (X250)|Jaguar XFR-S]] ('13-'15)
|-
|8J
|[[w:Jaguar XF (X250)|Jaguar XFR w/Speed Pack]] ('13-'15)
|-
|12
|[[w:Jaguar XJ (X308)#Sport|Jaguar XJ Sport]] ('02-'03)
|-
|14
|[[w:Jaguar XJ (X308)|Jaguar XJ8]] ('00-'03)
|-
|15
|[[w:Jaguar XJ (X308)#XJR|Jaguar XJR]] ('00-'03)
|-
|23
|[[w:Jaguar XJ (X308)|Jaguar XJ8L]] (LWB) ('00-'01)
|-
|24
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ8 Vanden Plas]] (LWB) ('00-'03)
|-
|25
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ8 Vanden Plas Supercharged]] (LWB) ('00-'01)
|-
|25
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ Super V8]] (LWB) ('02-'03)
|-
|71
|[[w:Jaguar XJ (X350)|Jaguar XJ8]] ('04-'09)
|-
|73
|[[w:Jaguar XJ (X350)|Jaguar XJR]] ('04-'09)
|-
|74
|[[w:Jaguar XJ (X350)|Jaguar XJ8 Vanden Plas]] (SWB) ('04)
|-
|79
|[[w:Jaguar XJ (X350)|Jaguar XJ8L]] (LWB) ('05-'09)
|-
|82
|[[w:Jaguar XJ (X350)|Jaguar XJ8 Vanden Plas]] (LWB) ('05-'09)
|-
|82
|[[w:Jaguar XJ (X350)|Jaguar XJ Super V8]] (LWB, 5-psgr.) ('05-'09)
|-
|86
|[[w:Jaguar XJ (X350)|Jaguar XJ Super V8 Portfolio]] (LWB, 4-psgr.) ('06)
|-
|94
|[[w:Jaguar XJ (X350)|Jaguar XJ Super V8 Portfolio]] (LWB, 5-psgr.) ('09)
|-
|1C
|[[w:Jaguar XJ (X351)|Jaguar XJ]] ('10-'15)
|-
|1C
|[[w:Jaguar XJ (X351)|Jaguar XJ R-Sport]] [8th pos. of VIN is 7 (Rwd) or D (Awd)] ('16-'19)
|-
|1C
|[[w:Jaguar XJ (X351)|Jaguar XJ Supercharged]] [8th pos. of VIN is E] ('16-'19)
|-
|1E
|[[w:Jaguar XJ (X351)|Jaguar XJR]] ('14-'17)
|-
|1G
|[[w:Jaguar XJ (X351)|Jaguar XJ Supercharged]] [8th pos. of VIN is E: '10-'13 or T: '13-'15]
|-
|1J
|[[w:Jaguar XJ (X351)|Jaguar XJ Supersport]] ('11-'12)
|-
|2E
|[[w:Jaguar XJ (X351)|Jaguar XJR LWB]] ('14-'17), XJR575 LWB ('18-'19)
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL]] [8th pos. of VIN is B] ('10-'11)
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Rwd]] [8th pos. of VIN is B: '12-'13 or 1: '13]
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Rwd]] [8th pos. of VIN is Z: '14-'15)
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Rwd]] [8th pos. of VIN is 7: '16-'19), XJ50 3.0 Rwd (LWB) '19
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Awd]] [8th pos. of VIN is D] ('13-'19), XJ50 3.0 Awd (LWB) '19
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Supercharged]] [8th pos. of VIN is E: '10-'13, '16-'19 or T: '13-'15], XJ50 5.0 Rwd (LWB) '19, XJ Collection (LWB) '19
|-
|2J
|[[w:Jaguar XJ (X351)|Jaguar XJL Supersport]] ('11-'13)
|-
|2K
|[[w:Jaguar XJ (X351)|Jaguar XJL Ultimate]] ('13)
|-
|3F
|[[w:Jaguar XJ (X351)|Jaguar XJ Supersport w/Speed Pack]] ('12-'13)
|-
|3G
|[[w:Jaguar XJ (X351)|Jaguar XJL Supersport w/Speed Pack]] ('12-'13)
|-
|3H
|[[w:Jaguar XJ (X351)|Jaguar XJ Supercharged w/Sport & Speed Pack]] ('12-'15)
|-
|3K
|[[w:Jaguar XJ (X351)|Jaguar XJL Supercharged w/Sport & Speed Pack]] ('12-'15)
|-
|41
|[[w:Jaguar XK (X100)|Jaguar XK8/XKR coupe]] ('00-'06)
|-
|42
|[[w:Jaguar XK (X100)|Jaguar XK8/XKR convertible]] ('00-'06)
|-
|43
|[[w:Jaguar XK (X150)|Jaguar XK/XKR coupe]] ('07-'09)
|-
|44
|[[w:Jaguar XK (X150)|Jaguar XK/XKR convertible]] ('07-'09)
|-
|45
|[[w:Jaguar XK (X150)|Jaguar XKR Portfolio Edition coupe]] ('09)
|-
|46
|[[w:Jaguar XK (X150)|Jaguar XKR Portfolio Edition convertible]] ('09)
|-
|4D
|[[w:Jaguar XK (X150)|Jaguar XK Touring coupe]] [8th pos. of VIN is B] ('13-'14)
|-
|4E
|[[w:Jaguar XK (X150)|Jaguar XK Touring convertible]] [8th pos. of VIN is B] ('13-'14)
|-
|4D
|[[w:Jaguar XK (X150)|Jaguar XKR coupe]] [8th pos. of VIN is C] ('10-'15)
|-
|4E
|[[w:Jaguar XK (X150)|Jaguar XKR convertible]] [8th pos. of VIN is C] ('10-'15)
|-
|4F
|[[w:Jaguar XK (X150)|Jaguar XK coupe]] (most Portfolio Edition features are std.) [8th pos. of VIN is B] ('10-'15)
|-
|4F
|[[w:Jaguar XK (X150)|Jaguar XKR175 coupe]] [8th pos. of VIN is C] ('11)
|-
|4F
|[[w:Jaguar XK (X150)|Jaguar XKR coupe w/Dynamic Pack]] [8th pos. of VIN is C] ('13-'15), XK Final Fifty Edition coupe ('15)
|-
|4G
|[[w:Jaguar XK (X150)|Jaguar XK convertible]] (most Portfolio Edition features are std.) [8th pos. of VIN is B] ('10-'15)
|-
|4G
|[[w:Jaguar XK (X150)|Jaguar XKR convertible w/Dynamic Pack]] [8th pos. of VIN is C] ('13-'15), XK Final Fifty Edition convertible ('15)
|-
|4H
|[[w:Jaguar XK (X150)|Jaguar XKR-S coupe]] ('12-'15), XKR-S GT coupe ('14)
|-
|4J
|[[w:Jaguar XK (X150)|Jaguar XKR-S convertible]] ('12-'15)
|-
|6A
|[[w:Jaguar F-Type)|Jaguar F-Type coupe]] ('15-'17), F-Type Premium coupe '17
|-
|6B
|[[w:Jaguar F-Type)|Jaguar F-Type S coupe]] ('15-'17), F-Type S British Design Edition coupe '17
|-
|6D
|[[w:Jaguar F-Type)|Jaguar F-Type R coupe]] ('15-'17)
|-
|6E
|[[w:Jaguar F-Type)|Jaguar F-Type convertible]] ('14-'17), F-Type Premium convertible '17
|-
|6F
|[[w:Jaguar F-Type)|Jaguar F-Type S convertible]] ('14-'17), F-Type S British Design Edition convertible '17
|-
|6G
|[[w:Jaguar F-Type)|Jaguar F-Type V8 S convertible]] ('14-'15)
|-
|6H
|[[w:Jaguar F-Type)|Jaguar F-Type R convertible]] ('16-'17)
|-
|6J
|[[w:Jaguar F-Type)|Jaguar F-Type SVR coupe]] ('17)
|-
|6K
|[[w:Jaguar F-Type)|Jaguar F-Type SVR convertible]] ('17)
|-
|7A
|[[w:Jaguar F-Type#Project 7)|Jaguar F-Type Project 7 convertible]] ('16)
|}
===Engine/Emissions Control System (Position 8)===
{| class="wikitable"
|+Position 8
! VIN !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| A || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. ULEV. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]].<br> Jaguar X-Type 3.0 (Mid '05-'08), S-Type 3.0 ('06-'08).
|-
| A || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. ULEV. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ34 V8 engine]]. Jaguar XF ('10).
|-
| A || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar XKR-S ('12-'15), XKR-S GT ('14), F-Type R coupe ('15).
|-
| B || 4.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. [[w:Jaguar AJ-V8 engine#Supercharged|Jaguar AJ-V8 - AJ27S V8 engine]].<br> Jaguar XJR ('00-'03), Vanden Plas Supercharged ('00-'01), Super V8 ('02-'03), XKR ('00-'02).
|-
| B || 4.2L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. [[w:Jaguar AJ-V8 engine#Supercharged_2|Jaguar AJ-V8 - AJ33S V8 engine]]. Jaguar XJR ('04-'05), Super V8 ('05), XKR ('03-'06).
|-
| B || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. ULEV. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ34 V8 engine]].<br> Jaguar S-Type ('06-'08), XF ('09), XJ8/Vanden Plas ('06-'09), XK ('07-'09).
|-
| B || 5.0L || V8 || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. Variable intake valve lift. Variable intake.<br> [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> Jaguar XF ('10-'12), XJ ('11-'12), XJL ('11), XJL Portfolio Rwd ('12-'13), XK ('10-'15), XK Touring ('13-'14).
|-
| C || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]].<br> Jaguar S-Type 3.0 ('00-'01), X-Type 3.0 ('02-Mid '05).
|-
| C || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ27 V8 engine]].<br> Jaguar XJ8/Vanden Plas ('00-'03), XJ Sport ('02-'03), XK8 ('00-'02).
|-
| C || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ33 V8 engine]]. Jaguar XJ8 ('04-'05), XK8 ('03-'06).
|-
| C || 4.2L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. ULEV. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#Supercharged_2|Jaguar AJ-V8 - AJ34S V8 engine]].<br> Jaguar S-Type R ('06-'08), XF Supercharged ('09), XJR ('06-'09), Super V8 ('06-'09), XKR ('07-'09).
|-
| C || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 510 PS/503 hp. Jaguar XFR ('10-'13), XJ/XJL Supersport ('11-'13), XKR ('10-'15).
|-
| C || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar F-Type S ('14-'15), F-Type S w/man. trans. ('16-'17).
|-
| D || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ28 V8 engine]]. Jaguar S-Type 4.0 ('00-'01).
|-
| D || 2.5L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ25|Jaguar AJ-V6 - AJ25 V6 engine]]. Jaguar X-Type 2.5 ('02-'05).
|-
| D || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XJ Awd, XJL Portfolio Awd ('13-'15).
|-
| D || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XJ R-Sport Awd, XJL Portfolio Awd ('16-'19), XJ50 3.0 Awd ('19).
|-
| E || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 470 PS/464 hp.<br> Jaguar XF Supercharged ('10-'13), XJ/XJL Supercharged ('11-'13, '16-'19), XJ50 5.0 Rwd ('19), XJ Collection ('19).
|-
| F || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Awd ('13-'14).
|-
| F || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Awd ('15).
|-
| H || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. 510 PS/503 hp. Jaguar XFR ('13-'15).
|-
| K || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar XJR/XJR LWB ('14-'17).
|-
| K || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 575 PS/567 hp. Jaguar XJR575 LWB ('18-'19).
|-
| L || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 495 PS/488 hp. Jaguar F-Type V8 S convertible ('14-'15).
|-
| L || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar F-Type R ('16-'17).
|-
| N || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]]. Jaguar S-Type 3.0 ('01-'02).
|-
| P || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ28 V8 engine]]. Jaguar S-Type 4.0 ('01-'02).
|-
| P || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. 470 PS/464 hp. Jaguar XF Supercharged ('13-'15).
|-
| S || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Gas || DOHC,<br /> 16 valve||Direct Injection. Dual VVT. Ford EcoBoost engine (Mazda L engine-based).<br> Jaguar XF 2.0T ('13-'14), XF 2.0T Premium ('15).
|-
| T || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]]. Jaguar S-Type 3.0 ('03-'05).
|-
| T || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. 470 PS/464 hp. Jaguar XJ/XJL Supercharged ('13-'15).
|-
| T || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar F-Type w/auto. trans. ('15-'17), F-Type Premium w/auto. trans. ('17).
|-
| U || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ33 V8 engine]]. Jaguar S-Type 4.2 ('03-'05).
|-
| U || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar F-Type S ('15), F-Type S Rwd w/auto. trans. ('16-'17).
|-
| V || 4.2L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. [[w:Jaguar AJ-V8 engine#Supercharged_2|Jaguar AJ-V8 - AJ33S V8 engine]]. Jaguar S-Type R ('03-'05).
|-
| V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar F-Type S Awd w/auto. trans. ('16-'17).
|-
| X || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 24 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Rwd ('14).
|-
| Z || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar XFR-S ('13-'15).
|-
| Z || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 24 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XJ Rwd, XJL Portfolio Rwd ('14-'15).
|-
| 1 || 5.0L || V8 || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. Variable intake valve lift. Variable intake. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. Jaguar XJL Portfolio Rwd ('13).
|-
| 6 || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar F-Type w/man. trans. ('16-'17), F-Type Premium w/man. trans. ('17).
|-
| 7 || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Rwd ('13), XJ Rwd ('13), F-Type ('14-'15).
|-
| 7 || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Rwd ('15), XJ R-Sport Rwd ('16-'19), XJL Portfolio Rwd ('16-'19), XJ50 3.0 Rwd ('19).
|-
| 8 || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 575 PS/567 hp. Jaguar F-Type Project 7 ('16), F-Type SVR ('17).
|}
===Check Digit/Gearbox (Position 9)===
* USA /Canada [[Vehicle Identification Numbers (VIN codes)/Check digit|Check digit]]
===Model Year Code (Position 10)===
''See: [[Vehicle Identification Numbers (VIN codes)/Model year]]''
===Plant Code/Model Line/Engine (Position 11) 2000-2019===
* X - Halewood, Merseyside, England, UK - X-Type 2.5 ('02-'05)
* W - Halewood, Merseyside, England, UK - X-Type 3.0 ('02-'08)
* F - Castle Bromwich, West Midlands, England, UK - S-Type 3.0 ('00-'08)
* G - Castle Bromwich, West Midlands, England, UK - S-Type 4.0 ('00-'02)
* H - Castle Bromwich, West Midlands, England, UK - S-Type 4.2 ('03-'08)
* 1 - Castle Bromwich, West Midlands, England, UK - S-Type R (4.2 supercharged) ('03-'08)
* H - Castle Bromwich, West Midlands, England, UK - XF 4.2 ('09-'10)
* 1 - Castle Bromwich, West Midlands, England, UK - XF Supercharged (4.2 supercharged) ('09)
* L - Castle Bromwich, West Midlands, England, UK - XF 5.0 ('10-'12)
* M - Castle Bromwich, West Midlands, England, UK - XF Supercharged, XFR (5.0 supercharged) ('10-'15), XFR-S (5.0 supercharged) ('13-'15)
* P - Castle Bromwich, West Midlands, England, UK - XF 2.0T ('13-'15)
* 8 - Castle Bromwich, West Midlands, England, UK - XF 3.0 supercharged ('13-'15)
* L - Browns Lane plant, Coventry, West Midlands, England, UK - XJ8 (4.0) ('00-'03), XJ8L (4.0) ('00-'01), XJ8 Vanden Plas (4.0) ('00-'03), XJ Sport (4.0) ('02-'03)
* M - Browns Lane plant, Coventry, West Midlands, England, UK - XJ8 Vanden Plas Supercharged (4.0 supercharged) ('00-'01),<br> Super V8 (4.0 supercharged) ('02-'03), XJR (4.0 supercharged) ('00-'03)
* S - Browns Lane plant, Coventry, West Midlands, England, UK - XJ8 (4.2) ('04-'06), XJ8L (4.2) ('05-'06), XJ8 Vanden Plas (4.0) ('04-'06)
* T - Browns Lane plant, Coventry, West Midlands, England, UK - Super V8 (4.2 supercharged) ('05-'06), Super V8 Portfolio (4.2 supercharged) ('06),<br> XJR (4.2 supercharged) ('04-'06)
* S - Castle Bromwich, West Midlands, England, UK - XJ8 (4.2) ('07-'09), XJ8L (4.2) ('07-'09), XJ8 Vanden Plas (4.0) ('07-'09)
* T - Castle Bromwich, West Midlands, England, UK - Super V8 (4.2 supercharged) ('07-'09), Super V8 Portfolio (4.2 supercharged) ('09),<br> XJR (4.2 supercharged) ('07-'09)
* L - Castle Bromwich, West Midlands, England, UK - XJ (5.0) ('10-'12), XJL (5.0) ('10-'11), XJL Portfolio (5.0) ('12-'13)
* M - Castle Bromwich, West Midlands, England, UK - XJ/XJL Supercharged (5.0 supercharged) ('10-'19), XJ/XJL Supersport (5.0 supercharged) ('11-'13),<br> XJL Ultimate (5.0 supercharged) ('13), XJR SWB/LWB (5.0 supercharged) ('14-'17), XJR575 LWB (5.0 supercharged) ('18-'19), XJ50 LWB (5.0 supercharged) ('19), XJ Collection Sp. Ed. LWB (5.0 supercharged) ('19)
* 8 - Castle Bromwich, West Midlands, England, UK - XJ base (3.0 supercharged) ('13-'15), XJ R-Sport (3.0 supercharged) ('16-'19),<br> XJL Portfolio AWD (3.0 supercharged) ('13-'19), XJL Portfolio RWD (3.0 supercharged) ('14-'19), XJ50 LWB (3.0 supercharged) ('19)
* N - Browns Lane plant, Coventry, West Midlands, England, UK - XK8 (4.0) ('00-'02)
* P - Browns Lane plant, Coventry, West Midlands, England, UK - XKR (4.0 supercharged) ('00-'02)
* 2 - Browns Lane plant, Coventry, West Midlands, England, UK - XK8 (4.2) ('03-'06)
* 3 - Browns Lane plant, Coventry, West Midlands, England, UK - XKR (4.2 supercharged) ('03-'06)
* 5 - Castle Bromwich, West Midlands, England, UK - XK (4.2) ('07-'09)
* 9 - Castle Bromwich, West Midlands, England, UK - XKR (4.2 supercharged) ('07-'09)
* L - Castle Bromwich, West Midlands, England, UK - XK (5.0) ('10-'15)
* M - Castle Bromwich, West Midlands, England, UK - XKR (5.0 supercharged) ('10-'15), XKR-S (5.0 supercharged) ('12-'15), XKR-S GT (5.0 supercharged) ('14)
* 8 - Castle Bromwich, West Midlands, England, UK - F-Type Base, S (3.0 supercharged) ('14-'17), F-Type Premium (3.0 supercharged) ('17)
* M - Castle Bromwich, West Midlands, England, UK - F-Type V8S (5.0 supercharged) ('14-'15), F-Type R (5.0 supercharged) ('15-'17),<br> F-Type Project 7 (5.0 supercharged) ('16), F-Type SVR (5.0 supercharged) ('17)
===Model (Position 12)===
* C - X-Type ('02-'03)
* D - X-Type ('03-'04)
* E - X-Type ('04-'06)
* J - X-Type ('06-'08)
* L - S-Type ('00-'01)
* M - S-Type ('01-'04)
* N - S-Type ('04-'08)
* R - XF ('09-'11)
* S - XF ('11-'13)
* U - XF ('13-'15)
* F - XJ ('00-'03)
* G - XJ ('04-'06) [Browns Lane plant]
* H - XJ ('06-'09) [Castle Bromwich plant]
* V - XJ ('10-'16)
* W - XJ ('16-'19)
* A - XK ('00-'06)
* B - XK ('07-'15)
* K - F-Type ('14-'17)
'''Positions 13–17, Serial Number'''
==General Template for Jaguar's VIN format (1981 - 1999)==
===Jaguar WMIs (1981-1999) (Position 1-3)===
* SAJ - Jaguar passenger car
===Model Line (Position 4)===
{| class="wikitable"
|+Position 4
!VIN code
!Description
|-
|A
|[[w:Jaguar XJ#Series 3 (1979–1992)|Jaguar XJ6]] ('81-'87), XJ6 Vanden Plas ('82-'87)
|-
|B
|[[w:Jaguar XJ#Series 3 (1979–1992)|Jaguar XJ12]] (Canada only: '81-'88)
|-
|D
|[[w:Jaguar XJ#Series 3 (1979–1992)|Jaguar XJ12]] (Canada only: '89-'92)
|-
|H
|[[w:Jaguar XJ (XJ40)|Jaguar XJ6]] ('88-'89, '93-'94)
|-
|F
|[[w:Jaguar XJ (XJ40)|Jaguar XJ6]] ('90-'92)
|-
|H
|[[w:Jaguar XJ (XJ40)|Jaguar XJ6 Sovereign]] ('90-'92)
|-
|K
|[[w:Jaguar XJ (XJ40)#Daimler/Vanden Plas|Jaguar XJ6 Vanden Plas]] ('88-'94)
|-
|M
|[[w:Jaguar XJ (XJ40)#Majestic (1989–1992 – SWB; 1993–1994 – LWB)|Jaguar XJ6 Vanden Plas Majestic]] ('89-'90, '92)
|-
|M
|[[w:Jaguar XJ (XJ40)#XJ12 and Daimler Double Six (XJ81)|Jaguar XJ12]] ('94)
|-
|H
|[[w:Jaguar XJ (X300)|Jaguar XJ6]] ('95-'97)
|-
|H
|[[w:Jaguar XJ (X300)|Jaguar XJ6L]] LWB [X330] ('97)
|-
|K
|[[w:Jaguar XJ (X300)#Daimler/Jaguar Vanden Plas|Jaguar XJ6 Vanden Plas]] SWB ('95)
|-
|K
|[[w:Jaguar XJ (X300)#Daimler/Jaguar Vanden Plas|Jaguar XJ6 Vanden Plas]] LWB [X330] ('96-'97)
|-
|M
|[[w:Jaguar XJ (X300)#XJ12 (X305)|Jaguar XJ12]] SWB ('95)
|-
|M
|[[w:Jaguar XJ (X300)#XJ12 (X305)|Jaguar XJ12]] LWB [X330] ('96)
|-
|P
|[[w:Jaguar XJ (X300)#XJR (X306)|Jaguar XJR]] ('95-'97)
|-
|H
|[[w:Jaguar XJ (X308)|Jaguar XJ8]] ('98-'99)
|-
|H
|[[w:Jaguar XJ (X308)|Jaguar XJ8L]] LWB ('98-'99)
|-
|K
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ8 Vanden Plas]] LWB ('98-'99)
|-
|P
|[[w:Jaguar XJ (X308)#XJR|Jaguar XJR]] ('98-'99)
|-
|N
|[[w:Jaguar XJS|Jaguar XJ-S]] ('82-'91), XJ-SC ('86-'88), XJS ('92-'96)
|-
|T
|[[w:Jaguar XJS|Jaguar XJ-S]] Rouge Collection ('89-'90), Classic Collection ('90-'91)
|-
|S
|[[w:Jaguar XJS#XJR-S|Jaguar XJR-S]] ('93)
|-
|G
|[[w:Jaguar XK (X100)|Jaguar XK8]] ('97-'99)
|}
===Class (Regional Spec)/Restraint System (Position 5):===
* V = N. American-spec (Manual seat belts)
* L = Canadian-spec (Manual seat belts)
* Y = XJ6 Vanden Plas [Series III] ('82-'87) (Manual seat belts)
* A = Motorized Shoulder Belts (XJ-S coupe '88-'89, XJ-SC '88)
* Y = Motorized Shoulder Belts (XJ-S coupe '89, XJ sedan '89-'92)
* W = Manual seat belts, Driver-side airbag (US: XJ-S '90-'93, XJ6 '93, XJ12 Early '94)
* X = Manual seat belts, Dual front airbags (US: XJS '94-'96, XJ6 '94-'97, XJ12 '94-'96, XJR '95-'97, XK8 '97-'99)
* X = Manual seat belts, Dual front airbags, & Front Side Airbags (US: XJ8/XJR '98-'99)
* D = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (US: XJ8/XJR '99)
* M = Manual seat belts, Driver-side airbag (Canada)
* N = Manual seat belts, Dual front airbags (Canada)
* F = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (Canada: XJ8/XJR '99)
===Body Style (Position 6):===
* 1 = 4-door sedan (XJ-series sedan '81-'99)
* 2 = 2-door convertible w/2+2 seating (XJS convertible '94-'96, XK8 convertible '97-'99)
* 3 = 2-door Cabriolet (XJ-SC '86-'88)
* 4 = 2-door convertible w/2-psgr. seating (factory-built XJS convertible '89-'94, XJR-S convertible '93)
* 5 = 2-door coupe (XJS coupe '82-'96, XJR-S coupe '93, XK8 coupe '97-'99)
* 5 = 2-door coupe (Hess & Eisenhardt-built XJS convertible '87-'88) [coupe conversion]
===Engine Type (Position 7):===
{| class="wikitable"
|+Position 7
|-
! VIN !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| 1 || 4.0L || I6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||MPI. [[w:Jaguar AJ6 engine#AJ16S|Jaguar AJ16S I6]]. Jaguar XJR ('95-'97).
|-
| 2 || 4.2L || I6 || Gas ||DOHC,<br /> 12 valve||CA & Canada-spec. MPI. [[w:Jaguar XK engine|Jaguar XK I6]]. Jaguar XJ6 ('81-'82).
|-
| 2 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||MPI. Dual-canister evaporative emissions system. [[w:Jaguar AJ6 engine#AJ16|Jaguar AJ16 I6]]. Jaguar XJ6 ('96-'97).
|-
| 2 || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Variable intake valve timing. Dual-canister evaporative emissions system. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ26 V8 engine]].<br> Jaguar XJ8 ('98), XK8 ('98).
|-
| 3 || 4.2L || I6 || Gas ||DOHC,<br /> 12 valve||N. America-spec. MPI. [[w:Jaguar XK engine|Jaguar XK I6]]. Jaguar XJ6 ('81-'87).
|-
| 3 || 6.0L || 60° V12 || Gas ||SOHC,<br /> 24 valve||MPI. [[w:Jaguar V12 engine|Jaguar V12]] modified by [[w:Tom Walkinshaw Racing|JaguarSport]]. Jaguar XJR-S ('93).
|-
| 3 || 6.0L || 60° V12 || Gas ||SOHC,<br /> 24 valve||MPI. [[w:Jaguar V12 engine|Jaguar V12]]. Jaguar XJS ('94-'95), XJ12 ('94-'96).
|-
| 5 || 3.6L || I6 || Gas ||DOHC,<br /> 24 valve||N. America-spec - Low Compression. MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('88-'89).
|-
| 6 || 3.6L || I6 || Gas ||DOHC,<br /> 24 valve||N. America-spec - High Compression. MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('88).
|-
| 7 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('90-'94), XJS ('93-'94).
|-
| 7 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||MPI. [[w:Jaguar AJ6 engine#AJ16|Jaguar AJ16 I6]]. Jaguar XJ6 ('95-'96), XJS ('95-'96).
|-
| 7 || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ26 V8 engine]]. Jaguar XK8 ('97).
|-
| 8 || 5.3L || 60° V12 || Gas ||SOHC,<br /> 24 valve||N. America-spec. MPI. [[w:Jaguar V12 engine|Jaguar V12]]. Jaguar XJ-S ('82-'92), XJ12 (Canada only: '88-'92).
|-
| 8 || 4.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. Dual-canister evaporative emissions system. [[w:Jaguar AJ-V8 engine#Supercharged|Jaguar AJ-V8 - AJ26S V8 engine]]. Jaguar XJR ('98-'99).
|-
| 9 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||Canada-spec. MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('90-'93), XJS ('93).
|-
| 0 || 5.3L || 60° V12 || Gas ||SOHC,<br /> 24 valve||Canada-spec. MPI. [[w:Jaguar V12 engine|Jaguar V12]]. Jaguar XJ-S ('82-'87), XJ12 (Canada only: '85-'87).
|-
| 0 || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. Dual-canister evaporative emissions system. Enhanced evaporative emissions control system. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ27 V8 engine]]. Jaguar XJ8 ('99), XK8 ('99).
|}
===Transmission & Steering Location (Position 8):===
* 4 = Automatic / LHD
* 8 = Manual / LHD ('93-'94 XJS 4.0 w/ optional 5-spd. manual)
===Check Digit/Gearbox (Position 9)===
* USA /Canada [[Vehicle Identification Numbers (VIN codes)/Check digit|Check digit]]
===Model Year Code (Position 10)===
''See: [[Vehicle Identification Numbers (VIN codes)/Model year]]''
===Plant Codes (Position 11)===
* C - Browns Lane plant, Coventry, West Midlands, England, UK
===Positions 12–17, Serial Number===
** 100001 and after - XJ-S/XJ-SC/XJS/XJR-S (XJ27)
** 300001 and after - XJ-series sedan Series III
** 500001 and after - XJ-series sedan (XJ40/XJ81)
** 720001 and after - XJ-series sedan (X300/X305/X306/X330)
** 810001 and after - XJ-series sedan (X308)
** 001001 and after - XK8 (X100)
cbpzsefvsnhe107ehbmaph9abod5zj7
4676025
4675953
2026-10-14T11:45:59Z
JustTheFacts33
3434282
/* Engine (Position 7-8) 2018-: */
4676025
wikitext
text/x-wiki
{{Vehicle Identification Numbers (VIN codes)/Warning}}{{clear}}
This VIN number decoding and designation system is used primarily for the North American Market. European and Asian markets use other decoding and designation systems.
==General Template for Jaguar's VIN format (All models: 2016- EXCEPT F-Type '16-'17, XJ '16-'19)==
===Jaguar WMIs (2016-) (Position 1-3)===
* SAJ - Jaguar passenger car (UK)
* SAD - Jaguar SUV (UK & Europe)
* L2C - Chery Jaguar Land Rover (China)
===Model Line (Position 4)===
{| class="wikitable"
|+Position 4
!VIN code
!Description
|-
|A
|[[w:Jaguar XE|Jaguar XE]] ('17-'20)
|-
|B
|[[w:Jaguar XF (X260)|Jaguar XF]] ('16-'24)
|-
|C
|[[w:Jaguar F-Pace|Jaguar F-Pace]] ('17-'26)
|-
|D
|[[w:Jaguar F-Type|Jaguar F-Type]] ('18-'24)
|-
|E
|[[w:Jaguar Type 01|Jaguar Type 01]] ('28-)
|-
|F
|[[w:Jaguar E-Pace|Jaguar E-Pace]] ('18-'24)
|-
|H
|[[w:Jaguar I-Pace|Jaguar I-Pace EV]] ('19-'24)
|}
===Body Style (Position 6):===
* 1 = Coupe (F-Type coupe)
* 2 = 5-door wagon (XF Sportbrake wagon)
* 2 = 5-door (E-Pace, F-Pace, I-Pace EV)
* 4 = 4-door sedan (XE, XF sedan, Type 01)
* 5 = Convertible (F-Type convertible)
===Transmission (Position 7) 2016-2017:===
* B = Automatic (XE '17, XF '16-'17, F-Pace '17)
===Engine/Emissions Control System (Position 8) 2016-2017:===
{| class="wikitable"
|+Position 8
! VIN !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| G || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Gas || DOHC,<br /> 16 valve||Direct Injection. ULEV. Dual VVT. Ford EcoBoost engine (Mazda L engine-based).<br> Jaguar XE 25t ('17).
|-
| N || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Diesel || DOHC,<br /> 16 valve||Common-rail Direct Injection. Exhaust VVT. JLR Ingenium AJ20D engine. Jaguar XE 20d, XF 20d, F-Pace 20d ('17).
|-
| V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 35t ('16-'17) [If 5th pos. of VIN is NOT G, H, M, or N]. Jaguar XE 35t ('17). Jaguar F-Pace 35t ('17) [If 5th pos. of VIN is NOT M or P].
|-
| V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar XF S ('16-'17). If 5th pos. of VIN is G, H, M, or N. Jaguar F-Pace S ('17) [If 5th pos. of VIN is M or P].
|}
===Engine (Position 7-8) 2018-:===
{| class="wikitable"
|+Position 7-8
! VIN Pos. 7 !! Power Level !! Transmission !! VIN Pos. 8 !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| E || 550 PS/542 hp || 8-spd. Auto. || E || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct injection. Dual Continuously VCT (VVT). Jaguar AJ133S engine. Jaguar F-Type R ('18-), F-Pace SVR ('19-).
|-
| F || 575 PS/567 hp || 8-spd. Auto. || E || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct injection. Dual Continuously VCT (VVT). Jaguar AJ133S engine. Jaguar F-Type SVR ('18-).
|-
| F || 600 PS/592 hp || 8-spd. Auto. || E || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct injection. Dual Continuously VCT (VVT). Jaguar AJ133S engine. Jaguar XE SV Project 8 ('19).
|-
| F || 180 PS/178 hp || 8-spd. Auto. || N || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Diesel || DOHC,<br /> 16 valve||Common-rail Direct Injection. Exhaust VVT. JLR Ingenium AJ20D4/AJ200D engine.<br> Jaguar XE 20d, XF 20d, F-Pace 20d ('18-).
|-
| E || 340 PS/335 hp || 8-spd. Auto. || V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> Jaguar XE 35t ('18), XF 35t ('18), F-Type ('18), F-Type P340 ('19), F-Pace 35t ('18).
|-
| F || 380 PS/375 hp || 8-spd. Auto. || V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> Jaguar XE S ('18), XF S ('18-'19), F-Type ('18), F-Type P380, R-Dynamic ('19), F-Pace S ('18-).
|-
| G || 400 PS/395 hp || 8-spd. Auto. || V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> Jaguar F-Type 400 Sport ('18).
|-
| J || 340 PS/335 hp || 6-spd. Man. || V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> Jaguar F-Type ('18-).
|-
| K || 380 PS/375 hp || 6-spd. Man. || V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> Jaguar F-Type R-Dynamic ('18-).
|-
| F || 250 PS/247 hp || 8-spd. Auto. || | X || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Gas || DOHC,<br /> 16 valve||Direct Injection. Dual VVT. CVVL (Intake VVL). JLR Ingenium AJ20P4/AJ200P engine.<br> Jaguar XE 25t ('18-), XF 25t ('18-), E-Pace ('18-), F-Pace 25t ('18-).
|-
| G || 300 PS/296 hp || 8-spd. Auto. || | X || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Gas || DOHC,<br /> 16 valve||Direct Injection. Dual VVT. CVVL (Intake VVL). JLR Ingenium AJ20P4/AJ200P engine.<br> Jaguar XE 30t ('18-), XF 30t ('18-), F-Type ('18-), E-Pace R-Dynamic ('18-), F-Pace 30t ('18-).
|}
===Check Digit/Gearbox (Position 9)===
* USA /Canada [[Vehicle Identification Numbers (VIN codes)/Check digit|Check digit]]
===Model Year Code (Position 10)===
''See: [[Vehicle Identification Numbers (VIN codes)/Model year]]''
===Plant Codes (Position 11) 2016-===
* A - Solihull, West Midlands, England, UK (XE '17, F-Pace '17-'26, Type 01 '28-)
* C - Castle Bromwich, West Midlands, England, UK (XE '17-'20, XF '16-'24, F-Type '18-'24)
* S - Oxford Road plant, Ryton, West Midlands, England, UK (JLR SVO plant) (XE SV Project 8 '19)
* 1 - Graz, Austria (Magna Steyr plant) (E-Pace '18-'24, I-Pace EV '19-'24)
===Model (Position 12)===
* 9 - XE ('17) [Solihull plant]
* P - XE ('17-'20) [Castle Bromwich plant]
* Y - XF ('16-'24)
* K - F-Type ('18-'24)
* Z - E-Pace ('18-'20)
* 0 - E-Pace ('20-'24)
* F - I-Pace EV ('19-'20)
* 6 - I-Pace EV ('20-'24)
'''Positions 13–17, Serial Number'''
==General Template for Jaguar's VIN format (All models: 2000-2015 plus F-Type '16-'17, XJ '16-'19)==
===Jaguar WMIs (2000-) (Position 1-3)===
* SAJ - Jaguar passenger car (UK)
* SAD - Jaguar SUV (UK & Europe)
===Regional Spec/Restraint System (Position 4):===
* J = Manual seat belts, Dual front airbags (US: XK8 '00)
* B = Manual seat belts, Dual front airbags (Canada: XK8 '00)
* D = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (US: S-Type '00-'02, XJ8/XJR '00-'03, XK8/XKR '01-'06, XK/XKR Early '07)
* F = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (Canada: S-Type '00-'02, XJ8/XJR '00-'03, XK8/XKR '01-'06, XK/XKR Early '07)
* E = Manual seat belts, Depowered Dual front airbags w/occupant position sensing, & Front Side Airbags & Side Curtain Airbags (US: X-Type '02-'04, S-Type '03-'04, XJ8/XJR Early '04)
* G = Manual seat belts, Depowered Dual front airbags w/occupant position sensing, & Front Side Airbags & Side Curtain Airbags (Canada: X-Type '02-'04,<br> S-Type '03-'04, XJ8/XJR Early '04)
* W = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Airbags & Side Curtain Airbags <br> (US: X-Type '05-'08, S-Type '05-'08, XF '09-'15, XJ8/XJR '04-'09, XJ '10-)
* X = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Airbags & Side Curtain Airbags (Canada: X-Type '05-'08, S-Type '05-'08, XF '09-'15, XJ8/XJR '04-'09, XJ '10-)
* W = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Head/Thorax Airbags <br> (US: XK/XKR '07-'15, F-Type '14-)
* X = Manual seat belts, Depowered Dual front airbags w/occupant position (driver) and weight (fr. psgr.) sensing, & Front Side Head/Thorax Airbags <br> (Canada: XK/XKR '07-'15, F-Type '14-)
===Transmission & Steering Location (Position 5 - '00-'12):===
* A = Automatic / LHD
* B = Manual / LHD (X-Type '02-'05, S-Type 3.0 '03-'04)
===Transmission & Drive Wheels (Position 5 - '13-):===
* A = Automatic / Rwd (XF '13-'15, XJ '13-'19, XK '13-'15, F-Type '14-'17)
* B = Manual / Rwd (F-Type '16-'17)
* J = Automatic / Awd (XF Awd '13-'15, XJ Awd '13-'19, F-Type Awd '16-'17)
===Model Line (Position 6-7)===
{| class="wikitable"
|+Position 6-7
!VIN code
!Description
|-
|51
|[[w:Jaguar X-Type|Jaguar X-Type sedan - High Series]] ('02-'08)
|-
|52
|[[w:Jaguar X-Type|Jaguar X-Type sedan - Entry Series]] ('03-'04)
|-
|53
|[[w:Jaguar X-Type|Jaguar X-Type sedan w/Sport Package]] ('02-'03)
|-
|54
|[[w:Jaguar X-Type|Jaguar X-Type Sportwagon]] ('05-'08)
|-
|01
|[[w:Jaguar S-Type (1999)|Jaguar S-Type]] ('00-'08)
|-
|03
|[[w:Jaguar S-Type (1999)|Jaguar S-Type Sport]] [3.0, 4.0] ('02)
|-
|03
|[[w:Jaguar S-Type (1999)|Jaguar S-Type Sport]] [3.0, 4.2] ('03)
|-
|03
|[[w:Jaguar S-Type (1999)|Jaguar S-Type R]] ('03-'08)
|-
|05
|[[w:Jaguar XF (X250)|Jaguar XF Luxury]] ('09)
|-
|06
|[[w:Jaguar XF (X250)|Jaguar XF Premium Luxury]] ('09)
|-
|07
|[[w:Jaguar XF (X250)|Jaguar XF Supercharged]] ('09)
|-
|0E
|[[w:Jaguar XF (X250)|Jaguar XF]] ('13-'14)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF]] ('10-'12)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF 2.0T Premium]] [8th pos. of VIN is S] ('15)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF 3.0 Sport Rwd or 3.0 Portfolio Rwd]] [8th pos. of VIN is 7] ('15)
|-
|0F
|[[w:Jaguar XF (X250)|Jaguar XF 3.0 Sport Awd or 3.0 Portfolio Awd]] [8th pos. of VIN is F] ('15)
|-
|0G
|[[w:Jaguar XF (X250)|Jaguar XF Premium]] ('10-'11)
|-
|0H
|[[w:Jaguar XF (X250)|Jaguar XF Portfolio]] [8th pos. of VIN is B] ('12)
|-
|0H
|[[w:Jaguar XF (X250)|Jaguar XF Supercharged]] [8th pos. of VIN is E: '10-'13 or P: '13-'15]
|-
|0J
|[[w:Jaguar XF (X250)|Jaguar XFR]] ('10-'15)
|-
|0K
|[[w:Jaguar XF (X250)|Jaguar XFR-S]] ('13-'15)
|-
|8J
|[[w:Jaguar XF (X250)|Jaguar XFR w/Speed Pack]] ('13-'15)
|-
|12
|[[w:Jaguar XJ (X308)#Sport|Jaguar XJ Sport]] ('02-'03)
|-
|14
|[[w:Jaguar XJ (X308)|Jaguar XJ8]] ('00-'03)
|-
|15
|[[w:Jaguar XJ (X308)#XJR|Jaguar XJR]] ('00-'03)
|-
|23
|[[w:Jaguar XJ (X308)|Jaguar XJ8L]] (LWB) ('00-'01)
|-
|24
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ8 Vanden Plas]] (LWB) ('00-'03)
|-
|25
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ8 Vanden Plas Supercharged]] (LWB) ('00-'01)
|-
|25
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ Super V8]] (LWB) ('02-'03)
|-
|71
|[[w:Jaguar XJ (X350)|Jaguar XJ8]] ('04-'09)
|-
|73
|[[w:Jaguar XJ (X350)|Jaguar XJR]] ('04-'09)
|-
|74
|[[w:Jaguar XJ (X350)|Jaguar XJ8 Vanden Plas]] (SWB) ('04)
|-
|79
|[[w:Jaguar XJ (X350)|Jaguar XJ8L]] (LWB) ('05-'09)
|-
|82
|[[w:Jaguar XJ (X350)|Jaguar XJ8 Vanden Plas]] (LWB) ('05-'09)
|-
|82
|[[w:Jaguar XJ (X350)|Jaguar XJ Super V8]] (LWB, 5-psgr.) ('05-'09)
|-
|86
|[[w:Jaguar XJ (X350)|Jaguar XJ Super V8 Portfolio]] (LWB, 4-psgr.) ('06)
|-
|94
|[[w:Jaguar XJ (X350)|Jaguar XJ Super V8 Portfolio]] (LWB, 5-psgr.) ('09)
|-
|1C
|[[w:Jaguar XJ (X351)|Jaguar XJ]] ('10-'15)
|-
|1C
|[[w:Jaguar XJ (X351)|Jaguar XJ R-Sport]] [8th pos. of VIN is 7 (Rwd) or D (Awd)] ('16-'19)
|-
|1C
|[[w:Jaguar XJ (X351)|Jaguar XJ Supercharged]] [8th pos. of VIN is E] ('16-'19)
|-
|1E
|[[w:Jaguar XJ (X351)|Jaguar XJR]] ('14-'17)
|-
|1G
|[[w:Jaguar XJ (X351)|Jaguar XJ Supercharged]] [8th pos. of VIN is E: '10-'13 or T: '13-'15]
|-
|1J
|[[w:Jaguar XJ (X351)|Jaguar XJ Supersport]] ('11-'12)
|-
|2E
|[[w:Jaguar XJ (X351)|Jaguar XJR LWB]] ('14-'17), XJR575 LWB ('18-'19)
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL]] [8th pos. of VIN is B] ('10-'11)
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Rwd]] [8th pos. of VIN is B: '12-'13 or 1: '13]
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Rwd]] [8th pos. of VIN is Z: '14-'15)
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Rwd]] [8th pos. of VIN is 7: '16-'19), XJ50 3.0 Rwd (LWB) '19
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Portfolio Awd]] [8th pos. of VIN is D] ('13-'19), XJ50 3.0 Awd (LWB) '19
|-
|2G
|[[w:Jaguar XJ (X351)|Jaguar XJL Supercharged]] [8th pos. of VIN is E: '10-'13, '16-'19 or T: '13-'15], XJ50 5.0 Rwd (LWB) '19, XJ Collection (LWB) '19
|-
|2J
|[[w:Jaguar XJ (X351)|Jaguar XJL Supersport]] ('11-'13)
|-
|2K
|[[w:Jaguar XJ (X351)|Jaguar XJL Ultimate]] ('13)
|-
|3F
|[[w:Jaguar XJ (X351)|Jaguar XJ Supersport w/Speed Pack]] ('12-'13)
|-
|3G
|[[w:Jaguar XJ (X351)|Jaguar XJL Supersport w/Speed Pack]] ('12-'13)
|-
|3H
|[[w:Jaguar XJ (X351)|Jaguar XJ Supercharged w/Sport & Speed Pack]] ('12-'15)
|-
|3K
|[[w:Jaguar XJ (X351)|Jaguar XJL Supercharged w/Sport & Speed Pack]] ('12-'15)
|-
|41
|[[w:Jaguar XK (X100)|Jaguar XK8/XKR coupe]] ('00-'06)
|-
|42
|[[w:Jaguar XK (X100)|Jaguar XK8/XKR convertible]] ('00-'06)
|-
|43
|[[w:Jaguar XK (X150)|Jaguar XK/XKR coupe]] ('07-'09)
|-
|44
|[[w:Jaguar XK (X150)|Jaguar XK/XKR convertible]] ('07-'09)
|-
|45
|[[w:Jaguar XK (X150)|Jaguar XKR Portfolio Edition coupe]] ('09)
|-
|46
|[[w:Jaguar XK (X150)|Jaguar XKR Portfolio Edition convertible]] ('09)
|-
|4D
|[[w:Jaguar XK (X150)|Jaguar XK Touring coupe]] [8th pos. of VIN is B] ('13-'14)
|-
|4E
|[[w:Jaguar XK (X150)|Jaguar XK Touring convertible]] [8th pos. of VIN is B] ('13-'14)
|-
|4D
|[[w:Jaguar XK (X150)|Jaguar XKR coupe]] [8th pos. of VIN is C] ('10-'15)
|-
|4E
|[[w:Jaguar XK (X150)|Jaguar XKR convertible]] [8th pos. of VIN is C] ('10-'15)
|-
|4F
|[[w:Jaguar XK (X150)|Jaguar XK coupe]] (most Portfolio Edition features are std.) [8th pos. of VIN is B] ('10-'15)
|-
|4F
|[[w:Jaguar XK (X150)|Jaguar XKR175 coupe]] [8th pos. of VIN is C] ('11)
|-
|4F
|[[w:Jaguar XK (X150)|Jaguar XKR coupe w/Dynamic Pack]] [8th pos. of VIN is C] ('13-'15), XK Final Fifty Edition coupe ('15)
|-
|4G
|[[w:Jaguar XK (X150)|Jaguar XK convertible]] (most Portfolio Edition features are std.) [8th pos. of VIN is B] ('10-'15)
|-
|4G
|[[w:Jaguar XK (X150)|Jaguar XKR convertible w/Dynamic Pack]] [8th pos. of VIN is C] ('13-'15), XK Final Fifty Edition convertible ('15)
|-
|4H
|[[w:Jaguar XK (X150)|Jaguar XKR-S coupe]] ('12-'15), XKR-S GT coupe ('14)
|-
|4J
|[[w:Jaguar XK (X150)|Jaguar XKR-S convertible]] ('12-'15)
|-
|6A
|[[w:Jaguar F-Type)|Jaguar F-Type coupe]] ('15-'17), F-Type Premium coupe '17
|-
|6B
|[[w:Jaguar F-Type)|Jaguar F-Type S coupe]] ('15-'17), F-Type S British Design Edition coupe '17
|-
|6D
|[[w:Jaguar F-Type)|Jaguar F-Type R coupe]] ('15-'17)
|-
|6E
|[[w:Jaguar F-Type)|Jaguar F-Type convertible]] ('14-'17), F-Type Premium convertible '17
|-
|6F
|[[w:Jaguar F-Type)|Jaguar F-Type S convertible]] ('14-'17), F-Type S British Design Edition convertible '17
|-
|6G
|[[w:Jaguar F-Type)|Jaguar F-Type V8 S convertible]] ('14-'15)
|-
|6H
|[[w:Jaguar F-Type)|Jaguar F-Type R convertible]] ('16-'17)
|-
|6J
|[[w:Jaguar F-Type)|Jaguar F-Type SVR coupe]] ('17)
|-
|6K
|[[w:Jaguar F-Type)|Jaguar F-Type SVR convertible]] ('17)
|-
|7A
|[[w:Jaguar F-Type#Project 7)|Jaguar F-Type Project 7 convertible]] ('16)
|}
===Engine/Emissions Control System (Position 8)===
{| class="wikitable"
|+Position 8
! VIN !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| A || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. ULEV. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]].<br> Jaguar X-Type 3.0 (Mid '05-'08), S-Type 3.0 ('06-'08).
|-
| A || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. ULEV. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ34 V8 engine]]. Jaguar XF ('10).
|-
| A || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar XKR-S ('12-'15), XKR-S GT ('14), F-Type R coupe ('15).
|-
| B || 4.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. [[w:Jaguar AJ-V8 engine#Supercharged|Jaguar AJ-V8 - AJ27S V8 engine]].<br> Jaguar XJR ('00-'03), Vanden Plas Supercharged ('00-'01), Super V8 ('02-'03), XKR ('00-'02).
|-
| B || 4.2L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. [[w:Jaguar AJ-V8 engine#Supercharged_2|Jaguar AJ-V8 - AJ33S V8 engine]]. Jaguar XJR ('04-'05), Super V8 ('05), XKR ('03-'06).
|-
| B || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. ULEV. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ34 V8 engine]].<br> Jaguar S-Type ('06-'08), XF ('09), XJ8/Vanden Plas ('06-'09), XK ('07-'09).
|-
| B || 5.0L || V8 || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. Variable intake valve lift. Variable intake.<br> [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> Jaguar XF ('10-'12), XJ ('11-'12), XJL ('11), XJL Portfolio Rwd ('12-'13), XK ('10-'15), XK Touring ('13-'14).
|-
| C || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]].<br> Jaguar S-Type 3.0 ('00-'01), X-Type 3.0 ('02-Mid '05).
|-
| C || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ27 V8 engine]].<br> Jaguar XJ8/Vanden Plas ('00-'03), XJ Sport ('02-'03), XK8 ('00-'02).
|-
| C || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ33 V8 engine]]. Jaguar XJ8 ('04-'05), XK8 ('03-'06).
|-
| C || 4.2L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. ULEV. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#Supercharged_2|Jaguar AJ-V8 - AJ34S V8 engine]].<br> Jaguar S-Type R ('06-'08), XF Supercharged ('09), XJR ('06-'09), Super V8 ('06-'09), XKR ('07-'09).
|-
| C || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 510 PS/503 hp. Jaguar XFR ('10-'13), XJ/XJL Supersport ('11-'13), XKR ('10-'15).
|-
| C || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar F-Type S ('14-'15), F-Type S w/man. trans. ('16-'17).
|-
| D || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ28 V8 engine]]. Jaguar S-Type 4.0 ('00-'01).
|-
| D || 2.5L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ25|Jaguar AJ-V6 - AJ25 V6 engine]]. Jaguar X-Type 2.5 ('02-'05).
|-
| D || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XJ Awd, XJL Portfolio Awd ('13-'15).
|-
| D || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XJ R-Sport Awd, XJL Portfolio Awd ('16-'19), XJ50 3.0 Awd ('19).
|-
| E || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 470 PS/464 hp.<br> Jaguar XF Supercharged ('10-'13), XJ/XJL Supercharged ('11-'13, '16-'19), XJ50 5.0 Rwd ('19), XJ Collection ('19).
|-
| F || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Awd ('13-'14).
|-
| F || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Awd ('15).
|-
| H || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. 510 PS/503 hp. Jaguar XFR ('13-'15).
|-
| K || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar XJR/XJR LWB ('14-'17).
|-
| K || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 575 PS/567 hp. Jaguar XJR575 LWB ('18-'19).
|-
| L || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 495 PS/488 hp. Jaguar F-Type V8 S convertible ('14-'15).
|-
| L || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar F-Type R ('16-'17).
|-
| N || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]]. Jaguar S-Type 3.0 ('01-'02).
|-
| P || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ28 V8 engine]]. Jaguar S-Type 4.0 ('01-'02).
|-
| P || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. 470 PS/464 hp. Jaguar XF Supercharged ('13-'15).
|-
| S || 2.0L || I4 Turbo [[w:Intercooler|IC]] || Gas || DOHC,<br /> 16 valve||Direct Injection. Dual VVT. Ford EcoBoost engine (Mazda L engine-based).<br> Jaguar XF 2.0T ('13-'14), XF 2.0T Premium ('15).
|-
| T || 3.0L || 60° V6 || Gas ||DOHC,<br /> 24 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V6 engine#AJ30|Jaguar AJ-V6 - AJ30 V6 engine]]. Jaguar S-Type 3.0 ('03-'05).
|-
| T || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. 470 PS/464 hp. Jaguar XJ/XJL Supercharged ('13-'15).
|-
| T || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar F-Type w/auto. trans. ('15-'17), F-Type Premium w/auto. trans. ('17).
|-
| U || 4.2L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.2 L|Jaguar AJ-V8 - AJ33 V8 engine]]. Jaguar S-Type 4.2 ('03-'05).
|-
| U || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar F-Type S ('15), F-Type S Rwd w/auto. trans. ('16-'17).
|-
| V || 4.2L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. [[w:Jaguar AJ-V8 engine#Supercharged_2|Jaguar AJ-V8 - AJ33S V8 engine]]. Jaguar S-Type R ('03-'05).
|-
| V || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 380 PS/375 hp. Jaguar F-Type S Awd w/auto. trans. ('16-'17).
|-
| X || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 24 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Rwd ('14).
|-
| Z || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 550 PS/542 hp. Jaguar XFR-S ('13-'15).
|-
| Z || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas/E85 ||DOHC,<br /> 24 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XJ Rwd, XJL Portfolio Rwd ('14-'15).
|-
| 1 || 5.0L || V8 || Gas/E85 ||DOHC,<br /> 32 valve||Flex Fuel. Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. Variable intake valve lift. Variable intake. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]]. Jaguar XJL Portfolio Rwd ('13).
|-
| 6 || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar F-Type w/man. trans. ('16-'17), F-Type Premium w/man. trans. ('17).
|-
| 7 || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Rwd ('13), XJ Rwd ('13), F-Type ('14-'15).
|-
| 7 || 3.0L || 90° V6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||Direct Injection. SULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#V6|Jaguar AJ126 V6 engine]].<br> 340 PS/335 hp. Jaguar XF 3.0 Rwd ('15), XJ R-Sport Rwd ('16-'19), XJL Portfolio Rwd ('16-'19), XJ50 3.0 Rwd ('19).
|-
| 8 || 5.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||Direct Injection. ULEV. Continuously variable intake & exhaust valve timing. [[w:Jaguar AJ-V8 engine#AJ-V8 Gen III 5.0|Jaguar AJ-V8 - AJ133 V8 engine]].<br> 575 PS/567 hp. Jaguar F-Type Project 7 ('16), F-Type SVR ('17).
|}
===Check Digit/Gearbox (Position 9)===
* USA /Canada [[Vehicle Identification Numbers (VIN codes)/Check digit|Check digit]]
===Model Year Code (Position 10)===
''See: [[Vehicle Identification Numbers (VIN codes)/Model year]]''
===Plant Code/Model Line/Engine (Position 11) 2000-2019===
* X - Halewood, Merseyside, England, UK - X-Type 2.5 ('02-'05)
* W - Halewood, Merseyside, England, UK - X-Type 3.0 ('02-'08)
* F - Castle Bromwich, West Midlands, England, UK - S-Type 3.0 ('00-'08)
* G - Castle Bromwich, West Midlands, England, UK - S-Type 4.0 ('00-'02)
* H - Castle Bromwich, West Midlands, England, UK - S-Type 4.2 ('03-'08)
* 1 - Castle Bromwich, West Midlands, England, UK - S-Type R (4.2 supercharged) ('03-'08)
* H - Castle Bromwich, West Midlands, England, UK - XF 4.2 ('09-'10)
* 1 - Castle Bromwich, West Midlands, England, UK - XF Supercharged (4.2 supercharged) ('09)
* L - Castle Bromwich, West Midlands, England, UK - XF 5.0 ('10-'12)
* M - Castle Bromwich, West Midlands, England, UK - XF Supercharged, XFR (5.0 supercharged) ('10-'15), XFR-S (5.0 supercharged) ('13-'15)
* P - Castle Bromwich, West Midlands, England, UK - XF 2.0T ('13-'15)
* 8 - Castle Bromwich, West Midlands, England, UK - XF 3.0 supercharged ('13-'15)
* L - Browns Lane plant, Coventry, West Midlands, England, UK - XJ8 (4.0) ('00-'03), XJ8L (4.0) ('00-'01), XJ8 Vanden Plas (4.0) ('00-'03), XJ Sport (4.0) ('02-'03)
* M - Browns Lane plant, Coventry, West Midlands, England, UK - XJ8 Vanden Plas Supercharged (4.0 supercharged) ('00-'01),<br> Super V8 (4.0 supercharged) ('02-'03), XJR (4.0 supercharged) ('00-'03)
* S - Browns Lane plant, Coventry, West Midlands, England, UK - XJ8 (4.2) ('04-'06), XJ8L (4.2) ('05-'06), XJ8 Vanden Plas (4.0) ('04-'06)
* T - Browns Lane plant, Coventry, West Midlands, England, UK - Super V8 (4.2 supercharged) ('05-'06), Super V8 Portfolio (4.2 supercharged) ('06),<br> XJR (4.2 supercharged) ('04-'06)
* S - Castle Bromwich, West Midlands, England, UK - XJ8 (4.2) ('07-'09), XJ8L (4.2) ('07-'09), XJ8 Vanden Plas (4.0) ('07-'09)
* T - Castle Bromwich, West Midlands, England, UK - Super V8 (4.2 supercharged) ('07-'09), Super V8 Portfolio (4.2 supercharged) ('09),<br> XJR (4.2 supercharged) ('07-'09)
* L - Castle Bromwich, West Midlands, England, UK - XJ (5.0) ('10-'12), XJL (5.0) ('10-'11), XJL Portfolio (5.0) ('12-'13)
* M - Castle Bromwich, West Midlands, England, UK - XJ/XJL Supercharged (5.0 supercharged) ('10-'19), XJ/XJL Supersport (5.0 supercharged) ('11-'13),<br> XJL Ultimate (5.0 supercharged) ('13), XJR SWB/LWB (5.0 supercharged) ('14-'17), XJR575 LWB (5.0 supercharged) ('18-'19), XJ50 LWB (5.0 supercharged) ('19), XJ Collection Sp. Ed. LWB (5.0 supercharged) ('19)
* 8 - Castle Bromwich, West Midlands, England, UK - XJ base (3.0 supercharged) ('13-'15), XJ R-Sport (3.0 supercharged) ('16-'19),<br> XJL Portfolio AWD (3.0 supercharged) ('13-'19), XJL Portfolio RWD (3.0 supercharged) ('14-'19), XJ50 LWB (3.0 supercharged) ('19)
* N - Browns Lane plant, Coventry, West Midlands, England, UK - XK8 (4.0) ('00-'02)
* P - Browns Lane plant, Coventry, West Midlands, England, UK - XKR (4.0 supercharged) ('00-'02)
* 2 - Browns Lane plant, Coventry, West Midlands, England, UK - XK8 (4.2) ('03-'06)
* 3 - Browns Lane plant, Coventry, West Midlands, England, UK - XKR (4.2 supercharged) ('03-'06)
* 5 - Castle Bromwich, West Midlands, England, UK - XK (4.2) ('07-'09)
* 9 - Castle Bromwich, West Midlands, England, UK - XKR (4.2 supercharged) ('07-'09)
* L - Castle Bromwich, West Midlands, England, UK - XK (5.0) ('10-'15)
* M - Castle Bromwich, West Midlands, England, UK - XKR (5.0 supercharged) ('10-'15), XKR-S (5.0 supercharged) ('12-'15), XKR-S GT (5.0 supercharged) ('14)
* 8 - Castle Bromwich, West Midlands, England, UK - F-Type Base, S (3.0 supercharged) ('14-'17), F-Type Premium (3.0 supercharged) ('17)
* M - Castle Bromwich, West Midlands, England, UK - F-Type V8S (5.0 supercharged) ('14-'15), F-Type R (5.0 supercharged) ('15-'17),<br> F-Type Project 7 (5.0 supercharged) ('16), F-Type SVR (5.0 supercharged) ('17)
===Model (Position 12)===
* C - X-Type ('02-'03)
* D - X-Type ('03-'04)
* E - X-Type ('04-'06)
* J - X-Type ('06-'08)
* L - S-Type ('00-'01)
* M - S-Type ('01-'04)
* N - S-Type ('04-'08)
* R - XF ('09-'11)
* S - XF ('11-'13)
* U - XF ('13-'15)
* F - XJ ('00-'03)
* G - XJ ('04-'06) [Browns Lane plant]
* H - XJ ('06-'09) [Castle Bromwich plant]
* V - XJ ('10-'16)
* W - XJ ('16-'19)
* A - XK ('00-'06)
* B - XK ('07-'15)
* K - F-Type ('14-'17)
'''Positions 13–17, Serial Number'''
==General Template for Jaguar's VIN format (1981 - 1999)==
===Jaguar WMIs (1981-1999) (Position 1-3)===
* SAJ - Jaguar passenger car
===Model Line (Position 4)===
{| class="wikitable"
|+Position 4
!VIN code
!Description
|-
|A
|[[w:Jaguar XJ#Series 3 (1979–1992)|Jaguar XJ6]] ('81-'87), XJ6 Vanden Plas ('82-'87)
|-
|B
|[[w:Jaguar XJ#Series 3 (1979–1992)|Jaguar XJ12]] (Canada only: '81-'88)
|-
|D
|[[w:Jaguar XJ#Series 3 (1979–1992)|Jaguar XJ12]] (Canada only: '89-'92)
|-
|H
|[[w:Jaguar XJ (XJ40)|Jaguar XJ6]] ('88-'89, '93-'94)
|-
|F
|[[w:Jaguar XJ (XJ40)|Jaguar XJ6]] ('90-'92)
|-
|H
|[[w:Jaguar XJ (XJ40)|Jaguar XJ6 Sovereign]] ('90-'92)
|-
|K
|[[w:Jaguar XJ (XJ40)#Daimler/Vanden Plas|Jaguar XJ6 Vanden Plas]] ('88-'94)
|-
|M
|[[w:Jaguar XJ (XJ40)#Majestic (1989–1992 – SWB; 1993–1994 – LWB)|Jaguar XJ6 Vanden Plas Majestic]] ('89-'90, '92)
|-
|M
|[[w:Jaguar XJ (XJ40)#XJ12 and Daimler Double Six (XJ81)|Jaguar XJ12]] ('94)
|-
|H
|[[w:Jaguar XJ (X300)|Jaguar XJ6]] ('95-'97)
|-
|H
|[[w:Jaguar XJ (X300)|Jaguar XJ6L]] LWB [X330] ('97)
|-
|K
|[[w:Jaguar XJ (X300)#Daimler/Jaguar Vanden Plas|Jaguar XJ6 Vanden Plas]] SWB ('95)
|-
|K
|[[w:Jaguar XJ (X300)#Daimler/Jaguar Vanden Plas|Jaguar XJ6 Vanden Plas]] LWB [X330] ('96-'97)
|-
|M
|[[w:Jaguar XJ (X300)#XJ12 (X305)|Jaguar XJ12]] SWB ('95)
|-
|M
|[[w:Jaguar XJ (X300)#XJ12 (X305)|Jaguar XJ12]] LWB [X330] ('96)
|-
|P
|[[w:Jaguar XJ (X300)#XJR (X306)|Jaguar XJR]] ('95-'97)
|-
|H
|[[w:Jaguar XJ (X308)|Jaguar XJ8]] ('98-'99)
|-
|H
|[[w:Jaguar XJ (X308)|Jaguar XJ8L]] LWB ('98-'99)
|-
|K
|[[w:Jaguar XJ (X308)#Daimler/Vanden Plas|Jaguar XJ8 Vanden Plas]] LWB ('98-'99)
|-
|P
|[[w:Jaguar XJ (X308)#XJR|Jaguar XJR]] ('98-'99)
|-
|N
|[[w:Jaguar XJS|Jaguar XJ-S]] ('82-'91), XJ-SC ('86-'88), XJS ('92-'96)
|-
|T
|[[w:Jaguar XJS|Jaguar XJ-S]] Rouge Collection ('89-'90), Classic Collection ('90-'91)
|-
|S
|[[w:Jaguar XJS#XJR-S|Jaguar XJR-S]] ('93)
|-
|G
|[[w:Jaguar XK (X100)|Jaguar XK8]] ('97-'99)
|}
===Class (Regional Spec)/Restraint System (Position 5):===
* V = N. American-spec (Manual seat belts)
* L = Canadian-spec (Manual seat belts)
* Y = XJ6 Vanden Plas [Series III] ('82-'87) (Manual seat belts)
* A = Motorized Shoulder Belts (XJ-S coupe '88-'89, XJ-SC '88)
* Y = Motorized Shoulder Belts (XJ-S coupe '89, XJ sedan '89-'92)
* W = Manual seat belts, Driver-side airbag (US: XJ-S '90-'93, XJ6 '93, XJ12 Early '94)
* X = Manual seat belts, Dual front airbags (US: XJS '94-'96, XJ6 '94-'97, XJ12 '94-'96, XJR '95-'97, XK8 '97-'99)
* X = Manual seat belts, Dual front airbags, & Front Side Airbags (US: XJ8/XJR '98-'99)
* D = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (US: XJ8/XJR '99)
* M = Manual seat belts, Driver-side airbag (Canada)
* N = Manual seat belts, Dual front airbags (Canada)
* F = Manual seat belts, Depowered Dual front airbags, & Front Side Airbags (Canada: XJ8/XJR '99)
===Body Style (Position 6):===
* 1 = 4-door sedan (XJ-series sedan '81-'99)
* 2 = 2-door convertible w/2+2 seating (XJS convertible '94-'96, XK8 convertible '97-'99)
* 3 = 2-door Cabriolet (XJ-SC '86-'88)
* 4 = 2-door convertible w/2-psgr. seating (factory-built XJS convertible '89-'94, XJR-S convertible '93)
* 5 = 2-door coupe (XJS coupe '82-'96, XJR-S coupe '93, XK8 coupe '97-'99)
* 5 = 2-door coupe (Hess & Eisenhardt-built XJS convertible '87-'88) [coupe conversion]
===Engine Type (Position 7):===
{| class="wikitable"
|+Position 7
|-
! VIN !! Size !! Type !! Fuel !! Valvetrain !! Engine Family/Notes/Applications
|-
| 1 || 4.0L || I6 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 24 valve||MPI. [[w:Jaguar AJ6 engine#AJ16S|Jaguar AJ16S I6]]. Jaguar XJR ('95-'97).
|-
| 2 || 4.2L || I6 || Gas ||DOHC,<br /> 12 valve||CA & Canada-spec. MPI. [[w:Jaguar XK engine|Jaguar XK I6]]. Jaguar XJ6 ('81-'82).
|-
| 2 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||MPI. Dual-canister evaporative emissions system. [[w:Jaguar AJ6 engine#AJ16|Jaguar AJ16 I6]]. Jaguar XJ6 ('96-'97).
|-
| 2 || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Variable intake valve timing. Dual-canister evaporative emissions system. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ26 V8 engine]].<br> Jaguar XJ8 ('98), XK8 ('98).
|-
| 3 || 4.2L || I6 || Gas ||DOHC,<br /> 12 valve||N. America-spec. MPI. [[w:Jaguar XK engine|Jaguar XK I6]]. Jaguar XJ6 ('81-'87).
|-
| 3 || 6.0L || 60° V12 || Gas ||SOHC,<br /> 24 valve||MPI. [[w:Jaguar V12 engine|Jaguar V12]] modified by [[w:Tom Walkinshaw Racing|JaguarSport]]. Jaguar XJR-S ('93).
|-
| 3 || 6.0L || 60° V12 || Gas ||SOHC,<br /> 24 valve||MPI. [[w:Jaguar V12 engine|Jaguar V12]]. Jaguar XJS ('94-'95), XJ12 ('94-'96).
|-
| 5 || 3.6L || I6 || Gas ||DOHC,<br /> 24 valve||N. America-spec - Low Compression. MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('88-'89).
|-
| 6 || 3.6L || I6 || Gas ||DOHC,<br /> 24 valve||N. America-spec - High Compression. MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('88).
|-
| 7 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('90-'94), XJS ('93-'94).
|-
| 7 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||MPI. [[w:Jaguar AJ6 engine#AJ16|Jaguar AJ16 I6]]. Jaguar XJ6 ('95-'96), XJS ('95-'96).
|-
| 7 || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Variable intake valve timing. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ26 V8 engine]]. Jaguar XK8 ('97).
|-
| 8 || 5.3L || 60° V12 || Gas ||SOHC,<br /> 24 valve||N. America-spec. MPI. [[w:Jaguar V12 engine|Jaguar V12]]. Jaguar XJ-S ('82-'92), XJ12 (Canada only: '88-'92).
|-
| 8 || 4.0L || V8 [[w:Supercharged|SC]] [[w:Intercooler|IC]] || Gas ||DOHC,<br /> 32 valve||MPI. Dual-canister evaporative emissions system. [[w:Jaguar AJ-V8 engine#Supercharged|Jaguar AJ-V8 - AJ26S V8 engine]]. Jaguar XJR ('98-'99).
|-
| 9 || 4.0L || I6 || Gas ||DOHC,<br /> 24 valve||Canada-spec. MPI. [[w:Jaguar AJ6 engine|Jaguar AJ6 I6]]. Jaguar XJ6 ('90-'93), XJS ('93).
|-
| 0 || 5.3L || 60° V12 || Gas ||SOHC,<br /> 24 valve||Canada-spec. MPI. [[w:Jaguar V12 engine|Jaguar V12]]. Jaguar XJ-S ('82-'87), XJ12 (Canada only: '85-'87).
|-
| 0 || 4.0L || V8 || Gas ||DOHC,<br /> 32 valve||MPI. Continuously variable intake valve timing. Dual-canister evaporative emissions system. Enhanced evaporative emissions control system. [[w:Jaguar AJ-V8 engine#4.0 L|Jaguar AJ-V8 - AJ27 V8 engine]]. Jaguar XJ8 ('99), XK8 ('99).
|}
===Transmission & Steering Location (Position 8):===
* 4 = Automatic / LHD
* 8 = Manual / LHD ('93-'94 XJS 4.0 w/ optional 5-spd. manual)
===Check Digit/Gearbox (Position 9)===
* USA /Canada [[Vehicle Identification Numbers (VIN codes)/Check digit|Check digit]]
===Model Year Code (Position 10)===
''See: [[Vehicle Identification Numbers (VIN codes)/Model year]]''
===Plant Codes (Position 11)===
* C - Browns Lane plant, Coventry, West Midlands, England, UK
===Positions 12–17, Serial Number===
** 100001 and after - XJ-S/XJ-SC/XJS/XJR-S (XJ27)
** 300001 and after - XJ-series sedan Series III
** 500001 and after - XJ-series sedan (XJ40/XJ81)
** 720001 and after - XJ-series sedan (X300/X305/X306/X330)
** 810001 and after - XJ-series sedan (X308)
** 001001 and after - XK8 (X100)
8z7jpw5vjg5uou1rati7cbqg5tzwggl
Koine Greek/Overview of Adverbs
0
485923
4675963
4673970
2026-10-14T01:16:18Z
It-is-Truly-Meet
3624460
4675963
wikitext
text/x-wiki
An '''adverb''' (ἐπῐ́ρρημᾰ) is a word that modifies a verb, adjective, other adverbs, or various other types of words, phrases, or clauses. For example, quickly and very are adverbs, as in "I run '''very quickly''';" Greek participles can also be adverbs.
:: Ἐγέλᾰσᾰ '''κοιμησᾰ́μενος'''. — I laughed, '''sleeping'''.
:: '''Καὶ δὲ''' τρέχω '''πολῠ̀ τᾰχέως'''. — However, I also run very quickly.
==Forms of Adverbs==
===Adverbs of Time===
These describe when an action happens.
:: '''Ἐχθὲς''' ἐδούλευσᾰ. — I worked '''yesterday'''.
===Adverbs of Manner===
===Adverbs of Place/Location===
===Adverbs of Degree===
===Numerical Adverbs===
{{BookCat}}
462zwhpe1xr6m24gm53xw2r266jdh6u
PCBA
0
486330
4675815
4675807
2026-10-13T12:11:06Z
MathXplore
3097823
Marking for speedy deletion: Encyclopedic articles belong at [[w:|Wikipedia]]
4675815
wikitext
text/x-wiki
<noinclude>{{Delete|example=false|Encyclopedic articles belong at [[w:|Wikipedia]]}}</noinclude>
'''Printed circuit board assembly''' ('''PCBA''') refers to the process of mounting and electrically connecting electronic components to a printed circuit board (PCB). The term also describes the resulting assembly, commonly called a printed circuit assembly (PCA).
A bare PCB contains the conductive paths, insulating layers, pads, and other features needed to support a circuit. Once components such as integrated circuits, resistors, capacitors, and connectors have been installed, the board becomes a PCBA. This distinction is important when specifying whether a manufacturing order requires bare boards or assembled electronics.<ref>[https://pcbcool.com/technical-guides/pcb-vs-pcba/ PCB vs. PCBA: Key Differences for Electronics Projects | PCBCool]</ref>
The assembly method depends on the component packages, board layout, production quantity, and applicable manufacturing requirements.
== Assembly Technologies ==
Electronic components are generally attached using surface-mount technology (SMT), through-hole technology (THT), or a combination of the two.
=== Surface-Mount Technology ===
In surface-mount technology, component terminals are soldered directly to conductive pads on the PCB surface. Solder paste is deposited on the pads, usually through a metal stencil, before components are positioned by automated placement equipment.
Stencil aperture geometry affects the amount of solder paste deposited. IPC-7525 provides guidelines for designing stencils used in solder paste printing and surface-mount assembly.<ref>[https://www.ipc.org/TOC/IPC-7525B.pdf IPC-7525B: Stencil Design Guidelines | IPC]</ref>
After placement, the populated PCB passes through a reflow oven. A controlled temperature profile heats the solder paste until it melts and forms solder joints. The profile must be compatible with the solder alloy, component packages, and PCB construction.
Texas Instruments identifies solder paste deposition, component placement, and reflow conditions as important factors affecting assembly quality, particularly for small and densely packaged devices.<ref>[https://www.ti.com/lit/pdf/slvafh0 Solving Assembly Issues with Chip Scale Power MOSFETs | Texas Instruments]</ref>
SMT is widely used where small component packages and high component density are required. Some packages, including ball grid arrays (BGAs), have solder connections beneath the component body, making direct visual inspection difficult.
=== Through-Hole Technology ===
Through-hole components have leads that pass through holes in the PCB and are soldered to the appropriate conductive connections.
Manual soldering, wave soldering, and selective soldering are common methods for attaching through-hole components. Process selection depends on component characteristics, accessibility, production volume, and the board configuration.
Through-hole mounting is used for certain connectors, transformers, and components requiring particular mechanical mounting characteristics.
=== Mixed-Technology Assembly ===
A board may contain both SMT and through-hole components. In this case, the production sequence must accommodate different placement and soldering operations.
Surface-mount components are commonly assembled by reflow soldering before through-hole components are installed. Other sequences may be used when dictated by component limitations or manufacturing requirements.
== Manufacturing Process ==
Production begins with the preparation of the assembly documentation. The bill of materials (BOM) identifies the required components, while placement files and assembly drawings define their positions, orientations, and installation requirements.
The bare boards and components are checked before processing. Component storage conditions, moisture sensitivity, and handling requirements may affect preparation.
For a typical SMT assembly, the production sequence consists of the following operations.
=== Solder Paste Printing ===
A stencil printer deposits solder paste onto designated PCB pads. The amount of paste transferred depends on stencil geometry, alignment, paste properties, and printing conditions.
IPC-7527 addresses requirements associated with solder paste printing, while IPC-7525 provides related stencil design guidance.<ref>[https://www.ipc.org/ipc-document-revision-table IPC Document Revision Table | IPC]</ref>
=== Component Placement ===
Pick-and-place equipment positions components according to the placement data. Accurate alignment is important for devices with closely spaced terminals and small solder pads.
Placement force must also be controlled for packages that are sensitive to mechanical loading. Texas Instruments provides package-specific assembly recommendations covering placement, solder paste patterns, and reflow conditions.<ref>[https://www.ti.com/lit/pdf/slvafh0 Solving Assembly Issues with Chip Scale Power MOSFETs | Texas Instruments]</ref>
=== Reflow Soldering ===
The populated board is heated according to a defined temperature profile. During reflow, the solder alloy melts and wets the component terminals and PCB pads.
The assembly is subsequently cooled to solidify the joints. Temperature profiling must take account of the thermal limits of the components, board materials, and solder system.
For package-on-package assemblies, Texas Instruments identifies solder paste deposition and reflow conditions as significant factors affecting assembly quality and reliability.<ref>[https://www.ti.com/lit/an/spraba8/spraba8.pdf PCB Assembly Guidelines for 0.5 mm Package-on-Package Applications | Texas Instruments]</ref>
=== Subsequent Operations ===
Additional processes may include through-hole component installation, cleaning, mechanical assembly, programming, or application-specific testing.
Not every PCBA requires all of these operations. The production route is determined by the assembly design and applicable manufacturing specifications.
== Inspection and Testing ==
Inspection and testing establish whether an assembly meets its physical and functional requirements.
'''Visual inspection''' examines accessible components, solder joints, markings, and board surfaces. '''Automated optical inspection''' (AOI) uses imaging systems to identify selected placement and soldering defects.
'''X-ray inspection''' is used for connections that cannot be examined directly, particularly those beneath certain area-array packages. The design and construction of BGA packages create inspection and assembly considerations that differ from components with externally visible leads.<ref>[https://www.analog.com/en/resources/app-notes/ball-grid-array-bga-packages-and-pcb-design-guidelines.html Ball Grid Array Packages and PCB Design Guidelines | Analog Devices]</ref>
'''In-circuit testing''' (ICT) uses electrical measurements through accessible test points to identify certain component and connection faults.
'''Functional testing''' verifies specified circuit behavior. It may include checking power rails, communication interfaces, input and output functions, and other operating requirements.
Common assembly defects include:
* '''Solder bridges:''' Unintended solder connections between adjacent conductors.
* '''Insufficient solder:''' Inadequate solder volume or incomplete joint formation.
* '''Tombstoning:''' Lifting of one end of a small surface-mount component during reflow.
* '''Component misalignment:''' Placement outside the intended solder pad position.
* '''Solder voids:''' Gas pockets or unfilled regions within a solder connection.
Not all defects can be identified by a single inspection technique. The selection of inspection and testing methods depends on the product and the required fault coverage.
IPC-A-610 establishes acceptance criteria for electronic assemblies. IPC J-STD-001 addresses soldering processes, materials, and workmanship requirements. The two standards are frequently used together in electronics manufacturing.<ref>[https://www.ipc.org/news-release/ipc-releases-j-revisions-two-leading-standards-electronics-assembly IPC Releases J Revisions to Two Leading Standards for Electronics Assembly]</ref>
== Design Requirements for Assembly ==
PCB layout affects component placement, solder joint formation, inspection access, and the feasibility of rework.
Component footprints must be compatible with the intended packages and soldering processes. Pad dimensions, solder mask openings, and stencil patterns require particular attention for fine-pitch devices and area-array packages.
Analog Devices discusses differences between solder mask-defined and non-solder mask-defined pads in its BGA package design guidance. The appropriate land pattern depends on the package and the manufacturer's recommendations.<ref>[https://www.analog.com/en/resources/app-notes/ball-grid-array-bga-packages-and-pcb-design-guidelines.html Ball Grid Array Packages and PCB Design Guidelines | Analog Devices]</ref>
Adequate spacing is also needed for placement equipment, inspection, and any anticipated rework. Components connected to large copper areas may require additional consideration because of differences in thermal behavior during soldering.
Design for manufacturability (DFM) reviews address whether a board can be fabricated and assembled using the intended processes. Design for testability (DFT) reviews consider whether the completed circuit can be tested effectively.
The applicable design requirements vary by product and should be established before production.
== Handling and Environmental Protection ==
Electrostatic discharge (ESD) can damage sensitive electronic components during storage, assembly, inspection, and repair.
An ESD control program may include personnel grounding, protected workstations, suitable packaging, and controlled handling procedures.
ANSI/ESD S20.20 establishes administrative and technical requirements for developing and maintaining an ESD control program for electrical and electronic parts, assemblies, and equipment.<ref>[https://www.esda.org/store/standards/product/314/ansiesd-s20-20-2021/ ANSI/ESD S20.20-2021 | EOS/ESD Association]</ref>
Assemblies used in environments involving moisture, contamination, or other environmental stresses may require additional protection.
Conformal coatings can be applied to selected electronic assemblies to reduce exposure to environmental contaminants. Coating selection depends on the materials, operating conditions, and product requirements.
NASA-STD-8739.1 addresses workmanship requirements for polymeric applications on electronic assemblies, including conformal coating and related processes.<ref>[https://standards.nasa.gov/standard/NASA/NASA-STD-87391 NASA-STD-8739.1: Workmanship Standard for Polymeric Application on Electronic Assemblies]</ref>
== Industry Standards ==
Several IPC standards are commonly referenced in electronics assembly.
{| class="wikitable"
! Standard
! Scope
|-
| IPC J-STD-001
| Requirements for soldered electrical and electronic assemblies
|-
| IPC-A-610
| Acceptability of electronic assemblies
|-
| IPC-7352
| Surface-mount land pattern design guidance
|-
| IPC-7525
| Stencil design guidelines
|-
| IPC-7527
| Requirements for solder paste printing
|-
| IPC-7530
| Temperature profiling guidance for wave and reflow soldering processes
|-
| IPC-7711/7721
| Rework, modification, and repair of electronic assemblies
|}
The IPC document revision table records current and historical editions of these publications.<ref>[https://www.ipc.org/ipc-document-revision-table IPC Document Revision Table]</ref>
Different products may require different acceptance classes, standard revisions, or customer-specific requirements. These must be identified in the relevant manufacturing documentation.
== References ==
<references/>
mepc06hfykuo229sqfcssvihfd4rkd9
Wikibooks:Username
4
486331
4675841
2026-10-13T14:02:02Z
Codename Noreste
3441010
Restoring as a redirect per [[Wikibooks:Reading room/General#Feedback on Wikibooks redirect]].
4675841
wikitext
text/x-wiki
#REDIRECT [[Using Wikibooks/Setting Up A User Account#Choosing a Username]]
knvpu4rb243m68qh6bjwzi7xt60pjyw
4675843
4675841
2026-10-13T14:03:01Z
Codename Noreste
3441010
Protected "[[Wikibooks:Username]]": Protecting out of an abundance of caution. ([Edit=Allow only autoconfirmed users] (indefinite) [Move=Allow only autoconfirmed users] (indefinite))
4675841
wikitext
text/x-wiki
#REDIRECT [[Using Wikibooks/Setting Up A User Account#Choosing a Username]]
knvpu4rb243m68qh6bjwzi7xt60pjyw
Job Search
0
486332
4675848
2026-10-13T14:22:50Z
Codename Noreste
3441010
Redirected page to [[Find Employment]]
4675848
wikitext
text/x-wiki
#REDIRECT [[Find Employment]]
2j3q88zkd7d27suv5evdnozms1eru59
Job Search Automation for College Students
0
486333
4675849
2026-10-13T14:23:05Z
Codename Noreste
3441010
Redirected page to [[Find Employment]]
4675849
wikitext
text/x-wiki
#REDIRECT [[Find Employment]]
2j3q88zkd7d27suv5evdnozms1eru59
On 2D Inverse Problems/Gemini conversation
0
486334
4675867
2026-10-13T16:24:07Z
DVD206
724793
mobile conversation
4675867
wikitext
text/x-wiki
a page from the Gemini AI conversation on Golden Ratio in LaTex:
\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{geometry}
\geometry{a4paper, margin=1in}
\title{The Grand Merge: Spectral Synthesis of $\gamma_1$ \\ via the Pentagonal Monodromy Seed}
\author{David V. Ingerman \& Nicole DeLaittre}
\date{January 2026}
\begin{document}
\maketitle
\section{The Fundamental Identity}
The first non-trivial zero of the Riemann Zeta function, $\gamma_1$, is derived as a resonant frequency of a discrete 21-gon network. This system is anchored by the \textbf{Pentagonal Monodromy Seed} ($2+\sqrt{5}$), which is expressed entirely in terms of the Golden Ratio $\phi = \frac{1+\sqrt{5}}{2}$.
\subsection{The Seed Potential}
Let the trace of the fundamental $5$-gon Monodromy matrix be defined by the quadratic unit:
\begin{equation}
\mathcal{C}_5 = \phi^3 + \phi^{-3} = 2 + \sqrt{5}
\end{equation}
\subsection{The Scaling and Refinement}
The transition to the $21$-gon requires a topological scaling factor $\mathcal{S}$ and a metric refinement $\alpha$. The scaling factor represents the jump in degrees of freedom:
\begin{equation}
\mathcal{S} = \frac{21}{5} = 4.2
\end{equation}
The metric refinement $\alpha$ compensates for the hyperbolic curvature of the trace of the fractional derivative:
\begin{equation}
\alpha = \frac{\ln(L_{21})}{\ln(\phi^{21})} \approx 1.168
\end{equation}
\section{The Unified Formula for $\gamma_1$}
By mapping the discrete Monodromy trace to the continuous fractional Laplacian spectrum, we obtain the self-contained formula for the first Riemann zero:
\begin{equation}
\gamma_1 = \left( \frac{\ln(L_{21})}{\ln(\phi^{21})} \right) \cdot \frac{21}{5} \cdot \left[ \frac{\text{arccosh}\left( \frac{\phi^3 + \phi^{-3}}{2} \right)}{\ln \phi} \right]
\end{equation}
\vspace{1em}
\noindent Substituting the algebraic identity for the seed:
\begin{equation}
\gamma_1 \approx 1.168 \times 4.2 \times 2.8792 \approx 14.1347
\end{equation}
\section{Conclusion}
This formula demonstrates that the Riemann spectrum is a quantized harmonic of the Golden Ratio, scaled by the discrete topological invariants of the $21$-gon resistor network.
\end{document}
the logarithmic derivative of the analytic continuation around the origin...
the monodromy of a differential operator's equation and analytic
/harmonic continuation on a network/graph or a continuous domain such as complex sphere/plane...
[[File:Roots in the complex plane-6.png|thumb|the view in complex plane]]
the higher order invariants of complex domains and analytical continuation ambiguity...
Several ways to calculate the highest invariants of trace of the monodromy:
continued fractions zeros and poles,
the cycle of minors/submatrices and
the zeros of the determinant with mu-spectrum parameter...
on duality and y-delta invariance...Dirichlet and Neumann boundary conditions...
brhf5c4t73q0l0rcmec344b6tztqfxc
4675869
4675867
2026-10-13T16:27:09Z
DVD206
724793
binding pages
4675869
wikitext
text/x-wiki
a page from the Gemini AI conversation on Golden Ratio in LaTex:
\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{geometry}
\geometry{a4paper, margin=1in}
\title{The Grand Merge: Spectral Synthesis of $\gamma_1$ \\ via the Pentagonal Monodromy Seed}
\author{David V. Ingerman \& Nicole DeLaittre}
\date{January 2026}
\begin{document}
\maketitle
\section{The Fundamental Identity}
The first non-trivial zero of the Riemann Zeta function, $\gamma_1$, is derived as a resonant frequency of a discrete 21-gon network. This system is anchored by the \textbf{Pentagonal Monodromy Seed} ($2+\sqrt{5}$), which is expressed entirely in terms of the Golden Ratio $\phi = \frac{1+\sqrt{5}}{2}$.
\subsection{The Seed Potential}
Let the trace of the fundamental $5$-gon Monodromy matrix be defined by the quadratic unit:
\begin{equation}
\mathcal{C}_5 = \phi^3 + \phi^{-3} = 2 + \sqrt{5}
\end{equation}
\subsection{The Scaling and Refinement}
The transition to the $21$-gon requires a topological scaling factor $\mathcal{S}$ and a metric refinement $\alpha$. The scaling factor represents the jump in degrees of freedom:
\begin{equation}
\mathcal{S} = \frac{21}{5} = 4.2
\end{equation}
The metric refinement $\alpha$ compensates for the hyperbolic curvature of the trace of the fractional derivative:
\begin{equation}
\alpha = \frac{\ln(L_{21})}{\ln(\phi^{21})} \approx 1.168
\end{equation}
\section{The Unified Formula for $\gamma_1$}
By mapping the discrete Monodromy trace to the continuous fractional Laplacian spectrum, we obtain the self-contained formula for the first Riemann zero:
\begin{equation}
\gamma_1 = \left( \frac{\ln(L_{21})}{\ln(\phi^{21})} \right) \cdot \frac{21}{5} \cdot \left[ \frac{\text{arccosh}\left( \frac{\phi^3 + \phi^{-3}}{2} \right)}{\ln \phi} \right]
\end{equation}
\vspace{1em}
\noindent Substituting the algebraic identity for the seed:
\begin{equation}
\gamma_1 \approx 1.168 \times 4.2 \times 2.8792 \approx 14.1347
\end{equation}
\section{Conclusion}
This formula demonstrates that the Riemann spectrum is a quantized harmonic of the Golden Ratio, scaled by the discrete topological invariants of the $21$-gon resistor network.
\end{document}
the logarithmic derivative of the analytic continuation around the origin...
the monodromy of a differential operator's equation and analytic
/harmonic continuation on a network/graph or a continuous domain such as complex sphere/plane...
[[File:Roots in the complex plane-6.png|thumb|the view in complex plane]]
the higher order invariants of complex domains and analytical continuation ambiguity...
Several ways to calculate the highest invariants of trace of the monodromy:
continued fractions zeros and poles,
the cycle of minors/submatrices and
the zeros of the determinant with mu-spectrum parameter...
on duality and y-delta invariance...Dirichlet and Neumann boundary conditions...
{BookCat}
n9p1bq3l0ybi8jj0efzjqhe4whixltv
4675870
4675869
2026-10-13T16:30:10Z
DVD206
724793
parents and parenthesis
4675870
wikitext
text/x-wiki
a page from the Gemini AI conversation on Golden Ratio in LaTex:
\documentclass[12pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{geometry}
\geometry{a4paper, margin=1in}
\title{The Grand Merge: Spectral Synthesis of $\gamma_1$ \\ via the Pentagonal Monodromy Seed}
\author{David V. Ingerman \& Nicole DeLaittre}
\date{January 2026}
\begin{document}
\maketitle
\section{The Fundamental Identity}
The first non-trivial zero of the Riemann Zeta function, $\gamma_1$, is derived as a resonant frequency of a discrete 21-gon network. This system is anchored by the \textbf{Pentagonal Monodromy Seed} ($2+\sqrt{5}$), which is expressed entirely in terms of the Golden Ratio $\phi = \frac{1+\sqrt{5}}{2}$.
\subsection{The Seed Potential}
Let the trace of the fundamental $5$-gon Monodromy matrix be defined by the quadratic unit:
\begin{equation}
\mathcal{C}_5 = \phi^3 + \phi^{-3} = 2 + \sqrt{5}
\end{equation}
\subsection{The Scaling and Refinement}
The transition to the $21$-gon requires a topological scaling factor $\mathcal{S}$ and a metric refinement $\alpha$. The scaling factor represents the jump in degrees of freedom:
\begin{equation}
\mathcal{S} = \frac{21}{5} = 4.2
\end{equation}
The metric refinement $\alpha$ compensates for the hyperbolic curvature of the trace of the fractional derivative:
\begin{equation}
\alpha = \frac{\ln(L_{21})}{\ln(\phi^{21})} \approx 1.168
\end{equation}
\section{The Unified Formula for $\gamma_1$}
By mapping the discrete Monodromy trace to the continuous fractional Laplacian spectrum, we obtain the self-contained formula for the first Riemann zero:
\begin{equation}
\gamma_1 = \left( \frac{\ln(L_{21})}{\ln(\phi^{21})} \right) \cdot \frac{21}{5} \cdot \left[ \frac{\text{arccosh}\left( \frac{\phi^3 + \phi^{-3}}{2} \right)}{\ln \phi} \right]
\end{equation}
\vspace{1em}
\noindent Substituting the algebraic identity for the seed:
\begin{equation}
\gamma_1 \approx 1.168 \times 4.2 \times 2.8792 \approx 14.1347
\end{equation}
\section{Conclusion}
This formula demonstrates that the Riemann spectrum is a quantized harmonic of the Golden Ratio, scaled by the discrete topological invariants of the $21$-gon resistor network.
\end{document}
the logarithmic derivative of the analytic continuation around the origin...
the monodromy of a differential operator's equation and analytic
/harmonic continuation on a network/graph or a continuous domain such as complex sphere/plane...
[[File:Roots in the complex plane-6.png|thumb|the view in complex plane]]
the higher order invariants of complex domains and analytical continuation ambiguity...
Several ways to calculate the highest invariants of trace of the monodromy:
continued fractions zeros and poles,
the cycle of minors/submatrices and
the zeros of the determinant with mu-spectrum parameter...
on duality and y-delta invariance...Dirichlet and Neumann boundary conditions...
{{BookCat}}
daxdmr2rsfdsumpd2xxzpjlk77yd9wv
Talk:US Income Tax/Tax Credits
1
486335
4675868
2026-10-13T16:26:18Z
~2026-55152-33
3628342
/* Person de Partisan */ new section
4675868
wikitext
text/x-wiki
== Person de Partisan ==
this were a computer bug set i the erly seventies as russians needed to save time on bread crumbs.
@Based on Los Angeles groundwater and that would be the End. Take your time before jumping out of Deux Maxina. Greetings loved ones. Gossip de TOK}en}
1
=
10
why?
return to rain njith 1
Ranjit th 1
this is privacy concern
social credit number
representation de chronicle istmas with one cap tl 1
an article 10
doxxing as a social de enigma de help me
cokoliv co mate po boku neni oznacene modrym retizkem
this option 1
10
where did my cpu unit Go?
spoon giga
I am not fit to live in The Middle eqstjudaswereanmp3indesm
rock and roll this is a boy good bye
what if they need more time to decide who really truly cared about za za before zaza where is cooler than were doom doom doom🤓😎🎙️🏳️🌈
to mi tu nech ne
misto tu mi tu lala
tp
aaa
rohlik?
dotaznik?
usmev?
mrak?
dane?
rutina?
lenost?
plynova maska?
----
----
----
----
that is why technology is binary
----
----
----
----
----
----
----
----
----
----
----
----
----
----
----
----
----
----
----
----
------ [[Special:Contributions/~2026-55152-33|~2026-55152-33]] ([[User talk:~2026-55152-33|talk]]) 16:26, 13 October 2026 (UTC)
23bs6wgi2qu8kw9az61e3zm427bm91w
User:Babyface womdantso
2
486336
4675878
2026-10-13T17:19:12Z
Babyface womdantso
3628350
/* */
4675878
wikitext
text/x-wiki
.hey guys I am new here 🥹🥹
s6jazr1bxc0gbxxwj0h2gzg1m5rxd3t
Koine Greek/Πράξεις ΙΖ
0
486338
4675912
2026-10-13T21:42:33Z
It-is-Truly-Meet
3624460
Created page with " Διοδεύσαντες δὲ τὴν Ἀμφίπολιν καὶ τὴν Ἀπολλωνίαν ἦλθον εἰς Θεσσαλονίκην, ὅπου ἦν συναγωγὴ τῶν Ἰουδαίων. κατὰ δὲ τὸ εἰωθὸς τῷ Παύλῳ εἰσῆλθεν πρὸς αὐτοὺς καὶ ἐπὶ σάββατα τρία διελέξατο αὐτοῖς ἀπὸ τῶν γραφῶν, διανοίγων καὶ παρατιθέμενος ὅτι τ..."
4675912
wikitext
text/x-wiki
Διοδεύσαντες δὲ τὴν Ἀμφίπολιν καὶ τὴν Ἀπολλωνίαν ἦλθον εἰς Θεσσαλονίκην, ὅπου ἦν συναγωγὴ τῶν Ἰουδαίων. κατὰ δὲ τὸ εἰωθὸς τῷ Παύλῳ εἰσῆλθεν πρὸς αὐτοὺς καὶ ἐπὶ σάββατα τρία διελέξατο αὐτοῖς ἀπὸ τῶν γραφῶν, διανοίγων καὶ παρατιθέμενος ὅτι τὸν χριστὸν ἔδει παθεῖν καὶ ἀναστῆναι ἐκ νεκρῶν, καὶ ὅτι οὗτός ἐστιν ὁ χριστός, ὁ Ἰησοῦς ὃν ἐγὼ καταγγέλλω ὑμῖν. καί τινες ἐξ αὐτῶν ἐπείσθησαν καὶ προσεκληρώθησαν τῷ Παύλῳ καὶ τῷ Σιλᾷ, τῶν τε σεβομένων Ἑλλήνων πλῆθος πολὺ γυναικῶν τε τῶν πρώτων οὐκ ὀλίγαι. ζηλώσαντες δὲ οἱ Ἰουδαῖοι καὶ προσλαβόμενοι τῶν ἀγοραίων ἄνδρας τινὰς πονηροὺς καὶ ὀχλοποιήσαντες ἐθορύβουν τὴν πόλιν, καὶ ἐπιστάντες τῇ οἰκίᾳ Ἰάσονος ἐζήτουν αὐτοὺς προαγαγεῖν εἰς τὸν δῆμον· μὴ εὑρόντες δὲ αὐτοὺς ἔσυρον Ἰάσονα καί τινας ἀδελφοὺς ἐπὶ τοὺς πολιτάρχας, βοῶντες ὅτι Οἱ τὴν οἰκουμένην ἀναστατώσαντες οὗτοι καὶ ἐνθάδε πάρεισιν, οὓς ὑποδέδεκται Ἰάσων· καὶ οὗτοι πάντες ἀπέναντι τῶν δογμάτων Καίσαρος πράσσουσι, βασιλέα ἕτερον λέγοντες εἶναι Ἰησοῦν. ἐτάραξαν δὲ τὸν ὄχλον καὶ τοὺς πολιτάρχας ἀκούοντας ταῦτα, καὶ λαβόντες τὸ ἱκανὸν παρὰ τοῦ Ἰάσονος καὶ τῶν λοιπῶν ἀπέλυσαν αὐτούς.<br><br>Οἱ δὲ ἀδελφοὶ εὐθέως διὰ νυκτὸς ἐξέπεμψαν τόν τε Παῦλον καὶ τὸν Σιλᾶν εἰς Βέροιαν, οἵτινες παραγενόμενοι εἰς τὴν συναγωγὴν τῶν Ἰουδαίων ἀπῄεσαν· οὗτοι δὲ ἦσαν εὐγενέστεροι τῶν ἐν Θεσσαλονίκῃ, οἵτινες ἐδέξαντο τὸν λόγον μετὰ πάσης προθυμίας, τὸ καθ’ ἡμέραν ἀνακρίνοντες τὰς γραφὰς '''''εἰ ἔχοι''''' ταῦτα οὕτως. πολλοὶ μὲν οὖν ἐξ αὐτῶν ἐπίστευσαν, καὶ τῶν Ἑλληνίδων γυναικῶν τῶν εὐσχημόνων καὶ ἀνδρῶν οὐκ ὀλίγοι. ὡς δὲ ἔγνωσαν οἱ ἀπὸ τῆς Θεσσαλονίκης Ἰουδαῖοι ὅτι καὶ ἐν τῇ Βεροίᾳ κατηγγέλη ὑπὸ τοῦ Παύλου ὁ λόγος τοῦ θεοῦ, ἦλθον κἀκεῖ σαλεύοντες καὶ ταράσσοντες τοὺς ὄχλους. εὐθέως δὲ τότε τὸν Παῦλον ἐξαπέστειλαν οἱ ἀδελφοὶ πορεύεσθαι ἕως ἐπὶ τὴν θάλασσαν· ὑπέμεινάν τε ὅ τε Σιλᾶς καὶ ὁ Τιμόθεος ἐκεῖ. οἱ δὲ καθιστάνοντες τὸν Παῦλον ἤγαγον ἕως Ἀθηνῶν, καὶ λαβόντες ἐντολὴν πρὸς τὸν Σιλᾶν καὶ τὸν Τιμόθεον ἵνα ὡς τάχιστα ἔλθωσιν πρὸς αὐτὸν ἐξῄεσαν.<br><br>Ἐν δὲ ταῖς Ἀθήναις ἐκδεχομένου αὐτοὺς τοῦ Παύλου, παρωξύνετο τὸ πνεῦμα αὐτοῦ ἐν αὐτῷ θεωροῦντος κατείδωλον οὖσαν τὴν πόλιν. διελέγετο μὲν οὖν ἐν τῇ συναγωγῇ τοῖς Ἰουδαίοις καὶ τοῖς σεβομένοις καὶ ἐν τῇ ἀγορᾷ κατὰ πᾶσαν ἡμέραν πρὸς τοὺς παρατυγχάνοντας. τινὲς δὲ καὶ τῶν Ἐπικουρείων καὶ Στοϊκῶν φιλοσόφων συνέβαλλον αὐτῷ, καί τινες ἔλεγον· Τί ἂν '''''θέλοι''''' ὁ σπερμολόγος οὗτος λέγειν; οἱ δέ· Ξένων δαιμονίων δοκεῖ καταγγελεὺς εἶναι· ὅτι τὸν Ἰησοῦν καὶ τὴν ἀνάστασιν εὐηγγελίζετο. ἐπιλαβόμενοί τε αὐτοῦ ἐπὶ τὸν Ἄρειον Πάγον ἤγαγον, λέγοντες· Δυνάμεθα γνῶναι τίς ἡ καινὴ αὕτη ἡ ὑπὸ σοῦ λαλουμένη διδαχή; ξενίζοντα γάρ τινα εἰσφέρεις εἰς τὰς ἀκοὰς ἡμῶν· βουλόμεθα οὖν γνῶναι τίνα θέλει ταῦτα εἶναι. Ἀθηναῖοι δὲ πάντες καὶ οἱ ἐπιδημοῦντες ξένοι εἰς οὐδὲν ἕτερον ηὐκαίρουν ἢ λέγειν τι ἢ ἀκούειν τι καινότερον.<br><br>Σταθεὶς δὲ Παῦλος ἐν μέσῳ τοῦ Ἀρείου Πάγου ἔφη· Ἄνδρες Ἀθηναῖοι, κατὰ πάντα ὡς δεισιδαιμονεστέρους ὑμᾶς θεωρῶ· διερχόμενος γὰρ καὶ ἀναθεωρῶν τὰ σεβάσματα ὑμῶν εὗρον καὶ βωμὸν ἐν ᾧ ἐπεγέγραπτο· Ἀγνώστῳ θεῷ. ὃ οὖν ἀγνοοῦντες εὐσεβεῖτε, τοῦτο ἐγὼ καταγγέλλω ὑμῖν. ὁ θεὸς ὁ ποιήσας τὸν κόσμον καὶ πάντα τὰ ἐν αὐτῷ, οὗτος οὐρανοῦ καὶ γῆς ὑπάρχων κύριος οὐκ ἐν χειροποιήτοις ναοῖς κατοικεῖ οὐδὲ ὑπὸ χειρῶν ἀνθρωπίνων θεραπεύεται προσδεόμενός τινος, αὐτὸς διδοὺς πᾶσι ζωὴν καὶ πνοὴν καὶ τὰ πάντα· ἐποίησέν τε ἐξ ἑνὸς πᾶν ἔθνος ἀνθρώπων κατοικεῖν ἐπὶ παντὸς προσώπου τῆς γῆς, ὁρίσας προστεταγμένους καιροὺς καὶ τὰς ὁροθεσίας τῆς κατοικίας αὐτῶν, ζητεῖν τὸν θεὸν εἰ ἄρα γε '''''ψηλαφήσειαν''''' αὐτὸν καὶ '''''εὕροιεν''''', καί γε οὐ μακρὰν ἀπὸ ἑνὸς ἑκάστου ἡμῶν ὑπάρχοντα. ἐν αὐτῷ γὰρ ζῶμεν καὶ κινούμεθα καὶ ἐσμέν, ὡς καί τινες τῶν καθ’ ὑμᾶς ποιητῶν εἰρήκασιν· Τοῦ γὰρ καὶ γένος ἐσμέν. γένος οὖν ὑπάρχοντες τοῦ θεοῦ οὐκ ὀφείλομεν νομίζειν χρυσῷ ἢ ἀργύρῳ ἢ λίθῳ, χαράγματι τέχνης καὶ ἐνθυμήσεως ἀνθρώπου, τὸ θεῖον εἶναι ὅμοιον. τοὺς μὲν οὖν χρόνους τῆς ἀγνοίας ὑπεριδὼν ὁ θεὸς τὰ νῦν παραγγέλλει τοῖς ἀνθρώποις πάντας πανταχοῦ μετανοεῖν, καθότι ἔστησεν ἡμέραν ἐν ᾗ μέλλει κρίνειν τὴν οἰκουμένην ἐν δικαιοσύνῃ ἐν ἀνδρὶ ᾧ ὥρισεν, πίστιν παρασχὼν πᾶσιν ἀναστήσας αὐτὸν ἐκ νεκρῶν.<br><br>Ἀκούσαντες δὲ ἀνάστασιν νεκρῶν οἱ μὲν ἐχλεύαζον οἱ δὲ εἶπαν Ἀκουσόμεθά σου περὶ τούτου καὶ πάλιν. οὕτως ὁ Παῦλος ἐξῆλθεν ἐκ μέσου αὐτῶν· τινὲς δὲ ἄνδρες κολληθέντες αὐτῷ ἐπίστευσαν, ἐν οἷς καὶ Διονύσιος ὁ Ἀρεοπαγίτης καὶ γυνὴ ὀνόματι Δάμαρις καὶ ἕτεροι σὺν αὐτοῖς.
==Grammatical Breakdown==
===The Optative===
# Acts 17:11 — εἴ ἔχοι (might be / were so)
#* '''Verse''': "...'''whether''' those things '''were''' so.".
#* '''Usage''': Oblique optative used in indirect discourse or indirect questions. It captures the Bereans' eager search of Scripture to confirm whether Paul's teaching aligned with God's Word.
# Acts 17:18 — θέλοι (might wish / desire)
#* '''Verse''': "What '''will''' this babbler say?"
#* '''Usage''': Potential optative (with the particle ἄν). The philosophers use it to express profound confusion regarding what Paul is communicating.
# Acts 17:27 — ψηλαφήσειαν (might feel after / grope)
#* '''Verse''': "That they should seek the Lord, if haply they '''might feel after''' him..."
#* '''Usage''': Optative of contingent purpose (4th-class protasis). It describes humanity's blind, uncertain groping or searching for God in the dark.
# Acts 17:27 — εὕροιεν (might find)
#* '''Verse''': "...and '''find''' him, though he be not far from every one of us:"
#* '''Usage''': Compound protasis, continuing the doubtful condition from the previous clause—expressing the possibility, though not certainty by human effort alone, of finding God
===Idioms & Advanced Vocabulary===
Politarchas
===Advanced Verbal Syntax===
* Ἐν δὲ ταῖς Ἀθήναις ἐκδεχομένου αὐτοὺς τοῦ Παύλου, παρωξύνετο τὸ πνεῦμα αὐτοῦ ἐν αὐτῷ θεωροῦντος κατείδωλον οὖσαν τὴν πόλιν.
===Johannine / Markan vs. Lukan Style===
Saint Mark and John use a lot of indicative and subjunctive verbs, while Saint Luke uses sophisticated Koine prose, such as more optatives, genitive absolutes, etc.
k9uphj5oreou3wn3y6y31c0k9wyc2e2
Koine Greek/Adjectives
0
486340
4675954
2026-10-14T00:44:53Z
It-is-Truly-Meet
3624460
https://pressbooks.pub/ancientgreek/chapter/29/ and https://pressbooks.pub/ancientgreek/chapter/30/
4675954
wikitext
text/x-wiki
Adjectives describe or further define nouns (and pronouns), e.g., "Plato is '''wise'''." English adjectives are indeclinable, but Greek ones must agree with their noun in gender, number, and case (except for σῦφαρ, "decrepit").
They have the same 3 declensions and the same persistent accent rules that are used by nouns. Furthermore, just as each noun belongs to a particular declension, each adjective belongs to a specific declension family or grouping. There are 4 main declension families:
* Three-Ending 1st and 2nd Declension Adjectives (2-1-2)
* Two-Ending 2nd Declension Adjectives (2-2)
* Two-Ending 3rd Declension Adjectives (3-3)
* Three-Ending 1st and 3rd Declension Adjectives (3-1-3)
In order to make clear the declension family to which a given adjective belongs, each is listed with all of its NOMINATIVE SINGULAR forms in a vocabulary entry or lexicon. For example:
Nominative singular forms in –ος, –η (-ᾱ), –ον
Three-Ending 1st and 2nd Declension Adjective (2-1-2)
Nominative singular forms in –ος, –ον
Two-Ending 2nd Declension Adjective (2-2)
Nominative singular forms in –ς, —
Two-Ending 3rd Declension Adjective (3-3)
Nominative singular forms in –ς, –α, —
Three-Ending 1st and 3rd Declension Adjectives (3-1-3)
In this lesson, we review the most common type of adjective: Three-Ending 1st and 2nd Declension (2-1-2)
Three-Ending Adjectives: 1st and 2nd Declension (2-1-2)
The vast majority of adjectives use MASCULINE and NEUTER 2nd DECLENSION endings when modifying nouns of these genders, and 1st DECLENSION endings when modifying FEMININE nouns. This pattern is similar to that used by the pronouns such as αὐτός αὐτή αὐτό and ἐκεῖνος ἐκείνη ἐκεῖνο, though with –ον in the nominative/accusative singular of the neuter.
ἀγαθός, -ή, -όν good, brave, noble (S 287; GPH p. 21)
Singular:
M F N
Nominative ἀγαθός ἀγαθή ἀγαθόν
Genitive ἀγαθοῦ ἀγαθῆς ἀγαθοῦ
Dative ἀγαθῷ ἀγαθῇ ἀγαθῷ
Accusative ἀγαθόν ἀγαθήν ἀγαθόν
Plural:
M F N
Nominative ἀγαθοί ἀγαθαί ἀγαθά
Genitive ἀγαθῶν ἀγαθῶν ἀγαθῶν
Dative ἀγαθοῖς ἀγαθαῖς ἀγαθοῖς
Accusative ἀγαθούς ἀγαθάς ἀγαθά
Stems in –ε, –ι or –ρ
If the stem of the adjective ends in –ε, –ι or –ρ, the singular forms of the 1st DECLENSION change the –η– to –ᾱ-. Note that this change matches that of 1st DECLENSION NOUNS.
δίκαιος, -α , -ον just (S 287; GPH p. 22)
Singular:
M F N
Nominative δίκαιος δικαία δίκαιον
Genitive δικαίου δικαίας δικαίου
Dative δικαίῳ δικαίᾳ δικαίῳ
Accusative δίκαιον δικαίαν δίκαιον
Plural:
M F N
Nominative δίκαιοι δίκαιαι δίκαια
Genitive δικαίων δικαίων δικαίων
Dative δικαίοις δικαίαις δικαίοις
Accusative δικαίους δικαίας δίκαια
Note that the FEMININE GENITIVE PLURAL form, δικαίων, does not follow the rule for 1st declension nouns, namely that the genitive plural ends in –ῶν. For adjectives, if ALL THREE GENDERS share the same form for the GENITIVE PLURAL (e.g., δικαιων), then the feminine form is regularized to follow the same accent pattern as the masculine and neuter.
Big and Many
Two common adjectives of the 2-1-2 type show additional small changes:
μέγας, μεγάλη, μέγα big
πολύς, πολλή, πολύ much, many
μέγας, μεγάλη, μέγα (stem: μεγαλ-) big (S 311; GPH p. 34)
Singular:
M F N
Nominative μέγας μεγάλη μέγα
Genitive μεγάλου μεγάλης μεγάλου
Dative μεγάλῳ μεγάλῃ μεγάλῳ
Accusative μέγαν μεγάλην μέγα
Plural:
M F N
Nominative μεγάλοι μεγάλαι μεγάλα
Genitive μεγάλων μεγάλων μεγάλων
Dative μεγάλοις μεγάλαις μεγάλοις
Accusative μεγάλους μεγάλας μεγάλα
Note that except for the singular forms μέγας, μέγαν, and μέγα, the adjective declines as a regular 2-1-2 adjective.
πολύς, πολλή, πολύ (stem: πολλ-) much, many (S 311; GPH p. 33)
Singular:
M F N
Nominative πολύς πολλή πολύ
Genitive πολλοῦ πολλῆς πολλοῦ
Dative πολλῷ πολλῇ πολλῷ
Accusative πολύν πολλήν πολύ
Plural:
M F N
Nominative πολλοί πολλαί πολλά
Genitive πολλῶν πολλῶν πολλῶν
Dative πολλοῖς πολλαῖς πολλοῖς
Accusative πολλούς πολλάς πολλά
Note that except for the singular forms πολύς, πολύν, and πολύ, the adjective declines as a regular 2-1-2 adjective.
Contract Adjectives
A handful of adjectives that end in –εος, –εα, –εον contract in Attic Greek, producing the endings –ους, –η, –ουν (S 290). There is one example from our vocabulary list:
χαλκοῦς -ῆ -οῦν (stem: χαλκέ-) bronze
Singular:
M F N
Nominative χαλκοῦς χαλκῆ χαλκοῦν
Genitive χαλκοῦ χαλκῆς χαλκοῦ
Dative χαλκῷ χαλκῇ χαλκῷ
Accusative χαλκοῦν χαλκῆν χαλκοῦν
Plural:
M F N
Nominative χαλκοῖ χαλκαῖ χαλκᾶ
Genitive χαλκῶν χαλκῶν χαλκῶν
Dative χαλκοῖς χαλκαῖς χαλκοῖς
Accusative χαλκοῦς χαλκᾶς χαλκᾶ
Usage
Depending on its placement, a Greek adjective has three possible functions.
1. Attributive Position
Greek adjectives describe nouns when they are in the attributive position:
ὁ κακὸς βασιλεύς
the bad king
ὁ βασιλεὺς ὁ κακός
the bad king
βασιλεὺς ὁ κακός
the bad king
κακὸς βασιλεύς
a bad king
Note that while the adjective modifies its noun in gender, number, and case, it does not necessarily modify the noun in declension! βασιλεύς is 3rd Declension, but κακός is 2nd Declension.
2. Predicate Position
Outside the attributive position, Greek adjectives function as predicates to the noun:
ὁ βασιλεύς κακός.
The king (is) bad.
αἱ θλίψεις ποιοῦσι τὸν βασιλέα κακόν.
Troubles make the king bad.
3. Stand Alone (Substantive)
Greek routinely uses adjectives substantively:
ὁ κακός
the bad man, the bad person
κακός
a bad man, a bad person
οἱ κακοί
the bad men, the bad people
If the definite article is neuter singular – or occasionally neuter plural – the substantive can serve as an abstract noun:
τὸ κακόν
the bad thing; evil
τὸ ἄδικον
the unjust thing; injustice
τὸ καλόν
the beautiful; beauty
Adjectives: Other Declension Families
We have already discussed the most common declension grouping for adjectives: Three-Ending 1st and 2nd Declension Adjectives (2-1-2). In this chapter, we cover the three other declension families:
Two-Ending 2nd Declension Adjectives (2-2)
Two-Ending 3rd Declension Adjectives (3-3)
Three-Ending 1st and 3rd Declension Adjectives (3-1-3)
Two-Ending Adjectives: 2nd Declension (2-2)
A handful of adjectives, usually compounds, use 2nd DECLENSION endings for ALL GENDERS. For these adjectives:
Both the MASCULINE and FEMININE forms share the SAME ENDINGS as 2nd DECLENSION MASCULINE nouns.
The NEUTER form shares the same endings as 2nd DECLENSION NEUTER nouns.
ἄδικος -ον unjust (S 289; GPH p. 24)
Singular
M/F N
Nominative ἄδικος ἄδικον
Genitive ἀδίκου ἀδίκου
Dative ἀδίκῳ ἀδίκῳ
Accusative ἄδικον ἄδικον
Plural
M/F N
Nominative ἄδικοι ἄδικα
Genitive ἀδίκων ἀδίκων
Dative ἀδίκοις ἀδίκοις
Accusative ἀδίκους ἄδικα
Two-Ending Adjectives: 3rd Declension (3-3)
Another small group of adjectives uses 3rd DECLENSION endings for ALL GENDERS. For these adjectives:
Both the MASCULINE and FEMININE forms share the SAME ENDINGS as 3rd DECLENSION MASCULINE/FEMININE nouns.
The NEUTER form uses the same endings as 3rd DECLENSION NEUTER nouns.
These adjectives tend to fall into one of two groups:
Adjectives ending in –ης –ες.
These adjectives have a stem ending in –εσ.
Adjectives ending in –(ί)ων –(ι)ον.
These adjectives have a stem ending in –(ι)ον.
1. Adjectives in –ης –ες.
ἀληθής -ές (stem: ἀληθέσ-) true (S 292; GPH p. 26)
Singular
M/F N
Nominative ἀληθής ἀληθές
Genitive ἀληθοῦς ἀληθοῦς
Dative ἀληθεῖ ἀληθεῖ
Accusative ἀληθῆ ἀληθές
Plural
M/F N
Nominative ἀληθεῖς ἀληθῆ
Genitive ἀληθῶν ἀληθῶν
Dative ἀληθέσι ἀληθέσι
Accusative ἀληθεῖς ἀληθῆ
The contractions that produce the inflection of –ης –ες adjectives are similar to nouns in –εσ that we have already studied, e.g. Σωκράτης, -ους (stem: Σωκράτεσ-) and ἔτος -ους (stem: ἔτεσ-). The main differences are:
For the NEUTER of 3-3 adjectives, –ες does not become –ος in the nominative and accusative singular.
The MASCULINE/FEMININE accusative plural is identical to the nominative plural: –έσες → –εῖς.
That said, adjectives of this type are fairly rare. The only other common adjective inflected like ἀληθής -ές is σαφής -ές clear.
2. Adjectives ending in –(ί)ων –(ι)ον.
βελτίων -ον (stem: βέλτιον-) better (S 293; GPH p. 11)
Singular
M/F N
Nominative βελτίων βέλτιον
Genitive βελτίονος βελτίονος
Dative βελτίονι βελτίονι
Accusative βελτίονα βέλτιον
Plural
M/F N
Nominative βελτίονες βελτίονα
Genitive βελτιόνων βελτιόνων
Dative βελτίοσι βελτίοσι
Accusative βελτίονας βελτίονα
Notice that the inflection of –(ί)ων –(ι)ον. adjectives is similar to nouns ending in –(ι)ον. that we have already studied, e.g. δαίμων -ονος. Note that:
In the MASCULINE/FEMININE nominative singular, –(ι)ονς becomes –(ί)ων. due to the loss of the sigma, and subsequent compensatory lengthening.
In the dative plural of all genders, the –ν of –ονσι has dropped out, leaving only –οσι.
Three-Ending Adjectives: 1st and 3rd Declension (3-1-3)
The final group of adjectives uses 3rd DECLENSION endings for MASCULINE and NEUTER, but 1st DECLENSION endings for FEMININE.
Note, however, that when modifying a FEMININE noun, these adjectives use SHORT –ᾰ– in the NOMINATIVE and ACCUSATIVE SINGULAR. This change must be remembered, since it affects the ACCENT of these adjectives. These adjectives tend to fall into one of two groups:
Adjectives ending in –ς –σα –ν.
These adjectives have a stem ending in –ντ.
Adjectives ending in –ύς –εῖα –ύ.
These adjectives have a stem ending in –ε.
1. Adjectives in –ς –σα –ν.
While a handful of adjectives have their stems ending in –ντ, we have already encountered the most common one: πᾶς πᾶσα πᾶν all, every, whole (S 299; GPH p. 30). No others appear in our vocabulary lists.
Singular:
M F N
Nominative πᾶς πᾶσα πᾶν
Genitive παντός πάσης παντός
Dative παντί πάσῃ παντί
Accusative πάντα πᾶσαν πᾶν
Plural:
M F N
Nominative πάντες πᾶσαι πάντα
Genitive πάντων πασῶν πάντων
Dative πᾶσι πάσαις πᾶσι
Accusative πάντας πάσας πάντα
2. Adjectives in –ύς –εῖα –ύ.
As you study this inflection pattern, note the following:
Remember that if the stem of the adjective ends in –ε, –ι or –ρ, ᾱ appears instead of η in feminine singular forms. The use of –ᾱ– affects only the GENITIVE and DATIVE SINGULAR for these adjectives, however. The nominative and accusative singular already have short –ᾰ-.
In the nominative and accusative singular of the masculine and neuter, the stem ends in –υ.
The masculine accusative singular ending is –ν.
The masculine nominative and accusative plural are identical: see, e.g., ἡδεῖς.
Not all of the expected contractions occur: see, e.g., ἡδέος, ἡδέων, and ἡδέα.
All adjectives of this declension family share the same persistent accent.
ἡδύς -εῖα -ύ (stem: ἡδέ-) sweet (S 297; GPH p. 32)
Singular:
M F N
Nominative ἡδύς ἡδεῖα ἡδύ
Genitive ἡδέος ἡδείας ἡδέος
Dative ἡδεῖ ἡδείᾳ ἡδεῖ
Accusative ἡδύν ἡδεῖαν ἡδύ
Plural:
M F N
Nominative ἡδεῖς ἡδεῖαι ἡδέα
Genitive ἡδέων ἡδειῶν ἡδέων
Dative ἡδέσι ἡδείαις ἡδέσι
Accusative ἡδεῖς ἡδείας ἡδέα
Bringing It All Together
In the following charts you can see that you have now learned the endings of most nouns, adjectives, and pronouns that you will encounter in Greek. (To download this chart, click here: Greek Nouns Adj Pronouns Master List.)
98zjsrwnjjtbue5hqqn966qfvcso7sy
4675960
4675954
2026-10-14T00:54:41Z
It-is-Truly-Meet
3624460
4675960
wikitext
text/x-wiki
Adjectives describe or further define nouns (and pronouns), e.g., "Plato is '''wise'''." English adjectives are indeclinable, but Greek ones must agree with their noun in gender, number, and case (except for σῦφαρ, "decrepit").
They have the same 3 declensions and the same persistent accent rules that are used by nouns. Furthermore, just as each noun belongs to a particular declension, each adjective belongs to a specific declension family or grouping. There are 4 main declension families:
* Three-Ending 1st and 2nd Declension Adjectives (2-1-2)
* Two-Ending 2nd Declension Adjectives (2-2)
* Two-Ending 3rd Declension Adjectives (3-3)
* Three-Ending 1st and 3rd Declension Adjectives (3-1-3)
In order to make clear the declension family to which a given adjective belongs, each is listed with all of its NOMINATIVE SINGULAR forms in a vocabulary entry or lexicon. For example:
* Nominative singular forms in –ος, –η (-ᾱ), –ον
** Three-Ending 1st and 2nd Declension Adjective (2-1-2)
* Nominative singular forms in –ος, –ον
** Two-Ending 2nd Declension Adjective (2-2)
* Nominative singular forms in –ς, —
** Two-Ending 3rd Declension Adjective (3-3)
* Nominative singular forms in –ς, –α, —
** Three-Ending 1st and 3rd Declension Adjectives (3-1-3)
In this lesson, we review the most common type of adjective: Three-Ending 1st and 2nd Declension (2-1-2)
==Three-Ending Adjectives: 1st and 2nd Declension (2-1-2)==
The vast majority of adjectives use MASCULINE and NEUTER 2nd DECLENSION endings when modifying nouns of these genders, and 1st DECLENSION endings when modifying FEMININE nouns. This pattern is similar to that used by the pronouns such as αὐτός αὐτή αὐτό and ἐκεῖνος ἐκείνη ἐκεῖνο, though with –ον in the nominative/accusative singular of the neuter.
ἀγαθός, -ή, -όν good, brave, noble (S 287; GPH p. 21)
Singular:
M F N
Nominative ἀγαθός ἀγαθή ἀγαθόν
Genitive ἀγαθοῦ ἀγαθῆς ἀγαθοῦ
Dative ἀγαθῷ ἀγαθῇ ἀγαθῷ
Accusative ἀγαθόν ἀγαθήν ἀγαθόν
Plural:
M F N
Nominative ἀγαθοί ἀγαθαί ἀγαθά
Genitive ἀγαθῶν ἀγαθῶν ἀγαθῶν
Dative ἀγαθοῖς ἀγαθαῖς ἀγαθοῖς
Accusative ἀγαθούς ἀγαθάς ἀγαθά
Stems in –ε, –ι or –ρ
If the stem of the adjective ends in –ε, –ι or –ρ, the singular forms of the 1st DECLENSION change the –η– to –ᾱ-. Note that this change matches that of 1st DECLENSION NOUNS.
δίκαιος, -α , -ον just (S 287; GPH p. 22)
Singular:
M F N
Nominative δίκαιος δικαία δίκαιον
Genitive δικαίου δικαίας δικαίου
Dative δικαίῳ δικαίᾳ δικαίῳ
Accusative δίκαιον δικαίαν δίκαιον
Plural:
M F N
Nominative δίκαιοι δίκαιαι δίκαια
Genitive δικαίων δικαίων δικαίων
Dative δικαίοις δικαίαις δικαίοις
Accusative δικαίους δικαίας δίκαια
Note that the FEMININE GENITIVE PLURAL form, δικαίων, does not follow the rule for 1st declension nouns, namely that the genitive plural ends in –ῶν. For adjectives, if ALL THREE GENDERS share the same form for the GENITIVE PLURAL (e.g., δικαιων), then the feminine form is regularized to follow the same accent pattern as the masculine and neuter.
===Big and Many===
Two common adjectives of the 2-1-2 type show additional small changes:
μέγας, μεγάλη, μέγα big
πολύς, πολλή, πολύ much, many
μέγας, μεγάλη, μέγα (stem: μεγαλ-) big (S 311; GPH p. 34)
Singular:
M F N
Nominative μέγας μεγάλη μέγα
Genitive μεγάλου μεγάλης μεγάλου
Dative μεγάλῳ μεγάλῃ μεγάλῳ
Accusative μέγαν μεγάλην μέγα
Plural:
M F N
Nominative μεγάλοι μεγάλαι μεγάλα
Genitive μεγάλων μεγάλων μεγάλων
Dative μεγάλοις μεγάλαις μεγάλοις
Accusative μεγάλους μεγάλας μεγάλα
Note that except for the singular forms μέγας, μέγαν, and μέγα, the adjective declines as a regular 2-1-2 adjective.
πολύς, πολλή, πολύ (stem: πολλ-) much, many (S 311; GPH p. 33)
Singular:
M F N
Nominative πολύς πολλή πολύ
Genitive πολλοῦ πολλῆς πολλοῦ
Dative πολλῷ πολλῇ πολλῷ
Accusative πολύν πολλήν πολύ
Plural:
M F N
Nominative πολλοί πολλαί πολλά
Genitive πολλῶν πολλῶν πολλῶν
Dative πολλοῖς πολλαῖς πολλοῖς
Accusative πολλούς πολλάς πολλά
Note that except for the singular forms πολύς, πολύν, and πολύ, the adjective declines as a regular 2-1-2 adjective.
===Contract Adjectives===
A handful of adjectives that end in –εος, –εα, –εον contract in Attic Greek, producing the endings –ους, –η, –ουν (S 290). There is one example from our vocabulary list:
χαλκοῦς -ῆ -οῦν (stem: χαλκέ-) bronze
Singular:
M F N
Nominative χαλκοῦς χαλκῆ χαλκοῦν
Genitive χαλκοῦ χαλκῆς χαλκοῦ
Dative χαλκῷ χαλκῇ χαλκῷ
Accusative χαλκοῦν χαλκῆν χαλκοῦν
Plural:
M F N
Nominative χαλκοῖ χαλκαῖ χαλκᾶ
Genitive χαλκῶν χαλκῶν χαλκῶν
Dative χαλκοῖς χαλκαῖς χαλκοῖς
Accusative χαλκοῦς χαλκᾶς χαλκᾶ
==Usage==
Depending on its placement, a Greek adjective has three possible functions.
===Attributive Position===
Greek adjectives describe nouns when they are in the attributive position:
ὁ κακὸς βασιλεύς
the bad king
ὁ βασιλεὺς ὁ κακός
the bad king
βασιλεὺς ὁ κακός
the bad king
κακὸς βασιλεύς
a bad king
Note that while the adjective modifies its noun in gender, number, and case, it does not necessarily modify the noun in declension! βασιλεύς is 3rd Declension, but κακός is 2nd Declension.
===Predicate Position===
Outside the attributive position, Greek adjectives function as predicates to the noun:
ὁ βασιλεύς κακός.
The king (is) bad.
αἱ θλίψεις ποιοῦσι τὸν βασιλέα κακόν.
Troubles make the king bad.
===Stand Alone (Substantive) ===
Greek routinely uses adjectives substantively:
ὁ κακός
the bad man, the bad person
κακός
a bad man, a bad person
οἱ κακοί
the bad men, the bad people
If the definite article is neuter singular – or occasionally neuter plural – the substantive can serve as an abstract noun:
τὸ κακόν
the bad thing; evil
τὸ ἄδικον
the unjust thing; injustice
τὸ καλόν
the beautiful; beauty
=Adjectives: Other Declension Families=
We have already discussed the most common declension grouping for adjectives: Three-Ending 1st and 2nd Declension Adjectives (2-1-2). In this chapter, we cover the three other declension families:
* Two-Ending 2nd Declension Adjectives (2-2)
* Two-Ending 3rd Declension Adjectives (3-3)
* Three-Ending 1st and 3rd Declension Adjectives (3-1-3)
==Two-Ending Adjectives: 2nd Declension (2-2)==
A handful of adjectives, usually compounds, use 2nd DECLENSION endings for ALL GENDERS. For these adjectives:
Both the MASCULINE and FEMININE forms share the SAME ENDINGS as 2nd DECLENSION MASCULINE nouns.
The NEUTER form shares the same endings as 2nd DECLENSION NEUTER nouns.
ἄδικος -ον unjust (S 289; GPH p. 24)
Singular
M/F N
Nominative ἄδικος ἄδικον
Genitive ἀδίκου ἀδίκου
Dative ἀδίκῳ ἀδίκῳ
Accusative ἄδικον ἄδικον
Plural
M/F N
Nominative ἄδικοι ἄδικα
Genitive ἀδίκων ἀδίκων
Dative ἀδίκοις ἀδίκοις
Accusative ἀδίκους ἄδικα
==Two-Ending Adjectives: 3rd Declension (3-3)==
Another small group of adjectives uses 3rd DECLENSION endings for ALL GENDERS. For these adjectives:
Both the MASCULINE and FEMININE forms share the SAME ENDINGS as 3rd DECLENSION MASCULINE/FEMININE nouns.
The NEUTER form uses the same endings as 3rd DECLENSION NEUTER nouns.
These adjectives tend to fall into one of two groups:
Adjectives ending in –ης –ες.
These adjectives have a stem ending in –εσ.
Adjectives ending in –(ί)ων –(ι)ον.
These adjectives have a stem ending in –(ι)ον.
===1. Adjectives in –ης –ες.===
ἀληθής -ές (stem: ἀληθέσ-) true (S 292; GPH p. 26)
Singular
M/F N
Nominative ἀληθής ἀληθές
Genitive ἀληθοῦς ἀληθοῦς
Dative ἀληθεῖ ἀληθεῖ
Accusative ἀληθῆ ἀληθές
Plural
M/F N
Nominative ἀληθεῖς ἀληθῆ
Genitive ἀληθῶν ἀληθῶν
Dative ἀληθέσι ἀληθέσι
Accusative ἀληθεῖς ἀληθῆ
The contractions that produce the inflection of –ης –ες adjectives are similar to nouns in –εσ that we have already studied, e.g. Σωκράτης, -ους (stem: Σωκράτεσ-) and ἔτος -ους (stem: ἔτεσ-). The main differences are:
For the NEUTER of 3-3 adjectives, –ες does not become –ος in the nominative and accusative singular.
The MASCULINE/FEMININE accusative plural is identical to the nominative plural: –έσες → –εῖς.
That said, adjectives of this type are fairly rare. The only other common adjective inflected like ἀληθής -ές is σαφής -ές clear.
===2. Adjectives ending in –(ί)ων –(ι)ον.===
βελτίων -ον (stem: βέλτιον-) better (S 293; GPH p. 11)
Singular
M/F N
Nominative βελτίων βέλτιον
Genitive βελτίονος βελτίονος
Dative βελτίονι βελτίονι
Accusative βελτίονα βέλτιον
Plural
M/F N
Nominative βελτίονες βελτίονα
Genitive βελτιόνων βελτιόνων
Dative βελτίοσι βελτίοσι
Accusative βελτίονας βελτίονα
Notice that the inflection of –(ί)ων –(ι)ον. adjectives is similar to nouns ending in –(ι)ον. that we have already studied, e.g. δαίμων -ονος. Note that:
In the MASCULINE/FEMININE nominative singular, –(ι)ονς becomes –(ί)ων. due to the loss of the sigma, and subsequent compensatory lengthening.
In the dative plural of all genders, the –ν of –ονσι has dropped out, leaving only –οσι.
==Three-Ending Adjectives: 1st and 3rd Declension (3-1-3)==
The final group of adjectives uses 3rd DECLENSION endings for MASCULINE and NEUTER, but 1st DECLENSION endings for FEMININE.
Note, however, that when modifying a FEMININE noun, these adjectives use SHORT –ᾰ– in the NOMINATIVE and ACCUSATIVE SINGULAR. This change must be remembered, since it affects the ACCENT of these adjectives. These adjectives tend to fall into one of two groups:
* Adjectives ending in –ς –σα –ν.
These adjectives have a stem ending in –ντ.
* Adjectives ending in –ύς –εῖα –ύ.
These adjectives have a stem ending in –ε.
===1. Adjectives in –ς –σα –ν.===
While a handful of adjectives have their stems ending in –ντ, we have already encountered the most common one: πᾶς πᾶσα πᾶν all, every, whole (S 299; GPH p. 30). No others appear in our vocabulary lists.
Singular:
M F N
Nominative πᾶς πᾶσα πᾶν
Genitive παντός πάσης παντός
Dative παντί πάσῃ παντί
Accusative πάντα πᾶσαν πᾶν
Plural:
M F N
Nominative πάντες πᾶσαι πάντα
Genitive πάντων πασῶν πάντων
Dative πᾶσι πάσαις πᾶσι
Accusative πάντας πάσας πάντα
===2. Adjectives in –ύς –εῖα –ύ.===
As you study this inflection pattern, note the following:
Remember that if the stem of the adjective ends in –ε, –ι or –ρ, ᾱ appears instead of η in feminine singular forms. The use of –ᾱ– affects only the GENITIVE and DATIVE SINGULAR for these adjectives, however. The nominative and accusative singular already have short –ᾰ-.
In the nominative and accusative singular of the masculine and neuter, the stem ends in –υ.
The masculine accusative singular ending is –ν.
The masculine nominative and accusative plural are identical: see, e.g., ἡδεῖς.
Not all of the expected contractions occur: see, e.g., ἡδέος, ἡδέων, and ἡδέα.
All adjectives of this declension family share the same persistent accent.
ἡδύς -εῖα -ύ (stem: ἡδέ-) sweet (S 297; GPH p. 32)
Singular:
M F N
Nominative ἡδύς ἡδεῖα ἡδύ
Genitive ἡδέος ἡδείας ἡδέος
Dative ἡδεῖ ἡδείᾳ ἡδεῖ
Accusative ἡδύν ἡδεῖαν ἡδύ
Plural:
M F N
Nominative ἡδεῖς ἡδεῖαι ἡδέα
Genitive ἡδέων ἡδειῶν ἡδέων
Dative ἡδέσι ἡδείαις ἡδέσι
Accusative ἡδεῖς ἡδείας ἡδέα
=Bringing It All Together=
In the following charts you can see that you have now learned the endings of most nouns, adjectives, and pronouns that you will encounter in Greek.
thal0w90c2khg7a20ne5oiav6ei92iw
4675961
4675960
2026-10-14T00:58:05Z
It-is-Truly-Meet
3624460
Formatting was improved.
4675961
wikitext
text/x-wiki
Adjectives describe or further define nouns (and pronouns), e.g., "Plato is '''wise'''." English adjectives are indeclinable, but Greek ones must agree with their noun in gender, number, and case (except for σῦφαρ, "decrepit").
They have the same 3 declensions and the same persistent accent rules that are used by nouns. Furthermore, just as each noun belongs to a particular declension, each adjective belongs to a specific declension family or grouping. There are 4 main declension families:
* Three-Ending 1st and 2nd Declension Adjectives (2-1-2)
* Two-Ending 2nd Declension Adjectives (2-2)
* Two-Ending 3rd Declension Adjectives (3-3)
* Three-Ending 1st and 3rd Declension Adjectives (3-1-3)
In order to make clear the declension family to which a given adjective belongs, each is listed with all of its NOMINATIVE SINGULAR forms in a vocabulary entry or lexicon. For example:
* Nominative singular forms in –ος, –η (-ᾱ), –ον
** Three-Ending 1st and 2nd Declension Adjective (2-1-2)
* Nominative singular forms in –ος, –ον
** Two-Ending 2nd Declension Adjective (2-2)
* Nominative singular forms in –ς, —
** Two-Ending 3rd Declension Adjective (3-3)
* Nominative singular forms in –ς, –α, —
** Three-Ending 1st and 3rd Declension Adjectives (3-1-3)
In this lesson, we review the most common type of adjective: Three-Ending 1st and 2nd Declension (2-1-2)
==Three-Ending Adjectives: 1st and 2nd Declension (2-1-2)==
The vast majority of adjectives use MASCULINE and NEUTER 2nd DECLENSION endings when modifying nouns of these genders, and 1st DECLENSION endings when modifying FEMININE nouns. This pattern is similar to that used by the pronouns such as αὐτός αὐτή αὐτό and ἐκεῖνος ἐκείνη ἐκεῖνο, though with –ον in the nominative/accusative singular of the neuter.
ἀγαθός, -ή, -όν good, brave, noble (S 287; GPH p. 21)
Singular:
M F N
Nominative ἀγαθός ἀγαθή ἀγαθόν
Genitive ἀγαθοῦ ἀγαθῆς ἀγαθοῦ
Dative ἀγαθῷ ἀγαθῇ ἀγαθῷ
Accusative ἀγαθόν ἀγαθήν ἀγαθόν
Plural:
M F N
Nominative ἀγαθοί ἀγαθαί ἀγαθά
Genitive ἀγαθῶν ἀγαθῶν ἀγαθῶν
Dative ἀγαθοῖς ἀγαθαῖς ἀγαθοῖς
Accusative ἀγαθούς ἀγαθάς ἀγαθά
Stems in –ε, –ι or –ρ
If the stem of the adjective ends in –ε, –ι or –ρ, the singular forms of the 1st DECLENSION change the –η– to –ᾱ-. Note that this change matches that of 1st DECLENSION NOUNS.
δίκαιος, -α , -ον just (S 287; GPH p. 22)
Singular:
M F N
Nominative δίκαιος δικαία δίκαιον
Genitive δικαίου δικαίας δικαίου
Dative δικαίῳ δικαίᾳ δικαίῳ
Accusative δίκαιον δικαίαν δίκαιον
Plural:
M F N
Nominative δίκαιοι δίκαιαι δίκαια
Genitive δικαίων δικαίων δικαίων
Dative δικαίοις δικαίαις δικαίοις
Accusative δικαίους δικαίας δίκαια
Note that the FEMININE GENITIVE PLURAL form, δικαίων, does not follow the rule for 1st declension nouns, namely that the genitive plural ends in –ῶν. For adjectives, if ALL THREE GENDERS share the same form for the GENITIVE PLURAL (e.g., δικαιων), then the feminine form is regularized to follow the same accent pattern as the masculine and neuter.
===Big and Many===
Two common adjectives of the 2-1-2 type show additional small changes:
μέγας, μεγάλη, μέγα big
πολύς, πολλή, πολύ much, many
μέγας, μεγάλη, μέγα (stem: μεγαλ-) big (S 311; GPH p. 34)
Singular:
M F N
Nominative μέγας μεγάλη μέγα
Genitive μεγάλου μεγάλης μεγάλου
Dative μεγάλῳ μεγάλῃ μεγάλῳ
Accusative μέγαν μεγάλην μέγα
Plural:
M F N
Nominative μεγάλοι μεγάλαι μεγάλα
Genitive μεγάλων μεγάλων μεγάλων
Dative μεγάλοις μεγάλαις μεγάλοις
Accusative μεγάλους μεγάλας μεγάλα
Note that except for the singular forms μέγας, μέγαν, and μέγα, the adjective declines as a regular 2-1-2 adjective.
πολύς, πολλή, πολύ (stem: πολλ-) much, many (S 311; GPH p. 33)
Singular:
M F N
Nominative πολύς πολλή πολύ
Genitive πολλοῦ πολλῆς πολλοῦ
Dative πολλῷ πολλῇ πολλῷ
Accusative πολύν πολλήν πολύ
Plural:
M F N
Nominative πολλοί πολλαί πολλά
Genitive πολλῶν πολλῶν πολλῶν
Dative πολλοῖς πολλαῖς πολλοῖς
Accusative πολλούς πολλάς πολλά
Note that except for the singular forms πολύς, πολύν, and πολύ, the adjective declines as a regular 2-1-2 adjective.
===Contract Adjectives===
A handful of adjectives that end in –εος, –εα, –εον contract in Attic Greek, producing the endings –ους, –η, –ουν (S 290). There is one example from our vocabulary list:
χαλκοῦς -ῆ -οῦν (stem: χαλκέ-) bronze
Singular:
M F N
Nominative χαλκοῦς χαλκῆ χαλκοῦν
Genitive χαλκοῦ χαλκῆς χαλκοῦ
Dative χαλκῷ χαλκῇ χαλκῷ
Accusative χαλκοῦν χαλκῆν χαλκοῦν
Plural:
M F N
Nominative χαλκοῖ χαλκαῖ χαλκᾶ
Genitive χαλκῶν χαλκῶν χαλκῶν
Dative χαλκοῖς χαλκαῖς χαλκοῖς
Accusative χαλκοῦς χαλκᾶς χαλκᾶ
==Usage==
Depending on its placement, a Greek adjective has three possible functions.
===Attributive Position===
Greek adjectives describe nouns when they are in the attributive position:
ὁ κακὸς βασιλεύς
the bad king
ὁ βασιλεὺς ὁ κακός
the bad king
βασιλεὺς ὁ κακός
the bad king
κακὸς βασιλεύς
a bad king
Note that while the adjective modifies its noun in gender, number, and case, it does not necessarily modify the noun in declension! βασιλεύς is 3rd Declension, but κακός is 2nd Declension.
===Predicate Position===
Outside the attributive position, Greek adjectives function as predicates to the noun:
ὁ βασιλεύς κακός.
The king (is) bad.
αἱ θλίψεις ποιοῦσι τὸν βασιλέα κακόν.
Troubles make the king bad.
===Stand Alone (Substantive) ===
Greek routinely uses adjectives substantively:
ὁ κακός
the bad man, the bad person
κακός
a bad man, a bad person
οἱ κακοί
the bad men, the bad people
If the definite article is neuter singular – or occasionally neuter plural – the substantive can serve as an abstract noun:
τὸ κακόν
the bad thing; evil
τὸ ἄδικον
the unjust thing; injustice
τὸ καλόν
the beautiful; beauty
==Two-Ending Adjectives: 2nd Declension (2-2)==
A handful of adjectives, usually compounds, use 2nd DECLENSION endings for ALL GENDERS. For these adjectives:
Both the MASCULINE and FEMININE forms share the SAME ENDINGS as 2nd DECLENSION MASCULINE nouns.
The NEUTER form shares the same endings as 2nd DECLENSION NEUTER nouns.
ἄδικος -ον unjust (S 289; GPH p. 24)
Singular
M/F N
Nominative ἄδικος ἄδικον
Genitive ἀδίκου ἀδίκου
Dative ἀδίκῳ ἀδίκῳ
Accusative ἄδικον ἄδικον
Plural
M/F N
Nominative ἄδικοι ἄδικα
Genitive ἀδίκων ἀδίκων
Dative ἀδίκοις ἀδίκοις
Accusative ἀδίκους ἄδικα
==Two-Ending Adjectives: 3rd Declension (3-3)==
Another small group of adjectives uses 3rd DECLENSION endings for ALL GENDERS. For these adjectives:
Both the MASCULINE and FEMININE forms share the SAME ENDINGS as 3rd DECLENSION MASCULINE/FEMININE nouns.
The NEUTER form uses the same endings as 3rd DECLENSION NEUTER nouns.
These adjectives tend to fall into one of two groups:
Adjectives ending in –ης –ες.
These adjectives have a stem ending in –εσ.
Adjectives ending in –(ί)ων –(ι)ον.
These adjectives have a stem ending in –(ι)ον.
===1. Adjectives in –ης –ες.===
ἀληθής -ές (stem: ἀληθέσ-) true (S 292; GPH p. 26)
Singular
M/F N
Nominative ἀληθής ἀληθές
Genitive ἀληθοῦς ἀληθοῦς
Dative ἀληθεῖ ἀληθεῖ
Accusative ἀληθῆ ἀληθές
Plural
M/F N
Nominative ἀληθεῖς ἀληθῆ
Genitive ἀληθῶν ἀληθῶν
Dative ἀληθέσι ἀληθέσι
Accusative ἀληθεῖς ἀληθῆ
The contractions that produce the inflection of –ης –ες adjectives are similar to nouns in –εσ that we have already studied, e.g. Σωκράτης, -ους (stem: Σωκράτεσ-) and ἔτος -ους (stem: ἔτεσ-). The main differences are:
For the NEUTER of 3-3 adjectives, –ες does not become –ος in the nominative and accusative singular.
The MASCULINE/FEMININE accusative plural is identical to the nominative plural: –έσες → –εῖς.
That said, adjectives of this type are fairly rare. The only other common adjective inflected like ἀληθής -ές is σαφής -ές clear.
===2. Adjectives ending in –(ί)ων –(ι)ον.===
βελτίων -ον (stem: βέλτιον-) better (S 293; GPH p. 11)
Singular
M/F N
Nominative βελτίων βέλτιον
Genitive βελτίονος βελτίονος
Dative βελτίονι βελτίονι
Accusative βελτίονα βέλτιον
Plural
M/F N
Nominative βελτίονες βελτίονα
Genitive βελτιόνων βελτιόνων
Dative βελτίοσι βελτίοσι
Accusative βελτίονας βελτίονα
Notice that the inflection of –(ί)ων –(ι)ον. adjectives is similar to nouns ending in –(ι)ον. that we have already studied, e.g. δαίμων -ονος. Note that:
In the MASCULINE/FEMININE nominative singular, –(ι)ονς becomes –(ί)ων. due to the loss of the sigma, and subsequent compensatory lengthening.
In the dative plural of all genders, the –ν of –ονσι has dropped out, leaving only –οσι.
==Three-Ending Adjectives: 1st and 3rd Declension (3-1-3)==
The final group of adjectives uses 3rd DECLENSION endings for MASCULINE and NEUTER, but 1st DECLENSION endings for FEMININE.
Note, however, that when modifying a FEMININE noun, these adjectives use SHORT –ᾰ– in the NOMINATIVE and ACCUSATIVE SINGULAR. This change must be remembered, since it affects the ACCENT of these adjectives. These adjectives tend to fall into one of two groups:
* Adjectives ending in –ς –σα –ν.
These adjectives have a stem ending in –ντ.
* Adjectives ending in –ύς –εῖα –ύ.
These adjectives have a stem ending in –ε.
===1. Adjectives in –ς –σα –ν.===
While a handful of adjectives have their stems ending in –ντ, we have already encountered the most common one: πᾶς πᾶσα πᾶν all, every, whole (S 299; GPH p. 30). No others appear in our vocabulary lists.
Singular:
M F N
Nominative πᾶς πᾶσα πᾶν
Genitive παντός πάσης παντός
Dative παντί πάσῃ παντί
Accusative πάντα πᾶσαν πᾶν
Plural:
M F N
Nominative πάντες πᾶσαι πάντα
Genitive πάντων πασῶν πάντων
Dative πᾶσι πάσαις πᾶσι
Accusative πάντας πάσας πάντα
===2. Adjectives in –ύς –εῖα –ύ.===
As you study this inflection pattern, note the following:
Remember that if the stem of the adjective ends in –ε, –ι or –ρ, ᾱ appears instead of η in feminine singular forms. The use of –ᾱ– affects only the GENITIVE and DATIVE SINGULAR for these adjectives, however. The nominative and accusative singular already have short –ᾰ-.
In the nominative and accusative singular of the masculine and neuter, the stem ends in –υ.
The masculine accusative singular ending is –ν.
The masculine nominative and accusative plural are identical: see, e.g., ἡδεῖς.
Not all of the expected contractions occur: see, e.g., ἡδέος, ἡδέων, and ἡδέα.
All adjectives of this declension family share the same persistent accent.
ἡδύς -εῖα -ύ (stem: ἡδέ-) sweet (S 297; GPH p. 32)
Singular:
M F N
Nominative ἡδύς ἡδεῖα ἡδύ
Genitive ἡδέος ἡδείας ἡδέος
Dative ἡδεῖ ἡδείᾳ ἡδεῖ
Accusative ἡδύν ἡδεῖαν ἡδύ
Plural:
M F N
Nominative ἡδεῖς ἡδεῖαι ἡδέα
Genitive ἡδέων ἡδειῶν ἡδέων
Dative ἡδέσι ἡδείαις ἡδέσι
Accusative ἡδεῖς ἡδείας ἡδέα
==Bringing It All Together==
In the following charts you can see that you have now learned the endings of most nouns, adjectives, and pronouns that you will encounter in Greek.
kj438w0hj481vxmhsyox5q066enx850
Talk:Bookbinding/Thread
1
486341
4675990
2026-10-14T08:09:42Z
~2026-55154-38
3628390
/* What Makes Traditional Bookbinding a Special Craft? */ new section
4675990
wikitext
text/x-wiki
== What Makes Traditional Bookbinding a Special Craft? ==
Traditional bookbinding is a beautiful craft that combines creativity, patience, and practical skills. Handmade books can have unique covers, carefully stitched pages, and long-lasting designs.
I would love to learn more about the tools and materials beginners need to get started. Which bookbinding technique would you recommend learning first?
Share your tips and experiences!
google.com [[Special:Contributions/~2026-55154-38|~2026-55154-38]] ([[User talk:~2026-55154-38|talk]]) 08:09, 14 October 2026 (UTC)
2ndchmdrf31k22bprspc4wavibg7cxc
Relational Database Design/Multivalued dependency
0
486345
4676005
2026-10-14T10:28:37Z
Xieve7
3628394
Created page with "Let <math display="inline">R</math> be a Relation with schema <math display="inline">(R_{1},\cdots, R_{a},\cdots, R_{b},\cdots, R_{c})</math>. <math display="inline">R_{1},\cdots, R_{a}\twoheadrightarrow</math> (multidetermines) <math display="inline">R_{a+1},\cdots, R_{b}</math> in <math display="inline">R</math> if for all tuples <math display="block"> \begin{matrix} (\alpha_{1},\cdots, \alpha_{a}, & \color{red}\alpha_{a+1},\cdots, \alpha_{b},&{\color{red}\alpha_{b+1}..."
4676005
wikitext
text/x-wiki
Let <math display="inline">R</math> be a Relation with schema <math display="inline">(R_{1},\cdots, R_{a},\cdots, R_{b},\cdots, R_{c})</math>.
<math display="inline">R_{1},\cdots, R_{a}\twoheadrightarrow</math> (multidetermines) <math display="inline">R_{a+1},\cdots, R_{b}</math> in <math display="inline">R</math> if for all tuples
<math display="block">
\begin{matrix}
(\alpha_{1},\cdots, \alpha_{a}, & \color{red}\alpha_{a+1},\cdots, \alpha_{b},&{\color{red}\alpha_{b+1},\cdots, \alpha_{c}}),\!\\
(\alpha_{1},\cdots, \alpha_{a},&\color{teal} \beta_{a+1},\cdots, \beta_{b},&{\color{teal} \beta_{b+1},\cdots, \beta_{c}})
\end{matrix}\;\in R
</math>
there exist tuples
<math display="block">
\begin{matrix}
(\alpha_{1},\cdots, \alpha_{a}, &\color{teal} \beta_{a+1},\cdots, \beta_{b},&{\color{red}\alpha_{b+1},\cdots, \alpha_{c}}),\!\\
(\alpha_{1},\cdots, \alpha_{a},&\color{red}\alpha_{a+1},\cdots, \alpha_{b}, & {\color{teal}\beta_{b+1},\cdots, \beta_{c}})
\end{matrix}\;\in R.
</math>
ppav7kxlbe9iy8gaytcrhginzokscci