My company signed up for a $1000/year subscription-based water cooler.- Reddit
1984 Rajneeshee bioterror attack
1984 Rajneeshee bioterror attack | |
---|---|
![]() Four of the restaurants in The Dalles affected by the attack | |
Location | The Dalles, Oregon |
Coordinates | 45°36′4″N121°10′58″W / 45.60111°N 121.18278°WCoordinates: 45°36′4″N121°10′58″W / 45.60111°N 121.18278°W[1] |
Date | August 29 – October 10, 1984 |
Target | Voting population, Wasco County |
Attack type | Bioterrorism |
Weapons | Salmonella enterica Typhimurium |
Non-fatal injuries | 751 people infected, 45 hospitalizations |
Perpetrators | Rajneeshee commune management |
The 1984 Rajneeshee bioterror attack was the food poisoning of 751 individuals in The Dalles, Oregon, through the deliberate contamination of salad bars at ten local restaurants with Salmonella. A leading group of followers of Bhagwan Shree Rajneesh (later known as Osho) called Rajneeshees had hoped to incapacitate the voting population of the city so that their own candidates would win the 1984 Wasco County elections.[2] The incident was the first and single largest bioterrorist attack in United States history.[3][4] The attack is one of only two confirmed terrorist uses of biological weapons to harm humans since 1945, the other being the 2001 anthrax attacks across the USA.[5]
Having previously gained political control of Antelope, Oregon, Rajneesh's followers, who were based in nearby Rajneeshpuram, sought election to two of the three seats on the Wasco County Circuit Court that were up for election in November 1984. Fearing they would not gain enough votes, some Rajneeshpuram officials decided to incapacitate voters in The Dalles, the largest population center in Wasco County. The chosen biological agent was Salmonella enterica Typhimurium, which was first delivered through glasses of water to two County Commissioners and then, on a larger scale, at salad bars and in salad dressing.
As a result of the attack, 751 people contracted salmonellosis, 45 of whom were hospitalized, but none died. Although an initial investigation by the Oregon Public Health Division and the Centers for Disease Control did not rule out deliberate contamination, the agents and contamination were only confirmed a year later. On February 28, 1985, Congressman James H. Weaver gave a speech in the United States House of Representatives in which he "accused the Rajneeshees of sprinkling Salmonella culture on salad bar ingredients in eight restaurants".[6]
At a press conference in September 1985, Rajneesh accused several of his followers of participation in this and other crimes, including an aborted plan in 1985 to assassinate a United States Attorney, and he asked State and Federal authorities to investigate.[7]Oregon Attorney GeneralDavid B. Frohnmayer set up an Interagency Task Force, composed of Oregon State Police and the Federal Bureau of Investigation, and executed search warrants in Rajneeshpuram. A sample of bacteria matching the contaminant that had sickened the town residents was found in a Rajneeshpuram medical laboratory. Two leading Rajneeshpuram officials were convicted on charges of attempted murder and served 29 months of 20-year sentences in a minimum-security federal prison.
Contents
Planning

Several thousand of Rajneesh's followers had moved onto the "Big Muddy Ranch" in rural Wasco County in 1981, where they later incorporated as a city called Rajneeshpuram.[8][9] They had taken political control of the small nearby town of Antelope, Oregon (population 75), the name of which they changed to "Rajneesh".[10] The group had started on friendly terms with the local population, but relations soon degraded because of land use conflicts and the commune's dramatic expansion.[10]
After being denied building permits for Rajneeshpuram, the commune leadership sought to gain political control over the rest of the county by influencing the November 1984 county election.[9] Their goal was to win two of three seats on the Wasco County Circuit Court, as well as the sheriff's office.[2] Their attempts to influence the election included the "Share-a-Home" program, in which they transported thousands of homeless people to Rajneeshpuram and attempted to register them to vote to inflate the constituency of voters for the group's candidates.[11][12] The Wasco county clerk countered this attempt by enforcing a regulation that required all new voters to submit their qualifications when registering to vote.[13]
The commune leadership planned to sicken and incapacitate voters in The Dalles, where most of the voters resided, to sway the election.[14] Approximately twelve people were involved in the plots to employ biological agents, and at least eleven were involved in planning them. No more than four appear to have been involved in development at the Rajneeshpuram medical laboratory; not all of those were necessarily aware of the objectives of their work. At least eight individuals helped spread the bacteria.[11]
The main planners of the attack included Sheela Silverman (Ma Anand Sheela), Rajneesh's chief lieutenant, and Diane Yvonne Onang (Ma Anand Puja), a nurse practitioner and secretary-treasurer of the Rajneesh Medical Corporation.[11][15] They purchased Salmonella bacteria from a medical supply company in Seattle, Washington, and staff cultured it in labs within the commune.[11] They contaminated the produce at the salad bars as a "trial run".[12][16] The group also tried to introduce pathogens into The Dalles' water system.[11] If successful, they planned to use the same techniques closer to Election Day. They did not carry out the second part of the plan. The commune decided to boycott the election when it became clear that those brought in through the "Share-a-Home" program would not be allowed to vote.[12]
Two visiting Wasco County commissioners were infected via glasses of water containing Salmonella bacteria during a visit to Rajneeshpuram on August 29, 1984. Both men fell ill and one was hospitalized. Afterward, members of Sheela's team spread Salmonella on produce in grocery stores and on doorknobs and urinal handles in the county courthouse, but these actions did not produce the desired effects.[5] In September and October 1984, they contaminated the salad bars of 10 local restaurants with Salmonella, infecting 751 people.[17] Forty-five people received hospital treatment; all survived.[18]
The primary delivery tactic involved one member concealing a plastic bag containing a light-brown liquid with the Salmonella bacteria (referred to by the perpetrators as "salsa"[15]), and either spreading it over the food at a salad bar, or pouring it into salad dressing.[19] By September 24, 1984, more than 150 people were violently ill. By the end of September, 751 cases of acute gastroenteritis were documented; lab testing determined that all of the victims were infected with Salmonella enterica Typhimurium.[20] Symptoms included diarrhea, fever, chills, nausea, vomiting, headaches, abdominal pain, and bloody stools.[17] Victims ranged in age from an infant, born two days after his mother's infection and initially given a five percent chance of survival,[12] to an 87-year-old.[8]
Local residents suspected that Rajneesh's followers were behind the poisonings. They turned out in droves on election day to prevent the cult from winning any county positions, thus rendering the plot unsuccessful.[2] The Rajneeshees eventually withdrew their candidate from the November 1984 ballot.[19] Only 239 of the commune's 7,000 residents voted; most were not US citizens and could not vote.[21] The outbreak cost local restaurants hundreds of thousands of dollars and health officials shut down the salad bars of the affected establishments.[2] Some residents feared further attacks and stayed at home.[22] One resident said: "People were so horrified and scared. People wouldn't go out, they wouldn't go out alone. People were becoming prisoners."[8]
Investigation
Officials and investigators from a number of different state and federal agencies investigated the outbreak.[14] Dr. Michael Skeels, Director of the Oregon State Public Health Laboratory at the time, said that the incident provoked such a large public health investigation because "it was the largest food-related outbreak in the U.S. in 1984".[20] The investigation identified the bacteria as Salmonella enterica Typhimurium and initially concluded that the outbreak had been due to food handlers' poor personal hygiene. Workers preparing food at the affected restaurants had fallen ill before most patrons had.[15][23][24]
Oregon Democratic Congressman James H. Weaver continued to investigate because he believed that the officials' conclusion did not adequately explain the facts.[12] He contacted physicians at the CDC and other agencies and urged them to investigate Rajneeshpuram.[6][12] According to Lewis F. Carter's book Charisma and Control in Rajneeshpuram, "many treated his concern" as paranoid or as an example of "Rajneeshee bashing".[12] On February 28, 1985, Weaver gave a speech at the United States House of Representatives in which he accused the Rajneeshees of contaminating salad bar ingredients in eight restaurants.[6][25] As events later showed, Weaver had presented a well-reasoned, if only circumstantial, case; these circumstantial elements were confirmed by evidence found after investigators gained access to Rajneeshpuram several months later.[12]
Months later, starting on September 16, 1985, Rajneesh, who had recently emerged from a four-year period of public silence and self-imposed isolation (although he had continued to meet with his assistant) at the commune,[15][26] convened press conferences: he stated that Sheela and 19 other commune leaders, including Puja, had left Rajneeshpuram over the weekend and gone to Europe.[7][26] He said that he had received information from commune residents that Sheela and her team had committed a number of serious crimes.[9][26] Calling them a "gang of fascists", he said they had tried to poison his doctor and Rajneesh's female companion, as well as the Jefferson County district attorney and the water system in The Dalles. He said that he believed they had poisoned a county commissioner and Judge William Hulse, and that they may have been responsible for the salmonellosis outbreak in The Dalles.[9] He invited state and federal law enforcement officials to the Ranch to investigate.[15] His allegations were initially greeted with skepticism by outside observers.[26]
Oregon Attorney GeneralDave Frohnmayer established a task force among the Wasco County Sheriff's office, the Oregon State Police, the Federal Bureau of Investigation (FBI), the Immigration and Naturalization Service (INS) and the National Guard that set up headquarters on the Ranch to investigate the allegations. They obtained search warrants and subpoenas; 50 investigators entered the Ranch on October 2, 1985. Dr. Skeels found glass vials containing Salmonella "bactrol disks" in the laboratory of a Rajneeshpuram medical clinic. Analysis by the Centers for Disease Control and Prevention lab in Atlanta confirmed that the bacteria at the Rajneesh laboratory were an exact match to those that sickened individuals who had eaten at local restaurants.[15]
The investigation also revealed prior experimentation at Rajneeshpuram with poisons, chemicals and bacteria, in 1984 and 1985.[15] Dr. Skeels described the scene at the Rajneesh laboratory as "a bacteriological freezer-dryer for large-scale production" of microbes.[20] Investigators found a copy of The Anarchist Cookbook, and literature on the manufacture and usage of explosives and military bio-warfare.[20] Investigators believed that the commune had previously carried out similar attacks in Salem, Portland, and other cities in Oregon.[15] According to court testimony, the plotters boasted that they had attacked a nursing home and a salad bar at the Mid-Columbia Medical Center, but no such attempts were ever proven in court.[15] As a result of the bioterrorism investigation, law enforcement officials discovered that there had been an aborted plot by Rajneeshees to murder Charles Turner, a former United States Attorney for Oregon.[27]
Prosecution

The mayor of Rajneeshpuram, David Berry Knapp (known as Swami Krishna Deva or KD), turned state's evidence and gave an account of his knowledge of the Salmonella attack to the FBI. He claimed that Sheela said "she had talked with [Rajneesh] about the plot to decrease voter turnout in The Dalles by making people sick. Sheela said that [Rajneesh] commented that it was best not to hurt people, but if a few died not to worry."[11] In Miller's Germs: Biological Weapons and America's Secret War, this statement is attributed to Sheela.[15] According to KD's testimony, she played doubters a tape of Rajneesh's muffled voice saying, "if it was necessary to do things to preserve [his] vision, then do it," and interpreted this to mean that murder in his name was fine, telling doubters "not to worry" if a few people had to die.[15] The investigation uncovered a September 25, 1984, invoice from the American Type Culture Collection of microbes, showing an order received by the Rajneeshpuram laboratory for Salmonellatyphi, the bacterium that causes the life-threatening illness typhoid fever.[15][28]
According to a 1994 study published in the journal Sociology of Religion, "[m]ost sannyasins indicated that they believed that [Rajneesh] knew about Ma Anand Sheela's illegal activities."[29]Frances FitzGerald writes in Cities on a Hill that most of Rajneesh's followers "believed [him] incapable of doing, or willing, violence against another person", and that almost all thought the responsibility for the criminality was Sheela's – according to FitzGerald, the followers believed the guru had not known anything about it.[9] Carus writes in Toxic Terror that, "There is no way to know to what extent [Rajneesh] participated in actual decision-making. His followers believed he was involved in every important decision that Sheela made, but those allegations were never proven."[30] Rajneesh insisted that Sheela, who he said was his only source of information during his period of isolation, used her position to impose "a fascist state" on the commune.[26] He acknowledged that the key to her actions was his silence.[26]
Rajneesh left Oregon by plane on October 27, 1985, and was arrested when he landed in Charlotte, North Carolina, and charged with 35 counts of deliberate violations of immigration laws.[31][32][33] As part of a plea bargain arrangement, he pleaded guilty to two counts of making false statements to immigration officials.[12][19][32] He received a ten-year suspended sentence and a fine of US$400,000, and was deported and barred from reentering the United States for a period of five years.[12][33][34] He was never prosecuted for crimes related to the Salmonella attack.[12][19]
Sheela and Puja were arrested in West Germany on October 28, 1985.[12] After protracted negotiations between the two governments, they were extradited to the United States, reaching Portland on February 6, 1986.[12] They were charged with attempting to murder Rajneesh's personal physician, first-degree assault for poisoning Judge William Hulse, second-degree assault for poisoning The Dalles Commissioner Raymond Matthews, and product tampering for the poisonings in The Dalles, as well as wiretapping and immigration offenses.[5][12] The U.S. Attorney's office handled the prosecution of the poisoning cases related to the 10 restaurants, and the Oregon Attorney General's office prosecuted the poisoning cases of Commissioner Matthews and Judge Hulse.[32]
On July 22, 1986, both women entered Alford pleas for the Salmonella attack and the other charges, and received sentences ranging from three to twenty years, to be served concurrently. Sheela received 20 years for the attempted murder of Rajneesh's physician, twenty years for first-degree assault in the poisoning of Judge Hulse, ten years for second-degree assault in the poisoning of Commissioner Matthews, four and a half years for her role in the attack, four and a half years for the wiretapping conspiracy, and five years' probation for immigration fraud; Puja received fifteen, fifteen, seven and a half, and four and a half years, respectively, for her role in the first four of these crimes, as well as three years' probation for the wiretapping conspiracy.[5][12][32] Both Sheela and Puja were released on parole early for good behavior, after serving twenty-nine months of their sentences in a minimum-security federal prison.[5][12][35][36] Sheela's Green Card was revoked; she moved to Switzerland. She remarried there and went on to run two nursing homes in Switzerland.[37]
Aftermath
The Oregonian ran a 20-part series on Rajneesh's movement, beginning in June 1985, which included an investigation into the Salmonella incident. As a result of a follow-up investigation, The Oregonian learned that Leslie L. Zaitz, one of their investigative journalists, had been placed as number three on a top-ten hit list by Sheela's group.[14]Oregon Attorney GeneralDave Frohnmayer commented on the poisoning incident and other acts perpetrated by the group, stating: "The Rajneeshees committed the most significant crimes of their kind in the history of the United States ... The largest single incident of fraudulent marriages, the most massive scheme of wiretapping and bugging, and the largest mass poisoning."[8][38] Looking back on the incident, Skeels stated, "We lost our innocence over this ... We really learned to be more suspicious ... The first significant biological attack on a U.S. community was not carried out by foreign terrorists smuggled into New York, but by legal residents of a U.S. community. The next time it happens it could be with more lethal agents ... We in public health are really not ready to deal with that."[20]
Milton Leitenberg noted in the 2005 work Assessing the Biological Weapons and Bioterrorism Threat, "there is apparently no other 'terrorist' group that is known to have successfully cultured any pathogen."[39] Federal and state investigators requested that details of the incident not be published in the Journal of the American Medical Association (JAMA) for 12 years, for they feared a description of the events could spark copycat crimes, and JAMA complied.[20] No repeat attacks or hoaxes subsequently occurred, and a detailed account of the incident and investigation was published in JAMA in 1997.[13][40][41] A 1999 empirical analysis in the journal Emerging Infectious Diseases published by the CDC described six motivational factors associated with bioterrorism, including: charismatic leadership, no outside constituency, apocalyptic ideology, loner or splinter group, sense of paranoia and grandiosity, and defensive aggression.[42] According to the article, the "Rajneesh Cult" satisfied all motivational factors except for an "apocalyptic ideology".[42] An analysis in the book Cults, Religion and Violence disputes the link to charismatic leadership, pointing out that in this and other cases, it was organizational lieutenants who played a pivotal role in the initiation of violence. Arguing for a contextual rather than decisive view of charisma, the authors state that the attribution of outcomes to the personality of a single individual, even a charismatic leader, usually camouflages a far more complex field of social relationships.[43]

The media revisited the incident during the 2001 anthrax attacks in the United States.[44][45][46][47] The 2001 publication of Judith Miller's Germs: Biological Weapons and America's Secret War, which contained an analysis and detailed description of the events, also brought discussion of the incident back into the news.[48][49][50] Residents of The Dalles commented that they have an understanding of how bioterrorism can occur in the United States.[2] The incident had spread fear in the community, and drained the local economy.[2] All but one of the restaurants affected went out of business.[51] In 2005, the Oregon State Land Board agreed to sell 480 acres (1.9 km2) of Wasco County, including Rajneeshpuram, to the Colorado-based youth ministry Young Life.[52][53] On February 18, 2005, Court TV aired an episode of Forensic Files about the incident, entitled: "'Bio-Attack' – Oregon Cult Poisonings".[54] The salmonellosis outbreak was also discussed in the media within the context of the 2006 North American E. coli outbreak.[55][56][57]
The book Emerging Infectious Diseases: Trends and Issues cites the 1984 Rajneeshee bioterror attack, along with the Aum Shinrikyo group's attempts to use anthrax and other agents, as exceptions to the belief "that only foreign-state supported groups have the resources to execute a credible bioterrorism event".[58] According to Deadly Cultures: Biological Weapons Since 1945, these are the only two confirmed uses of biological weapons for terrorist purposes to harm humans.[5] The incident was the single largest bioterrorist attack in United States history.[3][59][60] In the chapter titled: "Influencing An Election: America's First Modern Bioterrorist Attack" in his 2006 book Terrorism on American Soil: A Concise History of Plots and Perpetrators from the Famous to the Forgotten, author Joseph T. McCann concludes: "In every respect, the Salmonella attack carried out by the cult members was a major bioterrorist attack that fortunately failed to achieve its ultimate goal and resulted in no fatalities."[19]
See also
- 1985 Rajneeshee assassination plot
- 2001 anthrax attacks
- Biological warfare
- Deportation
- Elections in the United States
- Electoral fraud
- List of non-state terrorist incidents
- Public health
- Terrorism in the United States
- Tokyo subway sarin attack
- U.S. Immigration and Customs Enforcement
- Voting system
References
- ^"US Gazetteer files: 2010, 2000, and 1990". United States Census Bureau. 2011-02-12. Retrieved 2011-04-23.
- ^ abcdefFlaccus, Gillian (October 19, 2001). "Ore. Town Never Recovered From Scare". Associated Press.
- ^ abScripps Howard News Service (January 28, 2007). "Health experts fear bioterror attack". Grand Rapids Press. p. G1.
A total of 751 people, including members of the Wasco County Commission, became ill with nausea, diarrhea, headaches and fever. Forty-five people were hospitalized, but no one died. It was the first, and still the largest, germ-warfare attack in U.S. history.
- ^Lewis, Susan K (November 2001). "History of Biowarfare: Bioterror, The Cults". Nova Online Website. WGBH/NOVA. Archived from the original on December 9, 2007. Retrieved November 23, 2007.
- ^ abcdefWheelis, Mark; Rózsa, Lajos; Dando, Malcolm (2006). Deadly Cultures: Biological Weapons Since 1945. Harvard University Press. pp. 284–293, 301–303. ISBN 0-674-01699-8.
- ^ abcWeaver, James (April 24, 2001). "Slow Medical Sleuthing". The New York Times. The New York Times Company. Retrieved November 23, 2007.
- ^ abGordon, James S. (1987). The Golden Guru – The Strange Journey of Bhagwan Shree Rajneesh. The Stephen Greene Press. pp. 181–182. ISBN 0-8289-0630-0.
- ^ abcdSnow, Robert L. (2003). Deadly Cults: The Crimes of True Believers. Praeger/Greenwood. pp. 87–90. ISBN 0-275-98052-9.
- ^ abcdeFitzGerald, Frances (1987). Cities on a Hill. Simon & Schuster. pp. 360–361, 378. ISBN 0-671-55209-0.
- ^ abThompson, Christopher M. (December 2006). The Bioterrorism Threat By Non-State Actors: "The Rajneeshee Cult"(PDF). United States Navy. pp. 17–30. Archived from the original(PDF) on February 29, 2008. Retrieved March 13, 2008.
- ^ abcdefgCarus, W. Seth (2002). Bioterrorism and Biocrimes(PDF). The Minerva Group, Inc. pp. 50–55. ISBN 1-4101-0023-5. Archived(PDF) from the original on February 29, 2008. Retrieved March 18, 2008.
- ^ abcdefghijklmnopCarter, Lewis F. (1990). Charisma and Control in Rajneeshpuram. Cambridge University Press. p. s 202–238. ISBN 0-521-38554-7.
- ^ abEntis, Phyllis (2007). Food Safety: Old Habits, New Perspectives. Blackwell Publishing. pp. 244–246. ISBN 1-55581-417-4.
- ^ abcGrossman, Lawrence K. (January–February 2001). "The Story of a Truly Contaminated Election". Columbia Journalism Review. Archived from the original on November 19, 2008. Retrieved November 18, 2007.
- ^ abcdefghijklMiller, Judith; Broad, William; Engelberg, Stephen (September 17, 2002). Germs: Biological Weapons and America's Secret War. Simon & Schuster. pp. 1–34: "The Attack". ISBN 0-684-87159-9.
- ^Board on Global Health, Forum on Microbial Threats, Institute of Medicine (2006). Addressing Foodborne Threats to Health: Policies, Practices, and Global Coordination. National Academies. pp. 39, 41. ISBN 0-309-10043-7.
- ^ abUrbano, Mary Theresa (2006). The Complete Bioterrorism Survival Guide. Sentient Publications. pp. 60–61. ISBN 1-59181-051-5.
- ^Schweitzer, Glenn E.; Schweitzer, Carole Dorsch (2002). A Faceless Enemy: The Origins of Modern Terrorism. Da Capo Press. p. 121. ISBN 0-7382-0757-8.
- ^ abcdeMcCann, Joseph T. (2006). Terrorism on American Soil: A Concise History of Plots and Perpetrators from the Famous to the Forgotten. Sentient Publications. pp. 151–158. ISBN 1-59181-049-3.
- ^ abcdefGarrett, Laurie (2000). Betrayal of Trust: The Collapse of Global Public Health. New York: Hyperion. pp. 540–541, 544. ISBN 0-7868-8440-1.
- ^UPI Staff (November 9, 1984). "Few Followers of Guru Vote". The New York Times. The New York Times Company. Retrieved March 12, 2008.
- ^Stripling, Mahala Yates (2005). Bioethics And Medical Issues In Literature. Greenwood Press. p. 24. ISBN 0-313-32040-3.
- ^Novick, Lloyd (2003). Public Health Issues Disaster Preparedness: Focus on Bioterrorism. Jones and Bartlett Publishers. pp. 90, 104, 113. ISBN 0-7637-2500-5.
- ^Staff (October 21, 1984). "Ill Handlers Suspected in Oregon Food Poisonings". The New York Times. The New York Times Company. Retrieved March 15, 2008.
- ^Weaver, James (February 28, 1985). "The Town That Was Poisoned"(PDF). Congressional Record. Washington, D.C.: United States Government Printing Office. 131 (3–4): 4185–4189, 99th United States Congress, 1st Session. Archived from the original(PDF) on February 29, 2008. Retrieved March 18, 2008. Transcription at WikiSource.
- ^ abcdefMartin, Douglas (September 22, 1985). "Guru's Commune Roiled As Key Leader Departs". The New York Times. The New York Times Company. Retrieved March 15, 2008.
- ^Larabee, Mark (December 16, 2000). "Two Rajneeshee members plead guilty: Sally-Anne Croft and Susan Hagan return to the United States to face 15-year-old wiretapping charges". The Oregonian.
- ^Frost, Robin M. (2005). Nuclear Terrorism After 9/11. Routledge. p. 52. ISBN 0-415-39992-0.
- ^Latkin, Carl A.; Sundberg, Norman D.; Littman, Richard A.; Katsikis, Melissa G.; Hagan, Richard A. (1994). "Feelings after the fall: former Rajneeshpuram Commune members' perceptions of and affiliation with the Rajneeshee movement". Sociology of Religion. Oxford University Press. 55 (1): 65–74. doi:10.2307/3712176. JSTOR 3712176.
- ^Seth W. Carus (section) (2000). Tucker, Jonathan B., ed. Toxic Terror: Assessing Terrorist Use of Chemical and Biological Weapons. MIT Press. pp. 115–138. ISBN 0-262-70071-9.
- ^Staff (2001). "Bhagwan Shree Rajneesh". Encyclopedia of Occultism and Parapsychology, 5th ed. Gale Group.
- ^ abcdBernett, Brian C. (December 2006). U.S. Biodefense and Homeland Security Toward Detection and Attribution(PDF). United States Navy. pp. 13–35: "The Rajneeshee Cult Biological Attacks". Archived from the original(PDF) on February 29, 2008. Retrieved March 18, 2008.
- ^ ab"Acharya Rajneesh". Contemporary Authors Online. Thomson Gale. September 5, 2003.
- ^Staff (September 25, 2006). "Leadership, Director, Office of Policy and Planning, Joseph R. Greene". U.S. Immigration and Customs Enforcement. ICE. Archived from the original on September 25, 2006. Retrieved September 25, 2006.
- ^Senior, Jeanie (December 26, 1999). "Anand Sheela tends patients in Switzerland: The former spokeswoman for Bhagwan Shree Rajneesh works in two private nursing homes". The Oregonian.
- ^Suo, Steve (December 21, 2002). "Ex-Rajneeshee pleads guilty in conspiracy". Oregon Live.
- ^Senior, Jeanie; Hogan, Dave (January 22, 2000). "Indian guru follower Anand Sheela arrested after German TV show: Bhagwan Shree Rajneesh's former spokeswoman is freed because a Swiss court already convicted her in 1999". The Oregonian.
- ^Graham, Rachel (1983). "The Saffron Swami". Willamette Week (25th Anniversary Issue).
- ^Leitenberg, Milton (December 1, 2005). Assessing the Biological Weapons and Bioterrorism Threat. Strategic Studies Institute. ISBN 1-4289-1626-1. Archived from the original on March 4, 2008. Retrieved March 18, 2008.
- ^T. J. Török; R. V. Tauxe; R. P. Wise; J. R. Livengood; R. Sokolow; S. Mauvais; K. A. Birkness; M. R. Skeels; J. M. Horan; L. R. Foster (August 6, 1997). "A Large Community Outbreak of Salmonellosis Caused by Intentional Contamination of Restaurant Salad Bars". Journal of the American Medical Association. 278 (5): 389–395. doi:10.1001/jama.278.5.389. PMID 9244330. Archived from the original on December 1, 2007. Retrieved November 18, 2007.
- ^Advisory Panel to Assess Domestic Response Capabilities for Terrorism Involving Weapons of Mass Destruction (December 15, 1999). Assessing The Threat: First Annual Report to The President and The Congress of the Advisory Panel to Assess Domestic Response Capabilities for Terrorism Involving Weapons of Mass Destruction(PDF). DIANE Publishing. pp. 18–19. ISBN 1-4289-8112-8. Archived from the original on March 26, 2009.
- ^ abTucker, Jonathan B. (July 1, 1999). "Historical Trends Related to Bioterrorism: An Empirical Analysis". Emerging Infectious Diseases. Centers for Disease Control and Prevention. 5 (4): 498–504. doi:10.3201/eid0504.990406. PMC 2627752
. PMID 10458952. Archived from the original on November 13, 2007. Retrieved November 22, 2007.
- ^Bromley, David G.; Melton, J. Gordon (May 13, 2002). Cults, Religion and Violence. Cambridge University Press. p. 47. ISBN 0-521-66898-0.
- ^Dobbs, Lou (October 12, 2001). "Anthrax Exposure Discovered in New York; Interview With William Cohen". Lou Dobbs Moneyline. CNN. Retrieved November 23, 2007.
- ^Staff (October 21, 2001). "Bioweapons are possible to get, but it's not easy". Star Tribune.
- ^Mishra, Raja (September 27, 2001). "A Heightened Alert for Bioterrorism Detection System is Keeping Health Officials Apprised". Boston Globe.
- ^AP Staff (October 21, 2001). "Bioterror's first US victims offer hope to a nation – Cult Attack: The small town of The Dalles, near Portland, Oregon, was in 1984 the first place in America hit with germ warfare. The people of the town say that the country will get through this as well". The Taipei Times. p. 4. Archived from the original on December 8, 2007. Retrieved November 22, 2007.
- ^Beard, David (October 16, 2001). "'Germs' Examines US in Age of Bioterrorism". Boston Globe. p. E3.
- ^Lalich, Janja (2004). Bounded Choice: True Believers and Charismatic Cults. University of California Press. pp. 9–10. ISBN 0-520-24018-9.
- ^Elmer-Dewitt, Philip (September 30, 2001). "America's First Bioterrorism Attack". TIME. Time Warner. Retrieved November 18, 2007.
- ^Nestle, Marion (2003). Safe Food: Bacteria, Biotechnology, and Bioterrorism. University of California Press. pp. 266–267. ISBN 0-520-23292-5.
- ^Associated Press (December 15, 2005). "Oregon agrees to sell former Rajneeshees cult encampment". The Seattle Times. The Seattle Times Company. Archived from the original on October 8, 2008. Retrieved November 24, 2007.
- ^Staff (December 15, 2005). "State agrees to sell former Rajneesh encampment". KATU 2 Portland.
- ^Staff (February 18, 2005). "'Bio-Attack' – Oregon Cult Poisonings: In 1984, hundreds of people in The Dalles, Oregon became ill with food poisoning. Local, state and federal disease detectives slowly unraveled the medical mystery. Along with a unique strain of bacteria, they discovered a religious cult's bizarre plot to overthrow the government using germ warfare". Forensic Files: Court TV. Turner Entertainment Digital Network, Inc.
- ^Staff (September 21, 2006). "Spinach scare sparks memories of The Dalles". Nashua Telegraph. Telegraph Publishing Company.
- ^Staff (September 23, 2006). "Spinach and bioterrorism prevention". Ocala Star-Banner.
- ^Staff (September 19, 2006). "Bioterror and spinach". Scripps Howard News Service.
- ^Lashley, Felissa R.; Durham, Jerry D. (2007). Emerging Infectious Diseases: Trends and Issues. Springer Publishing Company. p. 419. ISBN 0-8261-0250-6.
- ^Cramer, John (October 14, 2001). "Oregon suffered largest bioterrorist attack in U.S. history, 20 years ago". The Bulletin. bendbulletin.com.
- ^Hargrove, Thomas (November 25, 2006). "Lab Unprepared for Germ Warfare". The Kentucky Post. p. A11.
Further reading
- Bernett, Brian C. (December 2006). U.S. Biodefense and Homeland Security Toward Detection and Attribution(PDF). United States Navy. pp. 13–35: "The Rajneeshee Cult Biological Attacks". Archived from the original(PDF) on February 29, 2008. Retrieved March 18, 2008.
- Carter, Lewis F. (1990). Charisma and Control in Rajneeshpuram. Ernest Q. Campbell, contributor. Cambridge University Press. pp. 202–257. ISBN 0-521-38554-7.
- Carus, W. Seth (2002). Bioterrorism and Biocrimes(PDF). The Minerva Group, Inc. pp. 50–55. ISBN 1-4101-0023-5. Archived(PDF) from the original on February 29, 2008. Retrieved March 18, 2008.
- Entis, Phyllis (2007). Food Safety: Old Habits, New Perspectives. Blackwell Publishing. pp. 244–246: "Salad Days in The Dalles". ISBN 1-55581-417-4.
- FitzGerald, Frances (1987). Cities on a Hill. Simon & Schuster. ISBN 0-671-55209-0.
- Garrett, Laurie (2000). Betrayal of Trust: The Collapse of Global Public Health. New York: Hyperion. pp. 540–541, 544. ISBN 0-7868-8440-1.
- McCann, Joseph T. (2006). Terrorism on American Soil: A Concise History of Plots and Perpetrators from the Famous to the Forgotten. Sentient Publications. pp. 151–158 – "Influencing An Election: America's First Modern Bioterrorist Attack". ISBN 1-59181-049-3.
- Miller, Judith; Broad, William; Engelberg, Stephen (September 17, 2002). Germs: Biological Weapons and America's Secret War. Simon & Schuster. pp. 1–34: "The Attack". ISBN 0-684-87159-9.
- Thompson, Christopher M. (December 2006). The Bioterrorism Threat By Non-State Actors(PDF). United States Navy. pp. 17–30: "The Rajneeshee Cult". Archived from the original(PDF) on February 29, 2008. Retrieved March 18, 2008.
- Seth W. Carus (section) (2000). Tucker, Jonathan B., ed. Toxic Terror: Assessing Terrorist Use of Chemical and Biological Weapons. MIT Press. pp. 115–138. ISBN 0-262-70071-9.
- Weaver, James (February 28, 1985). "The Town That Was Poisoned"(PDF). Congressional Record. Washington, D.C.: United States Government Printing Office. 131 (3–4): 4185–4189, 99th United States Congress, 1st Session. Archived from the original(PDF) on February 29, 2008. Retrieved March 18, 2008.
External links
![]() | Wikisource has original text related to this article: |
Media related to 1984 Rajneeshee bioterror attack at Wikimedia Commons
- Ayers, Shirley. "Bioterrorism in Oregon". Emergency Film Group. Archived from the original on April 29, 2012. Retrieved November 18, 2007.
- Oregon State Archives. "Wasco County History". Oregon Historical County Records Guide. Retrieved November 22, 2007.
- Oregon State Archives (2007). "Oregon History: Chronology – 1952 to 2002". Oregon Blue Book. Retrieved November 22, 2007.
- Oregon State Department of Human Services. "Bioterrorism questions and answers". OREGON.gov. Archived from the original on May 27, 2010. Retrieved November 18, 2007.
- U.S. Immigration and Customs Enforcement (September 25, 2006). "Leadership, Director, Office of Policy and Planning, Joseph R. Greene". ICE. Archived from the original on September 25, 2006. Retrieved November 22, 2007.
- WBUR. "Bioterrorism in History – 1984: Rajneesh Cult Attacks Local Salad Bar". NPR. Archived from the original on January 5, 2009. Retrieved November 18, 2007.
The Weird, Dangerous, Isolated Life of the Saturation Diver
For 52 straight days this winter, Shannon Hovey woke up in the company of five other men in a metal tube, 20 feet long and seven feet in diameter, tucked deep inside a ship in the Gulf of Mexico. He retrieved his breakfast from a hatch (usually eggs), read a briefing for the day, and listened for a disembodied voice to tell him when it was time to put on a rubber suit and get to work. Life in the tube was built around going through these same steps day after day after day … while trying not to think about the fact that any unintended breach in his temporary metal home would mean a fast, agonizing death.
Hovey works in one of the least known, most dangerous, and, frankly, most bizarre professions on Earth. He is a saturation diver—one of the men (just about all have been men*) who do construction and demolition work at depths up to 1,000 feet or more below the surface of the ocean.
Diving to that depth—or just about any depth—involves breathing pressurized air. Inert gases in it, such as nitrogen, dissolve benignly into your blood and tissues—as long as the weight of all the water above you keeps them compressed. But when you want to return to the surface, that gas needs time to diffuse out slowly. If not, if a diver shot straight to the surface, the gas would form bubbles, like in a shaken can of soda. Inside that diver’s body, it would be as if millions of tiny explosives began to detonate. Known as the bends or, more technically, decompression sickness, the condition can be catastrophically painful and debilitating, and, depending on the depth, nearly impossible to survive. Diving to 250 feet for an hour, for example, would require a five-hour ascent to avoid getting even slightly bent. (The condition was first seen in the 19th century, when men leaving pressurized caissons, used to dig tunnels and build bridges, mysteriously took ill and began dying.)
The world—and, specifically, the oil and gas industry—needs commercial divers like Hovey who can go to the seabed to perform the delicate maneuvers required to put together, maintain, and disassemble offshore wells, rigs, and pipelines, everything from flipping flow valves, to tightening bolts with hydraulic jacks, to working in tight confines around a blowout preventer. Remotely operated vehicles don’t have the touch, maneuverability, or judgment for the job. And so, a solution. Experiments in the 1930s showed that, after a certain time at pressure, divers’ bodies become fully saturated with inert gas, and they can remain at that pressure indefinitely, provided they get one long decompression at the end. In 1964, naval aquanauts occupied the first Sea Lab—a metal-encased living quarters lowered to a depth of 192 feet. The aquanauts could move effortlessly between their pressurized underwater home and the surrounding water, and they demonstrated the enormous commercial potential of saturation diving. It soon became apparent that it would be easier and cheaper to monitor and support the divers if the pressurized living quarters weren’t themselves at the bottom of the sea. At this moment, all around the world, there are commercial divers living at pressure inside saturation systems (mostly on ships, occasionally on rigs or barges), and commuting to and from their jobsites in pressurized diving bells. They can each put in solid six-hour working days on the bottom.
Hovey and his fellow divers spent that six-week assignment working at the relatively shallow (but still quite deadly) depth of 250 feet, and living in a shipboard capsule pressurized to the same level. Pressure can be measured in atmospheres (atm) or pounds per square inch (psi). Pressure at sea level is 1 atm, or 14.7 psi. Inside a bicycle tire is about 65 psi. Hovey was living at over 110 psi. An ocean-and-a-half away, diver Steve Tweddle was making his way through a 28-day job in “storage,” as they call it, for work at a depth of 426 feet (190 psi) in the North Sea. The Gulf of Mexico and the North Sea share a history of offshore drilling, sparked by the worldwide oil crisis of the 1970s, which sent prices skyrocketing and saw offshore oil and gas rigs pop up like giant galvanized lily pads. The vast majority of saturation dives are for maintaining or taking down this oil and gas infrastructure.

A saturation diver starts a job when he leaves the “beach” (any solid ground) and steps onto a flat-bottomed ship known as a dive support vessel (DSV). Every piece of equipment and person on the ship is there to support the work and lives of the divers. There are subsea managers and dive supervisors, life support supervisors, life support technicians, and assistant life support technicians. They control what the divers breathe and eat, supply personal necessities, and even help remotely flush the toilet—whatever is necessary to keep them comfortable (such as it is) and alive.
Before taking up residence in the saturation chamber, the core living space of the system, every diver must pass a medical workup including, among other things, a hunt for any signs of infection. Even a simple cold can be incredibly hazardous to a saturation diver—clogged ears and sinuses trap air that the divers won’t be able to equalize to the pressurized air, potentially causing permanent damage that can end a career. Before entering the sat system, Tweddle always takes a shower with antibacterial soap to scrub off any hitchhiking germs.
In their last moments before a job, both Hovey and Tweddle call their families, even though they can use cell phones while in the chamber. Hovey, a 42-year-old American with intense, mournful eyes and a gray-dappled beard, used to work as a sound engineer and is now (most likely) the only saturation diver who works as an herbalist when on the beach. He tries to find a sunny spot on the ship’s helipad for his phone call. It’s his last chance to breathe fresh air, and his last chance to speak in a voice his family will understand. Once he’s at pressure, he’s going to sound like Donald Duck after huffing a roomful of helium balloons.
Air—compressed or otherwise—is about 21 percent oxygen, 78 percent nitrogen, and one percent everything else. Below about 100 feet divers breathing compressed air, including recreational scuba divers, can develop what’s known as nitrogen narcosis, which does an excellent job of mimicking the feeling of being drunk. The deeper you go, the drunker and more incapacitated you feel: Beyond 200 feet you might become acutely disoriented, at 300 feet you can black out. It’s not a good condition to be in when you’re in a place where you have to be calm, careful, and methodical if you want to survive. In addition, that amount of compressed oxygen becomes toxic to the human body. Around 1919, electronics engineer and inventor Elihu Thompson figured that divers could avoid nitrogen narcosis by breathing a mixture of helium and oxygen. In the following decades a gas cocktail called heliox was developed—mostly helium, with sufficient oxygen and maybe a little nitrogen. (Other breathing gases, such as trimix and nitrox, are also used by deep divers.)

Saturation divers breathe heliox for the entire time they are in storage. And this brings us back to those final family phone calls. Helium is about seven times lighter than air, and sound waves travel much more quickly through it. The result is that buff, often ex-military men performing deadly serious jobs end up sounding like cartoon characters—and not just for a few moments, but for weeks on end. In the unfortunately named BBC series Real Men, a saturation diver in storage calls his son to wish him a happy birthday. “It’s hard to understand my dad because he talks in a duck language,” the boy says later, “and I don’t speak duck.”
The divers and their support teams adjust pretty quickly to the vocal distortion, but it can still make communication tricky—especially when accents are involved. “A helium Geordie [a native of Newcastle] from the northeast of England in a team with a South African and a Belgian makes communicating quite a challenge,” Tweddle says. Tweddle, an affable, 39-year-old former police diver with a shaved head that takes on a gray cast by the end of a job, is the Geordie in the above scenario. Support vessels are usually equipped with a kind of descrambler for when the divers need to be in constant communication with the onboard support team, but the equipment is notoriously unreliable, and many dive supervisors choose not to use it.
When it’s time to enter the chamber (Hovey calls it the “house”), the divers pass through a tight, circular hatch at one end, like one might see on an old submarine, that closes with a “tunk.” The hatch is sealed, and even though they’re on a boat, just feet from support crew and fresh air, the divers might as well be on the International Space Station. Even farther actually: It takes about 3.5 hours for an astronaut to make it back from space. Saturation divers have to decompress for days at minimum. On a dive early in his career, when Hovey was on a job at a depth of 700 feet, he learned that his wife had miscarried. It would have taken him 11 days of decompression to exit the chamber. They needed his salary (not surprisingly, saturation divers are well-compensated, up to $1,400 per day), so his wife told him to finish the job.

The layouts of saturation systems differ from company to company, vessel to vessel, and oil field to oil field. Generally, the North Sea facilities tend to be slightly roomier, thanks to strict regulations, but that’s not to say they are in any way spacious; they are even the mildest claustrophobe’s worst nightmare. For Tweddle, entering that first hatch puts the him in a miniscule round room known as the “wet pot.” It is used to transfer the divers to the diving bell through a hatch in the ceiling—and it’s also the bathroom, with a tiny metal sink, toilet (more on that later), and showerhead. Through the wet pot, another hatch leads to the living space, where there is just enough room for four to six seats around a removable aluminum table. In other words, for up to six weeks, the divers will spend their waking hours either under hundreds of feet of water on the ocean floor or squeezed into an area the size of a booth at Applebee’s.
Beyond that, past a droopy blue curtain, is the sleeping area, with six double-stacked bunks squeezed into a “U” shape. The bunks at the far end are partially blocked by the others, and therefore particularly cramped (especially for six-foot-four-inch Tweddle). So bunk choice is a big deal. In the North Sea, divers draw lots. Among American divers, Hovey says, it’s seniority—or whoever gets there first. But at least divers do all get their own sleeping spaces. In the bad old days, Tweddle says, six guys would have to hot-bed three bunks, with one group working while the other slept. There are still ways to keep the work going 24/7. On some vessels, up to four saturation chambers can be linked together through side hatches in the wet pots, and connected by large metal hamster tubes. This enables multiple dive teams to be in constant rotation.
Once the divers are tightly ensconced in the saturation chamber, the life support crew begins pumping in heliox, and the “blowdown” begins. The time it takes to get fully pressurized depends on the depth of the work site. On this latest job, Hovey’s blowdown took a mere three hours. On another job, with a storage depth of 750 feet, blowdown was 10 hours. In essence, pressurization transforms the saturation chamber into a space in which the air around them—and filling their lungs and saturating their tissues—is exerting pressure equivalent to the weight of the water they will be working under. Getting pressed to 750 feet requires 333 psi or 22.66 atms. It means squeezing into the chamber 22 times the amount of air it would normally hold.
During the blowdown, the rapid increase in atmospheric pressure makes the chamber very hot and humid (fluid dynamics are so strange), and sometimes needs to be paused so the climate control system can catch up. Later, the thermostat will get turned up to 90 degrees because the poor thermal properties of helium leave the divers perpetually chilly. The divers fan themselves and work constantly to equalize their ears: yawning, swallowing, and using the Valsalva maneuver (the formal name for pinching your nose, closing your mouth, and blowing). The blowdown also leaves them achy for hours or even days. “Anything not liquid or solid is affected by the physics of the gas,” says Hovey. “The cartilage in your joints is porous and shrinks for a couple days. All your joints hurt or click with movement.”

Once the divers are at pressure, they can only try to get comfortable, and make the chamber something of a home. In truth, they don’t bring or need a lot of gear—just a few items of clothing, toiletries, magnets for attaching family pictures to the walls, reading material, some personal electronics, the occasional Star Wars pillowcase. Everything else can be sent in via one of the two airlocks—a porthole-sized one in the living quarters known as the medlock and a larger one, for things such as their dive suits, off the wet pot. An assistant life support technician (Hovey says all American divers he knows call this person a “sat Betty”) is available to collect dirty clothes and linens through the medlock. Books, tools, and dive logs also make the journey in and out regularly, with each transit taking a minute or two.
Four times a day, someone sends in a menu with meal options, which come from the ship’s mess in disposable to-go containers (more hygienic than reusable plates and cups). Not surprisingly, the food quality varies greatly by vessel and chef, but mostly it sounds like the bill of fare from a discount cruise. Steak, chicken, fish, mushy vegetables, and a salad bar including cheese and cold cuts. Mostly the divers see food as little more than fuel—they might consume up to 6,000 calories each day (more than double the recommended intake) to keep up with their demanding shifts in the water. They also take healthy doses of multivitamins, with an emphasis on vitamin D, to make up for the lack of sunlight. The food itself is unaffected by the pressure, but taste buds tend to get muted. Hot sauce is a popular personal item, but the divers must be sure to loosen the cap—otherwise the bottle of hot sauce (or shampoo, or clove oil in Hovey’s case) will implode during pressurization or explode during depressurization.
The toilet and shower are in the wet pot, and it is no easy feat to flush a toilet safely at that kind of pressure. There is a famous, unverifiable, and, we can only hope, apocryphal story about a diver whose buttocks created a seal with the toilet seat, so that when he opened a valve to flush, the pressure differential—well, it’s best not to say too much more, other than that toilet safety is taken very, very seriously. “The toilet must be filled halfway with water before use,” says Tweddle. “After use we request a flush, [a technician] opens a valve on surface, allowing us to operate two valves in a particular order to empty the toilet into the holding tank, then empty the tank into the ship’s wastewater system.” In other words, every flush is at least a two-person, multi-step job.
The six-man dive crews split into teams of two or three and alternate shifts. They are woken up an hour before they need to leave the ship. They eat and hydrate and use the bathroom (Tweddle says that one quality that makes a good saturation diver is “the ability to shit on command.”) They put on a layer of their own clothing, followed by their water-tight diving suits, which are equipped with circulating hot water systems to prevent hypothermia.
The dive team seals itself off in the wet pot and then, through the hatch in the ceiling, gets into a diving bell, at the same pressure as the chamber. Both spaces are sealed, and then they disconnect—what’s known as a “transfer under pressure.” Anytime seals are made or broken under that kind of extreme pressure there is the danger that a mishap could lead to an explosive decompression. One of saturation diving’s worst accidents occurred in 1983, when a dive bell was detached from the transfer hatch before it was completely sealed. Four divers and one dive technician were killed instantly and gruesomely. (Newer saturation systems have locking mechanisms to prevent this from happening.)

The bell, shaped like an egg and about the size of a shower stall, is crammed with gauges, switches, communication equipment, and loops of hoses, referred to as umbilicals, that carry gas, electricity, voice communication, hot water, and video feeds back and forth between the divers’ helmets and the ship, via the bell. Once the bell detaches from the chamber, it is guided over to a moonpool—a hole in the boat’s hull, essentially—where it is lowered by cable to the working depth. One diver stays in the bell to monitor breathing, hot water, communication, and electrical systems. The other diver (or other two) puts on a dive helmet (a “hat” to the divers) and departs out the bottom for six uninterrupted hours in the water. During that time, urinating isn’t an issue—it’s pretty much the only job in the world where it is expected that you will pee in your pants.
Hovey, on his Gulf assignment, was working to clear a hurricane-toppled, garbage-strewn platform dating to the 1970s. The job was supposed to take 14 days—52 days later work was suspended until the spring because of bad weather. Most of the work involved collecting massive amounts of junk—“anything bigger than a breadbox or smaller than a VW bus”—and placing it in large baskets that could be raised by the ship’s crane. There were old barrels and pipes and chemical tanks and stainless-steel banding material that comes in huge rolls but littered the area like 500-foot-long Slinkys. Divers carry minimal tools with them; everything else they need gets sent down directly from the ship—saws, torches, wrenches, welding equipment, collection bags.
Hovey and the others also needed to cut the platform’s original eight legs off, 20 feet below the mud. This required using a massive water jet to create ditches around them and then cutting through the legs with an oversized band saw—all while keeping an eye out for a mudslide in near-zero visibility. “Say an old diesel engine that’s halfway up your ditch wall finally starts working its way out,” Hovey says. “Everything kind of moves slow, so you’ll notice a little mud going past your leg and then all of a sudden there’s this huge bunch of pressure on your lower back and then it’s on your upper back and it’s starting to push you over and unless you climb onto the top of it you’ll definitely get buried.” Generally, the divers aim for neutral buoyancy, but they’re not swimming around with fins like recreational divers. They hop-walk like moon men, often in beat-up rubber boots.

Nobody works deep at the bottom of the ocean without an extensive background in commercial diving in shallower waters and lengthy, costly training in areas such as mixed-gas and closed-bell diving. Just signing up for those advanced courses requires a substantial amount of commercial dive time and even once one is fully certified, it can be hard to get hired for a saturation dive job without trusted people to vouch for your ability to work under those conditions without losing it. Despite all this effort, the occupation has a high attrition rate—though leaving the field isn’t always voluntary. Hovey guesses that of every 20 guys who graduate from a training program, maybe one is still doing the work after five years. Some leave because of the difficulty or long weeks away from home, but this is also a job that takes lives. There are not good statistics about saturation diving death rates, but a Centers for Disease Control and Prevention report from 1998 estimated that the occupational fatality rate for all commercial divers is 40 times the national average for other professions. Many divers have close calls that convince them that it’s not worth the risk.
Hovey recalls moments of deep panic. Once, his umbilicals got tangled up in a tool rack that had been lowered down. The movement of the boat above began to jerk him around and he worried the force was about to separate him from his gas supply. “You have to calm down, take some breaths, and say, ‘You are the only one that can help yourself. No one’s going to come down here and help you.’” Some divers have cheated death, with help from their partners, or through a combination of discipline, training, and luck, but usually when things go wrong, they go wrong very fast, with catastrophic consequences.
In 2016, Hovey was working in the Gulf of Mexico, replacing a long piece of vertical pipe. The crew attached a temporary support, a heavy rod they call a “strong back”—to keep the pipe from bending during installation. Because of a miscommunication, the strong back was released from the top before the bottom. It rolled around and, Hovey believes, crushed a diver—the one on the shift just after his—against the pipe. Back in the sat system, Hovey got word that there had been an accident. As attending medic, he readied first-aid items, but when the bell returned, he saw right away that the diver’s hat had been crushed. Protocol required Hovey and the other divers to perform 45 minutes of CPR. Then they respectfully moved his body to a hyperbaric lifeboat/decompression chamber available to all sat systems. The support team could do an accelerated, emergency decompression, since he was already dead. It still took two days.
Tweddle believes that all the crazy stuff he saw as a police diver (dead bodies) makes him pretty hard to rattle, but he’s had scary moments, too. In particular, there have been the times when he started breathing so hard that the system couldn’t keep up. It’s a perfect storm for panic, as you breathe an excess of carbon dioxide and begin to huff harder and harder. The only way out is to wrestle down the fear and breathe as slowly as possible until the system catches up. It’s so common a phenomenon that divers have a name for it, “Breathing past your hat.”
In addition to the physical demands, moving around large pieces of equipment in a medium the human body is not well suited to, the work requires incredible focus and is done in near-zero or zero (black water) visibility. The dive hats have lights, but that can make things worse when particles in the water scatter light around. The divers must be in constant communication with the topside dive supervisor, who guides the work, troubleshoots, and sends down equipment. But ultimately whether they succeed or fail at the job—and stay alive—is on the divers alone.

Much of Tweddle’s work these days is helping plug and cap wells. You might imagine that beneath each platform is a single well, but wells might be as far as five or six miles away from the platform, and they often come in clusters—imagine using 10 straws to drink a milkshake instead of just one. But now the North Sea oil run is winding down, as the price of oil stagnates and the cost of extraction from increasingly empty fields grows. New exploration has gravitated to areas too deep for even saturation divers. Soon, the jobs will be harder to come by.
Days in sat become a blur of work and rest and boredom, perhaps punctuated by fear. Sometimes, despite dynamic positioning systems that compensate for wind and swells, bad weather suspends work, and the vessel might even return to port without the divers knowing—until a strange face suddenly pops up outside one of the chamber’s portholes. The divers soon realize that they are being stared at like monkeys in a cage. Or, rather, monkeys in a small, pressurized metal tube.
The general rule for depressurization—desat—is 24 hours for each 100 feet of pressure. Those are some of the hardest days, the divers say, with no work to break the monotony and with the comforts of home—sunlight, big beds, privacy, home-cooked food, wives, kids—so close. Desat mostly takes place in the chamber, but Hovey has done two-man desats in the small hyperbaric lifeboat (which can keep the divers under pressure for 72 hours if the ship were to sink), so work can continue with a new team.
Even desat is stressful on the body. Divers report joint pain, headaches, shortness of breath. Experienced divers know the difference between these symptoms and the start of something more serious. On one job, Tweddle worked with a relatively inexperienced diver who felt panicky about his symptoms during desat. The only cure for early signs of the decompression sickness is to return to higher pressure, so the whole team had to start again. It’s imperative, in this job, to err on the side of safety.
When the divers finally come out of the chamber, the adjustment is both emotional and physical. They emerge pale and disoriented, like prisoners released from solitary, drained and irritable, body clocks out of whack. Tweddle finds it hard to train his body not to eat quite so much. He has to be on guard for waistline expansion since there are now strict body mass index guidelines for North Sea divers.
Hovey owns some land in the central Texas pine woods, and he usually spends a few days there alone before trying to reintegrate with the noise and chaos of family life. His kids give him a wide berth after a job, and he and his wife like to start dating all over again as a way to reconnect. It’s hard to shake the feeling that he is in suspended animation while in sat, even though life goes on. “My family is constantly trying to grow and be better versions of themselves,” he says. “Sometimes being away for work, I get left in the dust.”
But by the time the phone rings for the next job, both he and Tweddle will be ready. There’s something about the isolation and asceticism and discipline (and, of course, the money) that they are drawn to. Or maybe it’s the idea that they are working on the edges of human capability, facing danger with calm and planning, members of a club with very, very few members. They are, in so many ways, like astronauts. Only no one’s ever heard of them.
* Correction: This article was updated for the correct spelling of Steve Tweddle’s name, and to clarify, upon hearing from readers, that there may indeed be active female saturation divers.
German online bank uses Bitcoins to transfer loans
BERLIN (Reuters) - German Radoslav Albrecht has founded an online bank that allows clients to transfer loans anywhere in the world using Bitcoin.
Bitbond uses cryptocurrencies like Bitcoin to bypass the Swift international transfer system to lend money across the globe rapidly and at low cost.
“Traditional money transfers are relatively costly due to currency exchange fees, and can take up to a few days,” Albrecht told Reuters TV in his office in Berlin’s fashionable neighborhood Prenzlauer Berg. “With Bitbond, payments work independently of where customers are. Via internet it is very, very quick and the fees are low.”
Clients hold the loans in digital tokens like Bitcoin only for seconds or minutes until they are exchanged back into the currency of the country where they wish to receive the funds, avoiding the crypto currencies fluctuating exchange rates.
Bitcoin has been used as collateral for loans, but never as a way of transferring credit in currency internationally.
Albrecht’s service has been growing in popularity among clients since he launched the company in 2013. His office employs 24 people from 12 countries who manage loans for 100 clients amounting to around $1 million each month.
Most clients are small business owners or freelance workers, Albrecht says. Loans are relatively small and don’t exceed 50,000 dollars. In 2016, Bitbond was officially licensed as a bank and has gained many investors since.
Adoption of Bitcoin has been rapid in Germany. It trails only the U.S., according to Bitnodes, which tracks the location of all the Bitcoin nodes that transmit data about new transactions.
Writing by Laura Dubois,; Editing by Joseph Nasr and Matthew Mpoke Bigg
'But didn't you write an embedded OS?'
I have been job hunting in the last 2 months or so. Thankfully, I am settled with a great choice now, and it seemed like I had more luck than the average job applicant. But among the handful of companies that I had the pleasure to interview with, I had my fair share of interesting moments.
The very first interview I had with a startup company was one of them. I mentioned in the resume I sent that I made an distro for the Raspberry Pi called Crankshaft, which is related to the work that they are doing and got a phone interview appointment. We chatted for a bit to introduce ourselves to each other. After 30 minutes, I was asked that whether I was in front of a computer (implying it will be a live coding exercise) out of the blue. To set the record straight, I'm totally happy to do live coding exercises, and I understand companies that are fed up with impostors who "inflated" their experiences on their resume. However, in that instance, there was no indication that it was coming even in the interview appointment email. Nonetheless, I figured I can swallow it. After all, I have been programming for more than a half of my life. I figured being able to code spontaneously shows that I am a fearless ninja warrior when it comes to programming :^).
I was presented with a Leetcode-esque question to which I said, "I can do it in two commands chained by a pipe in bash." And he said, let's treat it like a real CS question. So I asked, what languages can I code in, and the answer was any programming language I like. So I chose to program in Go. Now, when it comes to live coding challenges, one of the biggest problems is that the interviewer always knows the optimal answer when the applicant most likely can only come up with a suboptimal one given a very short time allowance. In a relatively successful interview, either the optimal solution is found when the two parties work on the plan of attack before the coding phase, or in the Q&A phase when a potential question or hint is presented to the interviewee. I presented the general direction I would take. In this case, I did not come up with the optimal algorithm but nonetheless, we agreed to proceed to the coding phase. In the Q&A session, the interviewer asked me why did I choose Go but not C. My answer was I would always choose Go over C if memory or performance is not a required constraint. Go is easier to work with and less boilerplate to worry about. Then, the interviewer mentioned something about a solution involving hashes that makes the lookup operation O(1) and I disagreed with him, so then we settled on them being "practically O(1)." Finally, we talked about some other stuff and I could sense that the interviewer being disappointed that I didn't come up with the optimal answer. I answered something like "I honestly don't know the answer for that – there are more things that I don't know than things I do know." He asked, "But didn't you write an embedded OS?". Then I realized that he was expecting me to be using C and coming up with the most optimal answer, and not taking "I don't know" for an answer because I wrote an embedded OS. So I told him "Oh, it is actually written in bash, you can see it on Github," and I can feel that he wasn't very impressed by my leet bash programming skillz. The interview concluded not long after that. I sent him a thank-you email but never heard back.
I guess I didn't qualify for the next round and was eliminated straight out. I don't intend to write this post to bash the interviewer or to say I should have been qualified – I didn't and I deserved it. I think though, there is something to say about the virtue of having, expecting, and imposing artificial constraints when it comes to problem-solving in general.
Truth to be told, more than 95% of Crankshaft code is written in bash. I am not even a leet bash programmer. I still have to look up "bash equality syntax" when I need to do a number comparison because the syntax confuses me (I remember the string equality syntax now, though).
That brings me back to the past. After dropping out of college in Vietnam years ago, I had the pleasure to work on a much less technically-demanding job in a small company that resells various specialized software packages. I had the chance to interact a lot with the CEO and the CTO. I first heard the quote "if all you have is a hammer, everything looks like a nail" from the CTO, which has since become one of my favorite ones. The CEO told me he studied Vovinam, a Vietnamese martial art. He told me that one of the main themes of Vovinam is using "soft" to win over "hard." Essentially, it means whenever possible, one should exert the least energy, basically choose the path of least resistance to achieve what they want to do. In overall, I learned the spirit from both of them: It is important to first think about the goal rather than the mean.
The trend of using hard technology is prevalent in tech-savvy people. Just today, someone asked on a forum about using their phone to VNC to their Raspberry Pi to watch Youtube videos because they are inspired by the lack of Adblock on the Youtube app on mobile. They started worrying about Bluetooth and battery constraints, and VNC, and using Bluetooth, and bandwidth and interference between Bluetooth and Wifi. Which is indeed solvable by googling "youtube client without ads" and you'll see NewPipe among the top results, which is an app you can install in 30 seconds to solve the problem. But when you have a hammer that is the Raspberry Pi, the Adblock problem starts to look like a nail.
Recently, a close friend of mine who is a founder of a small company back home asked me to advise him on making a website/app to have "Uber for X" (X being his non-tech business). Upon talking, I realized if he wants to compete by making a good website/app, it's both hard and expensive to do. If his tech model turns out to be relatively successful, a medium-sized company in tech will be able to easily copy his model and out-compete him. Perhaps all he wants to do only need a website to advertise but he doesn't need a website or an app to execute. All he needs is an Excel spreadsheet and a relatively competent secretary to manage that spreadsheet and call people with demand and supply. But when you have a hammer that is Uber, the supply-and-demand problem starts to look like a nail, even when you don't have millions of people using it in real-time.
And I see the same trend in Machine learning, Big data, AI, Cryptocurrency, Internet of Things, Social networks, Decentralized networks, etc. Everything in life, however trivial or hard, is a nail that can be solved with those fancy hammers. So we can have a tablet juxtaposed on a fridge, a bluetooth speaker integrated to a salt shaker, a subscription model for juicers, and machine learning for all kinds of social problems.
I enjoy hard problems a lot. In the last couple of years, working on CUDA kernels to do parallel string comparison is one of the topics I busted my chops on. Some problems are extremely hard and need really clever algorithms and tuning to solve. But alongside with those, there are problems that only need a generally good idea to solve with very little hard code required.
And that's the moment of enlightenment: Writing dumb scripts may become my niche as a person who "wrote an embedded OS."
Flare: An Approach to Routing in Lightning Network (2016) [pdf]
React in Patterns
A book about common design patterns used while developing with React. It includes techniques for composition, data flow, dependency management and more.
- Web (https://krasimir.gitbooks.io/react-in-patterns/content/)
- PDF (https://github.com/krasimir/react-in-patterns/blob/master/book.pdf)
- Mobi (https://www.gitbook.com/download/mobi/book/krasimir/react-in-patterns)
- ePub (https://www.gitbook.com/download/epub/book/krasimir/react-in-patterns)
- GitHub (https://github.com/krasimir/react-in-patterns)
GDPR isn't to blame for all the permission emails you're getting
By now, the emails will be incredibly familiar. They have the same chirpy tone, are being sent from brands and ask whether you'd like to get more emails from that company. (It's likely you completely forgot what the company was, let alone what you purchased from it in 2007).
"We're committed to managing and safeguarding the information you give us when looking for a job," reads a typical one from a recruitment website. "CLICK HERE TO STAY SIGNED UP," shouts another before continuing: "We don’t want to lose you, so please take action now". Some have even claimed user accounts will have to be deleted if a reply isn't recieved.
The majority of these emails cite the European General Data Protection Regulation (GDPR), which starts to be enforced on May 25. GDPR introduces changes to how businesses and organisations should handle personal information – and for companies faced with the prospect of huge fines for breaching the new rules, it's causing panic. And that's why you're getting all those emails.
"We’ve heard stories of email inboxes bursting with long emails from organisations asking people if they’re still happy to hear from them," Steve Wood, the deputy information commissioner for the UK wrote in a blog post earlier this week. "Think about whether you actually need to refresh consent before you send that email and don’t forget to put in place mechanisms for people to withdraw their consent easily," Wood says.
But, it turns out, most of these emails are pointless. "In the UK it has been the law since 2003 that you can only send a marketing email to an individual recipient when they have consented to receive it or you have an existing customer relationship with them and have offered them the opportunity to opt out," explains Jon Baines, data protection advisor at law firm Mishcon de Reya.
So why are they sending these emails? It's largely around the fear of GDPR. The regulation says companies can be fined up to €20 million or four per cent of their annual global turnover. Many companies are keen to get their systems in order. Although in the UK the Information Commissioner has made it clear it won't be heavy-handed with fines.
Baines believes a big reason why these emails are being sent at the moment is because of an "increased awareness around the fact that sending marketing emails requires either the consent of the recipient or an existing customer relationship". That awareness has been amplified because of the hype around GDPR.
However, the Privacy and Electronic Communications (EC Directive) Regulations – known as PECR for short – govern marketing messages. These are based upon a European e-privacy Directive and cover messages used for marketing – everything from the pesky emails to text messages.
GDPR doesn't replace PECR but sits alongside it and European regulators are coming up with a new set of e-privacy rules to replace it. Confused? So are the companies emailing you. The result is a slightly messy mix of rules: both GDPR and PECR are dense, legally complex and have a plethora of caveats with exemptions for different scenarios.
But the existence of PECR means that in a large amount of cases, companies may not have necessarily needed to send the emails re-asking for permission to keep in touch. "I think a lot of the emails people are receiving are unnecessary, because people have either already consented or are receiving them to business addresses," Baines says. Business email addresses – for instance, rowland@wired.co.uk – fall under GDPR as personal data, but for marketing messages consent to receive them may not be needed.
If people haven't already consented to receive marketing messages, the company sending them will have been in breach of PECR, potentially for many years.
But what is considered consent is a slightly murky affair. With the introduction of GDPR comes an updated definition of what consent is. It's complex but states consent has to be unambiguous and involve someone actively saying yes. For instance, a pre-ticked box saying you are willing to receive marketing emails doesn't count as unambiguous consent. But a box you have to actively tick does.
"If consent is the appropriate lawful basis then that energy and effort must be spent establishing informed, active, unambiguous consent," the ICO's Wood says. As well as consent, there are other ways for companies to obtain and process a person's data and still be inline with the requirements of GPDR.
Ultimately, the overlap between PECR and GDPR has meant some companies will lose subscribers to their mailing lists that have just ignored the deluge of messages being received. In an almost ironic twist, last year the ICO fined Honda and Flybe for sending emails asking people to agree to getting more emails. "Sending emails to determine whether people want to receive marketing without the right consent, is still marketing and it is against the law," the ICO said at the time.
But there also have been more malicious examples of email consent messages being sent. UK-based cybersecurity firm Redscan discovered phishing emails have been sent that were disguised as GDPR-related emails. The firm spotted a fake email that had been made to look like it was from Airbnb, stating its customers should click on a particular link to update their privacy settings.
When clicked, the link would take users to a spoofed Airbnb website that collected all the details entered and saved them to systems belonging to the hackers that created the website. “The irony won’t be lost on anyone that cybercriminals are exploiting the arrival of new data protection regulations to steal people’s data,” Redscan's director of cybersecurity Mark Nicholls, said in a statement.
Big Integers in Zig
I’ve recently been writing a big-integer library, zig-bn in the Zig programming language.
The goal is to have reasonable performance in a fairly simple implementation with a generic implementation with no assembly routines.
I’ll list a few nice features about Zig which I think suit this sort of library before exploring some preliminary performance comparisons and what in the language encourages the speed.
Transparent Local Allocators
Unlike most languages, the Zig standard library does not have a default allocator implementation. Instead, allocators are specified at runtime, passed as arguments to parts of the program which require it. I’ve used the same idea with this big integer library.
The nice thing about this is it is very easy to use different allocators on a per-integer level. A practical example may be to use a faster stack-based allocator for small temporaries, which can be bounded by some upper limit.
// Allocate an integer on the heap
var heap_allocator = std.heap.c_allocator;
var a = try BigInt.init(heap_allocator);
defer a.deinit();
// ... and one on the stack
var stack_allocator = std.debug.global_allocator;
var b = try BigInt.init(stack_allocator);
defer b.deinit();
// ... and some in a shared arena with shared deallocation
var arena = ArenaAllocator.init(heap_allocator);
defer arena.deinit();
var c = try BigInt.init(&arena.allocator);
var d = try BigInt.init(&arena.allocator);
This isn’t possible in GMP, which allows specifying custom allocation functions, but which are shared across the all objects. Only one set of memory functions can be used per program.
Handling OOM
One issue with GMP is that out-of-memory conditions cannot easily be handled. The only feasible way in-process way is to override the allocation functions and use exceptions in C++, or longjmp back to a clean-up function which can attempt to handle this as best as it can.
Since Zig was designed to handle allocation in a different way to C, we can handle these much more easily. For any operation that could fail (either out-of-memory or some other generic error), we can handle the error or pass it back up the call-stack.
var a = try BigInt.init(failing_allocator);
// maybe got an out-of-memory! if we did, lets pass it back to the caller
try a.set(0x123294781294871290478129478);
There is the small detriment that it is required to explicitly handle possible failing functions (and for zig-bn, that is practically all of them). The provided syntax makes this minimal boilerplate, and unlike GMP we can at least see where something could go wrong and not have to rely on hidden error control flow.
Compile-time switch functions
Zig provides a fair amount of compile-time support. A particular feature is the
ability to pass an arbitrary type var
to a function. This gives a duck-typing
sort of feature and can provide more fluent interfaces than we otherwise could
write.
For example:
pub fn plusOne(x: var) @typeOf(x) {
const T = @typeOf(x);
switch (@typeInfo(T)) {
TypeId.Int => {
return x + 1;
},
TypeId.Float => {
return x + 1.0;
},
else => {
@compileError("can't handle this type, sorry!");
},
}
}
This feature is used to combine set
functions into a single function
instead of needing a variety of functions for each type as in GMP (mpz_set_ui
,mpz_set_si
, …).
Peformance
Perhaps the most important detail of a big integer library is its raw performance. I’ll walk through the low-level addition routine and look at some techniques we can use to speed it up incrementally.
The benchmarks used here can be found in this repository. We simply compute the 50000’th fibonacci number. This requires addition and subtraction only.
Our initial naive implementation is as follows. It uses 32-bit limbs (so our double-limb is a 64-bit integer) and simply propagates the carry. We force inline the per-limb division and our debug asserts are compiled out in release mode. Memory allocation is handled in the calling function.
// a + b + *carry, sets carry to overflow bits
fn addLimbWithCarry(a: Limb, b: Limb, carry: &Limb) Limb {
const result = DoubleLimb(a) + DoubleLimb(b) + DoubleLimb(*carry);
*carry = @truncate(Limb, result >> Limb.bit_count);
return @truncate(Limb, result);
}
fn lladd(r: []Limb, a: []const Limb, b: []const Limb) void {
debug.assert(a.len != 0 and b.len != 0);
debug.assert(a.len >= b.len);
debug.assert(r.len >= a.len + 1);
var i: usize = 0;
var carry: Limb = 0;
while (i < b.len) : (i += 1) {
r[i] = @inlineCall(addLimbWithCarry, a[i], b[i], &carry);
}
while (i < a.len) : (i += 1) {
r[i] = @inlineCall(addLimbWithCarry, a[i], 0, &carry);
}
r[i] = carry;
}
The results are as follows:
fib-zig: 0:00.75 real, 0.75 user, 0.00 sys
debug: 0:06.61 real, 6.60 user, 0.00 sys
For comparison, the GMP run time is:
fib-c: 0:00.17 real, 0.17 user, 0.00 sys
A more comparable C implementation (python) is:
fib-py: 0:00.77 real, 0.77 user, 0.00 sys
A bit of work to do against GMP! We aren’t out of the ballpark compared to less heavily optimized libraries. We are comparing the debug runtime version as well since I consider it important that it runs reasonably quick for a good development cycle, and not orders of magnitude slower.
Leveraging Compiler Addition Builtins
Zig provides a number of LLVM builtins to us. While these shouldn’t
usually be required, they can be valuable in certain cases. We’ll be using the
@addWithOverflow
builtin to perform addition while catching possible overflow.
Our new addition routine is now:
fn lladd(r: []Limb, a: []const Limb, b: []const Limb) void {
debug.assert(a.len != 0 and b.len != 0);
debug.assert(a.len >= b.len);
debug.assert(r.len >= a.len + 1);
var i: usize = 0;
var carry: Limb = 0;
while (i < b.len) : (i += 1) {
var c: Limb = 0;
c += Limb(@addWithOverflow(Limb, a[i], b[i], &r[i]));
c += Limb(@addWithOverflow(Limb, r[i], carry, &r[i]));
carry = c;
}
while (i < a.len) : (i += 1) {
carry = Limb(@addWithOverflow(Limb, a[i], carry, &r[i]));
}
r[i] = carry;
}
The new results:
fib-zig: 0:00.69 real, 0.69 user, 0.00 sys
debug: 0:06.47 real, 6.42 user, 0.00 sys
A minimal, but noticeable improvement.
Improving Debug Performance
Debug mode in Zig performs runtime bounds checks which include array checks and other checks for possible undefined behavior.
For these inner loops this is a lot of overhead. Our assertions are sufficient to cover all the looping cases. We can disable these safety checks on a per-block basis:
fn lladd(r: []Limb, a: []const Limb, b: []const Limb) void {
@setRuntimeSafety(false);
...
}
fib-zig: 0:00.69 real, 0.69 user, 0.00 sys
debug: 0:03.91 real, 3.90 user, 0.00 sys
That is a lot better.
64-bit limbs (and 128-bit integers).
We have been using 32-bit words this entire time. Our machine word-size however is 64-bits. Lets change our limb size only, and rerun our tests.
fib-zig: 0:00.35 real, 0.35 user, 0.00 sys
debug: 0:01.95 real, 1.95 user, 0.00 sys
Unsurprisingly, this is now twice as fast! It is fairly useful if your compiler supports builtin 128-bit integer types when using 64-bit limbs. The reason is it makes handling overflow in addition and especially multiplication much more simple and easier to optimize by the compiler. Otherwise, software workarounds need to be done which can be much less performant.
Implementation Performance Summary
Benchmark code here.
A performance comparison using the following libraries/languages:
Note that C and Go use assembly, while Rust/CPython both are implemented in Rust and C respectively, and are comparable as non-tuned generic implementations.
System Info
Architecture: x86_64
Model name: Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz
Compiler Versions
zig: 0.2.0.ef3111be
gcc: gcc (GCC) 8.1.0
go: go version go1.10.2 linux/amd64
py: Python 3.6.5
rust: rustc 1.25.0 (84203cac6 2018-03-25)
Addition/Subtraction Test
Computes the 50,000th fibonacci number.
fib-zig: 0:00.35 real, 0.35 user, 0.00 sys
fib-c: 0:00.17 real, 0.17 user, 0.00 sys
fib-go: 0:00.20 real, 0.20 user, 0.00 sys
fib-py: 0:00.75 real, 0.75 user, 0.00 sys
fib-rs: 0:00.81 real, 0.81 user, 0.00 sys
Multiplication/Addition Test
Computes the 50,000th factorial.
Zig uses naive multiplication only while all others use asymptotically faster algorithms such as (karatsuba multiplication)[https://en.wikipedia.org/wiki/Karatsuba_algorithm].
fac-zig: 0:00.54 real, 0.54 user, 0.00 sys
fac-c: 0:00.18 real, 0.18 user, 0.00 sys
fac-go: 0:00.21 real, 0.21 user, 0.00 sys
fac-py: 0:00.50 real, 0.48 user, 0.02 sys
fac-rs: 0:00.53 real, 0.53 user, 0.00 sys
Division Test (single-limb)
Computes the 20,000th factorial then divides it back down to 1.
Rust is most likely much slower since it doesn’t special-case length 1 limbs.
facdiv-zig: 0:00.99 real, 0.98 user, 0.00 sys
facdiv-c: 0:00.16 real, 0.16 user, 0.00 sys
facdiv-go: 0:00.93 real, 0.93 user, 0.00 sys
facdiv-py: 0:00.99 real, 0.99 user, 0.00 sys
facdiv-rs: 0:05.01 real, 4.98 user, 0.00 sys
Summary
In short, zig-bn has managed to get fairly good performance from a pretty simple implementation. It is twice as fast as other generic libraries for the functions we have optimized, and is likely to be similarly fast using comparable algorithms for multiplication/division.
While I consider these good results for a very simple implementation (<1k loc, excluding tests) it is still lacking vs. GMP. Most notably, the algorithms used are much more advanced and the gap would continue to grow as numbers grew even larger. Hats off to the GMP project, as always.
A good start for a weeks work.
String functions: Nim vs. Python comparison (2017)
While learning the Nim language and trying to correlate that with my Python 3 knowledge, I came across this awesome comparison table ofstring manipulation functions between the two languages.
My utmost gratitude goes to the developers of Nim, Python, Org,ob-nim
and ob-python
, and of course Hugo which allowed me to
publish my notes in this presentable format.
Here are the code samples and their outputs. In each mini-section below, you will find a Python code snippet, followed by its output, and then the same implementation in Nim, followed by the output of that.
The tool versions used are:
Updates #
- Update the Nim snippets output using the improved
echo
! Theecho
output difference is notable in the.split
examples. This fixes the issue about confusingecho
outputs that I raised in Nim Issue #6225. Big thanks toFabian Keller for Nim PR #6825! - Update the Understanding the
^N
syntax example that gave incorrect output before Nim Issue #6223 got fixed. - Update the
.join
example that did not work before Nim Issue #6210 got fixed. - Use the binary operator
..<
instead of the combination of binary operator..
and the deprecated unary<
operator.
String slicing #
All characters except last #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str[:-1])
a bc def aghij cklm danopqrstuv adefwxyz zy
varstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"# Always add a space around the .. and ..< operatorsechostr[0..<str.high]# orechostr[0..^2]# orechostr[..^2]
a bc def aghij cklm danopqrstuv adefwxyz zy
a bc def aghij cklm danopqrstuv adefwxyz zy
a bc def aghij cklm danopqrstuv adefwxyz zy
Understanding the ^N
syntax #
varstr="abc"# Always add a space around the .. and ..< operatorsecho"1st char(0) to last, including \\0(^0) : ",str[0..^0]# Interestingly, this also prints the NULL character in the output.. looks like "abc^@" in Emacsecho"1st char(0) to last (^1) «3rd» : ",str[0..^1]echo"1st char(0) to 2nd-to-last(^2) «2nd» : ",str[0..^2]echo"1st char(0) to 3rd-to-last(^3) «1st» : ",str[0..^3]echo"1st char(0) to 4th-to-last(^4) «0th» : ",str[0..^4]# echo "1st char(0) to 4th-to-last(^4) «0th» : ", str[0 .. ^5] # Error: unhandled exception: value out of range: -1 [RangeError]# echo "2nd char(1) to 4th-to-last(^4) «0th» : ", str[1 .. ^4] # Error: unhandled exception: value out of range: -1 [RangeError]echo"2nd char(1) to 3rd-to-last(^3) «1st» : ",str[1..^3]echo"2nd char(1) to 2nd-to-last(^2) «2nd» : ",str[1..^2]echo"2nd char(1) to last, (^1) «3rd» : ",str[1..^1]echo"Now going a bit crazy .."echo" 2nd-to-last(^2) «2nd» char to 3rd(2) : ",str[^2..2]echo" 2nd-to-last(^2) «2nd» char to last(^1) «3rd» : ",str[^2..^1]echo" 3rd-to-last(^3) «1st» char to 3rd(2) : ",str[^3..2]
1st char(0) to last, including \0(^0) : abc
1st char(0) to last (^1) «3rd» : abc
1st char(0) to 2nd-to-last(^2) «2nd» : ab
1st char(0) to 3rd-to-last(^3) «1st» : a
1st char(0) to 4th-to-last(^4) «0th» :
2nd char(1) to 3rd-to-last(^3) «1st» :
2nd char(1) to 2nd-to-last(^2) «2nd» : b
2nd char(1) to last, (^1) «3rd» : bc
Now going a bit crazy ..
2nd-to-last(^2) «2nd» char to 3rd(2) : bc
2nd-to-last(^2) «2nd» char to last(^1) «3rd» : bc
3rd-to-last(^3) «1st» char to 3rd(2) : abc
Notes #
It is recommended to always use a space around the
..
and..<
binary operators to get consistent results (and no compilation errors!). Examples:[0 ..< str.high]
,[0 .. str.high]
,[0 .. ^2]
,[ .. ^2]
. This is based on the tip by Andreas Rumpf (also one of the core devs of Nim). You will find the full discussion around this topic of dots and spaces in Nim Issue #6216.Special ascii chars like
%
.
&
$
are collected into a single operator token. – AraqTo repeat: Always add a space around the
..
and..<
operators.As of commit 70ea45cdba, the
<
unary operator is deprecated! So do[0 ..< str.high]
instead of[0 .. <str.high]
(see Nim Issue #6788).With the example
str
variable value being"abc"
, earlier bothstr[0 .. ^5]
andstr[1 .. ^4]
returned an empty stringincorrectly! (see Nim Issue #6223). That now got fixed in commit b74a5148a9. After the fix, those will cause this error:system.nim(3534) [] system.nim(2819) sysFatal Error: unhandled exception: value out of range: -1 [RangeError]
Also after this fix,
str[0 .. ^0]
outputsabc^@
(where^@
is the representation of NULL character).. very cool!
All characters except first #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str[1:])
bc def aghij cklm danopqrstuv adefwxyz zyx
varstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"# echo str[1 .. ] # Does not work.. Error: expression expected, but found ']'# https://github.com/nim-lang/Nim/issues/6212# Always add a space around the .. and ..< operatorsechostr[1..str.high]# orechostr[1..^1]# second(1) to last(^1)
bc def aghij cklm danopqrstuv adefwxyz zyx
bc def aghij cklm danopqrstuv adefwxyz zyx
All characters except first and last #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str[1:-1])
bc def aghij cklm danopqrstuv adefwxyz zy
varstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"# Always add a space around the .. and ..< operatorsechostr[1..<str.high]# orechostr[1..^2]# second(1) to second-to-last(^2)
bc def aghij cklm danopqrstuv adefwxyz zy
bc def aghij cklm danopqrstuv adefwxyz zy
Count #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str.count('a'))print(str.count('de'))
importstrutilsvarstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"echostr.count('a')echostr.count("de")
Starts/ends with #
Starts With #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str.startswith('a'))print(str.startswith('a\t'))print(str.startswith('z'))
importstrutilsvarstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"echostr.startsWith('a')# Recommended Nim style# orechostr.startswith('a')# orechostr.starts_with('a')echostr.startsWith("a\t")echostr.startsWith('z')
true
true
true
true
false
Notes #
- All Nim identifiers are case and underscore insensitive (except
for the first character of the identifier), as seen in the above
example. So any of
startsWith
orstartswith
orstarts_with
would work the exact same way. - Though, it has to be noted that using the camelCase variant
(
startsWith
) is preferred in Nim.
Ends With #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str.endswith('x'))print(str.endswith('yx'))print(str.endswith('z'))
importstrutilsvarstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"echostr.endsWith('x')echostr.endsWith("yx")echostr.endsWith('z')
Expand Tabs #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str.expandtabs())print(str.expandtabs(4))
a bc def aghij cklm danopqrstuv adefwxyz zyx
a bc def aghij cklm danopqrstuv adefwxyz zyx
importstrmiscvarstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"echostr.expandTabs()echostr.expandTabs(4)
a bc def aghij cklm danopqrstuv adefwxyz zyx
a bc def aghij cklm danopqrstuv adefwxyz zyx
Find/Index #
Find (from left) #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str.find('a'))print(str.find('b'))print(str.find('c'))print(str.find('zyx'))print(str.find('aaa'))
importstrutilsvarstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"echostr.find('a')echostr.find('b')echostr.find('c')echostr.find("zyx")echostr.find("aaa")
Find from right #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str.rfind('a'))print(str.rfind('b'))print(str.rfind('c'))print(str.rfind('zyx'))print(str.rfind('aaa'))
importstrutilsvarstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"echostr.rfind('a')echostr.rfind('b')echostr.rfind('c')echostr.rfind("zyx")echostr.rfind("aaa")
Index (from left) #
From Python 3 docs,
Like
find()
, but raiseValueError
when the substring is not found.
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str.index('a'))print(str.index('b'))print(str.index('c'))print(str.index('zyx'))# print(str.index('aaa')) # Throws ValueError: substring not found
Nim does not have an error raising index
function like that
out-of-box, but something like that can be done with:
importstrutilsvarstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"# https://nim-lang.org/docs/strutils.html#find,string,string,Natural,Natural# proc find(s, sub: string; start: Natural = 0; last: Natural = 0): int {..}proc index(s,sub:auto;start:Natural=0;last:Natural=0):int=result=s.find(sub,start,last)ifresult<0:raisenewException(ValueError,"$1 not found in $2".format(sub,s))echostr.index('a')echostr.index('b')echostr.index('c')echostr.index("zyx")# echo str.index("aaa") # Error: unhandled exception: aaa not found in a bc def aghij cklm danopqrstuv adefwxyz zyx [ValueError]
Notes #
- No Nim equivalent, but I came up with my own
index
proc for Nim above.
Index from right #
From Python 3 docs,
Like
rfind()
, but raiseValueError
when the substring is not found.
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str.rindex('a'))print(str.rindex('b'))print(str.rindex('c'))print(str.rindex('zyx'))# print(str.rindex('aaa')) # Throws ValueError: substring not found
Nim does not have an error raising rindex
function like that
out-of-box, but something like that can be done with:
importstrutilsvarstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"# https://nim-lang.org/docs/strutils.html#rfind,string,string,int# proc rfind(s, sub: string; start: int = - 1): int {..}proc rindex(s,sub:auto;start:int=-1):int=result=s.rfind(sub,start)ifresult<0:raisenewException(ValueError,"$1 not found in $2".format(sub,s))echostr.rindex('a')echostr.rindex('b')echostr.rindex('c')echostr.rindex("zyx")# echo str.rindex("aaa") # Error: unhandled exception: aaa not found in a bc def aghij cklm danopqrstuv adefwxyz zyx [ValueError]
Notes #
- No Nim equivalent, but I came up with my own
rindex
proc for Nim above.
Format #
print('{} {}'.format(1,2))print('{} {}'.format('a','b'))
importstrutils# echo "$1 $2" % [1, 2] # This gives error. % cannot have int list as arg, has to be string list# echo "$1 $2" % ['a', 'b'] # This gives error. % cannot have char list as arg, has to be string listecho"$1$2"%["a","b"]# orecho"$1$2".format(["a","b"])# orecho"$1$2".format("a","b")# orecho"$1$2".format('a','b')# format, unlike % does auto-stringification of the inputecho"$1$2".format(1,2)
Using strfmt
module #
importstrfmtecho"{} {}".fmt(1,0)echo"{} {}".fmt('a','b')echo"{} {}".fmt("abc","def")echo"{0} {1} {0}".fmt(1,0)echo"{0.x} {0.y}".fmt((x:1,y:"foo"))
1 0
a b
abc def
1 0 1
1 foo
Notes #
- Thanks to the tip by Daniil Yarancev, I can
use the
strfmt
module to get Python.format()
-like formatting function. - You will need to install it first by doing
nimble install strfmt
. - See this for full documentation on
strfmt
. The awesome thing is that it allows using a format syntax that’s similar to Python’s Format Specification Mini-Language🙌
String Predicates #
Is Alphanumeric? #
print('abc'.isalnum())print('012'.isalnum())print('abc012'.isalnum())print('abc012_'.isalnum())print('{}'.isalnum())print('Unicode:')print('ábc'.isalnum())
True
True
True
False
False
Unicode:
True
importstrutilsecho"abc".isAlphaNumeric()echo"012".isAlphaNumeric()echo"abc012".isAlphaNumeric()echo"abc012_".isAlphaNumeric()echo"{}".isAlphaNumeric()echo"[Wrong] ","ábc".isAlphaNumeric()# Returns false! isAlphaNumeric works only for ascii.
true
true
true
false
false
[Wrong] false
TODO Figure out how to write unicode-equivalent of isAlphaNumeric
#
Is Alpha? #
print('abc'.isalpha())print('012'.isalpha())print('abc012'.isalpha())print('abc012_'.isalpha())print('{}'.isalpha())print('Unicode:')print('ábc'.isalpha())
True
False
False
False
False
Unicode:
True
importstrutilsexceptisAlphaimportunicodeecho"abc".isAlphaAscii()echo"012".isAlphaAscii()echo"abc012".isAlphaAscii()echo"abc012_".isAlphaAscii()echo"{}".isAlphaAscii()echo"Unicode:"echounicode.isAlpha("ábc")# orechoisAlpha("ábc")# unicode prefix is not needed# because of import strutils except isAlpha# orecho"ábc".isAlpha()# from unicode
true
false
false
false
false
Unicode:
true
true
true
Notes #
Thanks to the tip from Dominik Picheta on the use of
except
inimport
:importstrutilsexceptisAlphaimportunicode
That prevents the ambiguous call error like below as we are specifying that
import
everything fromstrutils
,except
for theisAlpha
proc. Thus theunicode
version ofisAlpha
proc is used automatically.nim_src_28505flZ.nim(14, 13) Error: ambiguous call; both strutils.isAlpha(s: string)[declared in lib/pure/strutils.nim(289, 5)] and unicode.isAlpha(s: string)[declared in lib/pure/unicode.nim(1416, 5)] match for: (string)
Is Digit? #
print('abc'.isdigit())print('012'.isdigit())print('abc012'.isdigit())print('abc012_'.isdigit())print('{}'.isdigit())
False
True
False
False
False
importstrutilsecho"abc".isDigit()echo"012".isDigit()echo"abc012".isDigit()echo"abc012_".isDigit()echo"{}".isDigit()
false
true
false
false
false
Is Lower? #
print('a'.islower())print('A'.islower())print('abc'.islower())print('Abc'.islower())print('aBc'.islower())print('012'.islower())print('{}'.islower())print('ABC'.islower())print('À'.islower())print('à'.islower())
True
False
True
False
False
False
False
False
False
True
importstrutilsexceptisLowerimportunicodeecho'a'.isLowerAscii()echo'A'.isLowerAscii()echo"abc".isLowerAscii()echo"Abc".isLowerAscii()echo"aBc".isLowerAscii()echo"012".isLowerAscii()echo"{}".isLowerAscii()echo"ABC".isLowerAscii()echo"À".isLowerAscii()echo"[Wrong] ","à".isLowerAscii()# Returns false! As the name suggests, works only for ascii.echo"À".isLower()# from unicodeecho"à".isLower()# from unicode# echo "à".unicode.isLower() # Does not work, Error: undeclared field: 'unicode'
true
false
true
false
false
false
false
false
false
[Wrong] false
false
true
Notes #
isLower
fromstrutils
is deprecated. UseisLowerAscii
instead, orisLower
fromunicode
(as done above).- To check if a non-ascii alphabet is in lower case, use
unicode.isLower
.
Is Upper? #
print('a'.isupper())print('A'.isupper())print('abc'.isupper())print('Abc'.isupper())print('aBc'.isupper())print('012'.isupper())print('{}'.isupper())print('ABC'.isupper())print('À'.isupper())print('à'.isupper())
False
True
False
False
False
False
False
True
True
False
importstrutilsexceptisUpperimportunicodeecho'a'.isUpperAscii()echo'A'.isUpperAscii()echo"abc".isUpperAscii()echo"Abc".isUpperAscii()echo"aBc".isUpperAscii()echo"012".isUpperAscii()echo"{}".isUpperAscii()echo"ABC".isUpperAscii()echo"[Wrong] ","À".isUpperAscii()# Returns false! As the name suggests, works only for ascii.echo"à".isUpperAscii()echo"À".isUpper()# from unicodeecho"à".isUpper()# from unicode# echo "À".unicode.isUpper() # Does not work, Error: undeclared field: 'unicode'
false
true
false
false
false
false
false
true
[Wrong] false
false
true
false
Notes #
isUpper
fromstrutils
is deprecated. UseisUpperAscii
instead, orisUpper
fromunicode
(as done above).- To check if a non-ascii alphabet is in upper case, use
unicode.isUpper
.
Is Space? #
print(''.isspace())print(' '.isspace())print('\t'.isspace())print('\r'.isspace())print('\n'.isspace())print(' \t\n'.isspace())print('abc'.isspace())print('Testing with ZERO WIDTH SPACE unicode character below:')print('[Wrong] {}'.format(''.isspace()))# Returns false! That's, I believe, incorrect behavior.
False
True
True
True
True
True
False
Testing with ZERO WIDTH SPACE unicode character below:
[Wrong] False
importstrutilsexceptisSpaceimportunicodeecho"".isSpaceAscii()# empty string has to be in double quotesecho' '.isSpaceAscii()echo'\t'.isSpaceAscii()echo'\r'.isSpaceAscii()echo"\n".isSpaceAscii()# \n is a string, not a character in Nimecho" \t\n".isSpaceAscii()echo"abc".isSpaceAscii()echo"Testing with ZERO WIDTH SPACE unicode character below:"echo"[Wrong] ","".isSpaceAscii()# Returns false! As the name suggests, works only for ascii.echo"".isSpace()# from unicode
false
true
true
true
true
true
false
Testing with ZERO WIDTH SPACE unicode character below:
[Wrong] false
true
Notes #
- Empty string results in a false result for both Python and Nim
variants of
isspace
. \n
is a string, not a character in Nim, because based on the OS,\n
can comprise of one or more characters.isSpace
fromstrutils
is deprecated. UseisSpaceAscii
instead, orisSpace
fromunicode
(as done above).- To check if a non-ascii alphabet is in space case, use
unicode.isSpace
. - Interestingly, Nim’s
isSpace
fromunicode
module returns true forZERO WIDTH SPACE
unicode character (0x200b
) as input, but Python’sisspace
returns false. I believe Python’s behavior here is incorrect.
Is Title? #
print(''.istitle())print('this is not a title'.istitle())print('This Is A Title'.istitle())print('This Is À Title'.istitle())print('This Is Not a Title'.istitle())
False
False
True
True
False
importunicodeecho"".isTitle()echo"this is not a title".isTitle()echo"This Is A Title".isTitle()echo"This Is À Title".isTitle()echo"This Is Not a Title".isTitle()
false
false
true
true
false
Join #
print(' '.join(['a','b','c']))print('xx'.join(['a','b','c']))
importstrutilsecho"Sequences:"# echo @["a", "b", "c"].join(' ') # Error: type mismatch: got (seq[string], char)echo@["a","b","c"].join(" ")echojoin(@["a","b","c"]," ")echo"Lists:"echo["a","b","c"].join(" ")# Works after Nim issue # 6210 got fixed.echo(["a","b","c"].join(" "))# Works!echojoin(["a","b","c"]," ")# Works!varlist=["a","b","c"]echolist.join(" ")# Works too!echo@["a","b","c"].join("xx")
Sequences:
a b c
a b c
Lists:
a b c
a b c
a b c
a b c
axxbxxc
Notes #
- The second arg to join, the separator argument has to be a string, cannot be a character.
echo ["a", "b", "c"].join(" ")
did not work prior to the fix in commit ddc131cf07 (see Nim Issue #6210), but now it does!
Justify with filling #
Center Justify with filling #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str.center(80))print(str.center(80,'*'))
a bc def aghij cklm danopqrstuv adefwxyz zyx
******************a bc def aghij cklm danopqrstuv adefwxyz zyx******************
importstrutilsvarstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"echostr.center(80)echostr.center(80,'*')# orechocenter(str,80,'*')
a bc def aghij cklm danopqrstuv adefwxyz zyx
******************a bc def aghij cklm danopqrstuv adefwxyz zyx******************
******************a bc def aghij cklm danopqrstuv adefwxyz zyx******************
Left Justify with filling #
print('abc'.ljust(2,'*'))print('abc'.ljust(10,'*'))
importstrutilsproc ljust(s:string;count:Natural;padding=' '):string=result=sletstrlen:int=len(s)ifstrlen<count:result.add(padding.repeat(count-strlen))echo"abc".ljust(2,'*')echo"abc".ljust(10,'*')
Notes #
- No Nim equivalent, but I came up with my own
ljust
proc for Nim above.
Right Justify with filling #
print('abc'.rjust(10,'*'))
importstrutilsecho"abc".align(10,'*')
Zero Fill #
print('42'.zfill(5))print('-42'.zfill(5))print(' -42'.zfill(5))
importstrutilsecho"Using align:"echo"42".align(5,'0')echo"-42".align(5,'0')echo"Using zfill:"proc zfill(s:string;count:Natural):string=letstrlen:int=len(s)ifstrlen<count:ifs[0]=='-':result="-"result.add("0".repeat(count-strlen))result.add(s[1..s.high])else:result="0".repeat(count-strlen)result.add(s)else:result=secho"42".zfill(5)echo"-42".zfill(5)echo" -42".zfill(5)
Using align:
00042
00-42
Using zfill:
00042
-0042
0 -42
Notes #
- The
align
in Nim does not do the right thing as the Pythonzfill
does when filling zeroes on the left in strings representing negative numbers. - No Nim equivalent, but I came up with my own
zfill
proc for Nim above.
Case conversion #
To Lower #
print('a'.lower())print('A'.lower())print('abc'.lower())print('Abc'.lower())print('aBc'.lower())print('012'.lower())print('{}'.lower())print('ABC'.lower())print('À'.lower())print('à'.lower())
a
a
abc
abc
abc
012
{}
abc
à
à
importstrutilsexcepttoLowerimportunicodeecho'a'.toLowerAscii()echo'A'.toLowerAscii()echo"abc".toLowerAscii()echo"Abc".toLowerAscii()echo"aBc".toLowerAscii()echo"012".toLowerAscii()echo"{}".toLowerAscii()echo"ABC".toLowerAscii()echo"[Wrong] ","À".toLowerAscii()# Does not work! As the name suggests, works only for ascii.echo"à".toLowerAscii()echo"À".toLower()# from unicodeecho"à".toLower()# from unicode
a
a
abc
abc
abc
012
{}
abc
[Wrong] À
à
à
à
Notes #
toLower
fromstrutils
is deprecated. UsetoLowerAscii
instead, ortoLower
fromunicode
(as done above).- To convert a non-ascii alphabet to lower case, use
unicode.toLower
.
To Upper #
print('a'.upper())print('A'.upper())print('abc'.upper())print('Abc'.upper())print('aBc'.upper())print('012'.upper())print('{}'.upper())print('ABC'.upper())print('À'.upper())print('à'.upper())
A
A
ABC
ABC
ABC
012
{}
ABC
À
À
importstrutilsexcepttoUpperimportunicodeecho'a'.toUpperAscii()echo'A'.toUpperAscii()echo"abc".toUpperAscii()echo"Abc".toUpperAscii()echo"aBc".toUpperAscii()echo"012".toUpperAscii()echo"{}".toUpperAscii()echo"ABC".toUpperAscii()echo"À".toUpperAscii()echo"[Wrong] ","à".toUpperAscii()# Does not work! As the name suggests, works only for ascii.echo"À".toUpper()# from unicodeecho"à".toUpper()# from unicode
A
A
ABC
ABC
ABC
012
{}
ABC
À
[Wrong] à
À
À
Notes #
toUpper
fromstrutils
is deprecated. UsetoUpperAscii
instead, ortoUpper
fromunicode
(as done above).- To convert a non-ascii alphabet to upper case, use
unicode.toUpper
.
Capitalize #
str="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"print(str.capitalize())
A bc def aghij cklm danopqrstuv adefwxyz zyx
importstrutilsvarstr="a\tbc\tdef\taghij\tcklm\tdanopqrstuv\tadefwxyz\tzyx"echostr.capitalizeAscii# orechocapitalizeAscii(str)
A bc def aghij cklm danopqrstuv adefwxyz zyx
A bc def aghij cklm danopqrstuv adefwxyz zyx
To Title #
print('convert this to title á û'.title())
Convert This To Title Á Û
importunicodeecho"convert this to title á û".title()
Convert This To Title Á Û
Swap Case #
print('Swap CASE example á û Ê'.swapcase())print('Swap CASE example á û Ê'.swapcase().swapcase())
sWAP case EXAMPLE Á Û ê
Swap CASE example á û Ê
importunicodeecho"Swap CASE example á û Ê".swapcase()echo"Swap CASE example á û Ê".swapcase().swapcase()
sWAP case EXAMPLE Á Û ê
Swap CASE example á û Ê
Notes #
- See this SO Q/A to read about few cases where
s.swapcase().swapcase()==s
is not true (at least for Python).
Strip #
Left/leading and right/trailing Strip #
print('«'+' spacious '.strip()+'»')print('www.example.com'.strip('cmowz.'))print('mississippi'.strip('mipz'))
«spacious»
example
ssiss
importstrutilsecho"«"," spacious ".strip(),"»"echo"www.example.com".strip(chars={'c','m','o','w','z','.'})echo"mississippi".strip(chars={'m','i','p','z'})
«spacious»
example
ssiss
Notes #
- Python
strip
takes a string as an argument to specify the letters that need to be stripped off the input string. But Nimstrip
requires a Set of characters.
Left/leading Strip #
print('«'+' spacious '.lstrip()+'»')print('www.example.com'.lstrip('cmowz.'))print('mississippi'.lstrip('mipz'))
«spacious »
example.com
ssissippi
importstrutilsecho"«"," spacious ".strip(trailing=false),"»"echo"www.example.com".strip(trailing=false,chars={'c','m','o','w','z','.'})echo"mississippi".strip(trailing=false,chars={'m','i','p','z'})
«spacious »
example.com
ssissippi
Right/trailing Strip #
print('«'+' spacious '.rstrip()+'»')print('www.example.com'.rstrip('cmowz.'))print('mississippi'.rstrip('mipz'))
« spacious»
www.example
mississ
importstrutilsecho"«"," spacious ".strip(leading=false),"»"echo"www.example.com".strip(leading=false,chars={'c','m','o','w','z','.'})echo"mississippi".strip(leading=false,chars={'m','i','p','z'})
« spacious»
www.example
mississ
Partition #
First occurrence partition #
print('ab:ce:ef:ce:ab'.partition(':'))print('ab:ce:ef:ce:ab'.partition('ce'))
('ab', ':', 'ce:ef:ce:ab')
('ab:', 'ce', ':ef:ce:ab')
importstrmiscecho"ab:ce:ef:ce:ab".partition(":")# The argument is a string, not a characterecho"ab:ce:ef:ce:ab".partition("ce")
(Field0: "ab", Field1: ":", Field2: "ce:ef:ce:ab")
(Field0: "ab:", Field1: "ce", Field2: ":ef:ce:ab")
Right partition or Last occurrence partition #
print('ab:ce:ef:ce:ab'.rpartition(':'))print('ab:ce:ef:ce:ab'.rpartition('ce'))
('ab:ce:ef:ce', ':', 'ab')
('ab:ce:ef:', 'ce', ':ab')
importstrmiscecho"ab:ce:ef:ce:ab".rpartition(":")# The argument is a string, not a character# orecho"ab:ce:ef:ce:ab".partition(":",right=true)echo"ab:ce:ef:ce:ab".rpartition("ce")# orecho"ab:ce:ef:ce:ab".partition("ce",right=true)
(Field0: "ab:ce:ef:ce", Field1: ":", Field2: "ab")
(Field0: "ab:ce:ef:ce", Field1: ":", Field2: "ab")
(Field0: "ab:ce:ef:", Field1: "ce", Field2: ":ab")
(Field0: "ab:ce:ef:", Field1: "ce", Field2: ":ab")
Replace #
print('abc abc abc'.replace(' ab','-xy'))print('abc abc abc'.replace(' ab','-xy',0))print('abc abc abc'.replace(' ab','-xy',1))print('abc abc abc'.replace(' ab','-xy',2))
abc-xyc-xyc
abc abc abc
abc-xyc abc
abc-xyc-xyc
importstrutilsecho"abc abc abc".replace(" ab","-xy")# echo "abc abc abc".replace(" ab", "-xy", 0) # Invalid, does not expect a count:int argument# echo "abc abc abc".replace(" ab", "-xy", 1) # Invalid, does not expect a count:int argument# echo "abc abc abc".replace(" ab", "-xy", 2) # Invalid, does not expect a count:int argument
Notes #
- Nim does not allow specifying the number of occurrences to be
replaced using a
count
argument as in the Python version ofreplace
.
Split #
Split (from left) #
print('1,2,3'.split(','))print('1,2,3'.split(',',maxsplit=1))print('1,2,,3,'.split(','))print('1::2::3'.split('::'))print('1::2::3'.split('::',maxsplit=1))print('1::2::::3::'.split('::'))
['1', '2', '3']
['1', '2,3']
['1', '2', '', '3', '']
['1', '2', '3']
['1', '2::3']
['1', '2', '', '3', '']
importstrutilsecho"1,2,3".split(',')echo"1,2,3".split(',',maxsplit=1)echo"1,2,,3,".split(',')echo"1::2::3".split("::")echo"1::2::3".split("::",maxsplit=1)echo"1::2::::3::".split("::")
@["1", "2", "3"]
@["1", "2,3"]
@["1", "2", "", "3", ""]
@["1", "2", "3"]
@["1", "2::3"]
@["1", "2", "", "3", ""]
Split from right #
rsplit
behaves just like split
unless the maxsplit
argument is
given
print('1,2,3'.rsplit(','))print('1,2,3'.rsplit(',',maxsplit=1))print('1,2,,3,'.rsplit(','))print('1::2::3'.rsplit('::'))print('1::2::3'.rsplit('::',maxsplit=1))print('1::2::::3::'.rsplit('::'))
['1', '2', '3']
['1,2', '3']
['1', '2', '', '3', '']
['1', '2', '3']
['1::2', '3']
['1', '2', '', '3', '']
importstrutilsecho"1,2,3".rsplit(',')echo"1,2,3".rsplit(',',maxsplit=1)echo"1,2,,3,".rsplit(',')echo"1::2::3".rsplit("::")echo"1::2::3".rsplit("::",maxsplit=1)echo"1::2::::3::".rsplit("::")
@["1", "2", "3"]
@["1,2", "3"]
@["1", "2", "", "3", ""]
@["1", "2", "3"]
@["1::2", "3"]
@["1", "2", "", "", "3", ""]
Split Lines #
splits='ab c\n\nde fg\rkl\r\n'.splitlines()print(splits)print('ab c\n\nde fg\rkl\r\n'.splitlines(keepends=True))
['ab c', '', 'de fg', 'kl']
['ab c\n', '\n', 'de fg\r', 'kl\r\n']
importstrutilsvarsplits:seq[string]="ab c\n\nde fg\rkl\r\n".splitLines()echosplits
@["ab c", "", "de fg", "kl", ""]
Notes #
- The Nim version of
splitLines
does not have a second argument likekeepends
in the Python versionsplitlines
. - Also the Nim version creates separate splits for the
\r
and\n
. Note the last""
split created by Nim, but not by Python in the above example.
Convert #
See the encodings
module for equivalents of Python decode
andencode
functions.
Others #
There is no equivalent for the Python translate
function ,
in Nim as of writing this ( ).
References #
Internet Explorer 0-Day Discovered
In late April, two security companies (Qihoo360 and Kaspersky) independently discovered a zero-day for Internet Explorer (CVE-2018-8174), which was used in targeted attacks for espionage purposes. This marks two years since a zero-day has been found (CVE-2016-0189 being the latest one) in the browser that won’t die, despite efforts from Microsoft to move on to the more modern Edge.
The vulnerability exists in the VBScript engine and how it handles memory objects. It will also affect IE11, even though VBScript is no longer supported by using the compatibility tag for IE10.
The attack came via a Word document making use of OLE autolink objects to retrieve the exploit and shellcode from a remote server. However, it is important to note that it could very well have been executed by visiting a website instead.
Perhaps one of the reasons why it was not used as a drive-by download attack may be because Internet Explorer is no longer the default browser for most people, and therefore the exploitation would never occur. However, by tricking their victims to open an Office document, the attackers can force Internet Explorer to load, thanks in part to the URL moniker“feature.”
Using rtfdump.py, we see the call for an HTTP connection:
python rtfdump.py -s 320 -H CVE-2018-8174.rtf
000014C0: 70 B2 86 8C 53 30 05 43 00 38 30 01 18 68 00 74 p���S0.C.80..h.t 000014D0: 00 74 00 70 00 3A 00 2F 00 2F 00 61 00 75 00 74 .t.p.:././.a.u.t 000014E0: 00 6F 00 73 00 6F 00 75 00 6E 00 64 00 63 00 68 .o.s.o.u.n.d.c.h 000014F0: 00 65 00 63 00 6B 00 65 00 72 00 73 00 2E 00 63 .e.c.k.e.r.s...c 00001500: 00 6F 00 6D 00 2F 00 73 00 32 00 2F 00 73 00 65 .o.m./.s.2./.s.e 00001510: 00 61 00 72 00 63 00 68 00 2E 00 70 00 68 00 70 .a.r.c.h...p.h.p 00001520: 00 3F 00 77 00 68 00 6F 00 3D 00 37 00 00 00 00 .?.w.h.o.=.7....
This remote request will download a VBS script. A Proof of Concept adapted from the blog that was published by Kaspersky can be seen below:
The flaw abused by this vulnerability relates to a reference count that is checked at the beginning of the function but not after, despite the chance of it being incremented along the way. This allows an attacker to execute malicious shellcode and eventually load the malware binary of his choice.
We tested this Use After Free (UAF) vulnerability with the publicly available PoC running Internet Explorer 11 under Windows 10. The browser crashes once it loads the VBS code, but with Malwarebytes, the attack vector is mitigated:
Microsoft has released a patch for this vulnerability, and we strongly advise to apply it, as it is just a matter of time before other threat actors start leveraging this new opportunity in spam or exploit kit campaigns.
We will update this blog if we obtain more information about this vulnerability being used widely, and in particular, if a full working exploit is available.
Strftime's alpha-sorted man page vs. well-meaning people
I have another tale of humans being humans, and getting into trouble when using computer systems. I think I even have a plausible explanation for how this one happens, and why people plant a certain time-bomb into their code without realizing it. This is an expansion of something I mentioned briefly last year.
Okay, so let's set the stage. You're a new coder, and you find yourself tasked with taking a Unix time_t type value and turning it into some kind of human-readable format. We'll assume you're on something C or C++-ish, at which point you will eventually learn about strftime(). You might find this directly, or you might crib some invocation of it from elsewhere in the code base and just adjust it for your own needs. Maybe what you found just does the time but you need something more.
You've been told that the output should be the year, month, and day, and then hour, minute, second, and the local time zone. As an example, it might look like "2018-04-20 17:04:04 PDT". This brings you to the man page, and you go looking for "year" in there. The first thing you find is something about "century number (year/100) as a 2-digit integer". You don't want that, so you keep looking down the list.
The very next thing you land on while scrolling through the manual is described like this:
The ISO 8601 week-based year (see NOTES) with century as a decimal number. The 4-digit year corresponding to the ISO week number (see %V).
It goes on like this, but you're suddenly very happy. ISO 8601 sounds right, doesn't it? Isn't that what all of the nerds say you should do instead of a MM/DD or DD/MM type of thing? Cool! Also, it's four digits, so no Y2K here!
You create your format string. It winds up looking like this:
%G-%m-%d %H:%M:%S %Z
You code it up and run your program. It spits out exactly what was shown above, albeit a few minutes later since time has moved on: "2018-04-20 17:09:16 PDT". Nice! Looks legit, ship it?
It's April. This code will fail within a year. In particular, it will fail at midnight local time (here on the west coast of the US/Canada) one day before the new year. In one second, it will jump from displaying 23:59:59 on Sunday, December 30th, 2018 to displaying 00:00:00 on Monday, December 31st, 2019. Yep, it'll jump a whole year all at once.
It'll look like this:
1546243197 = 2018-12-30 23:59:57 PST 1546243198 = 2018-12-30 23:59:58 PST 1546243199 = 2018-12-30 23:59:59 PST 1546243200 = 2019-12-31 00:00:00 PST 1546243201 = 2019-12-31 00:00:01 PST
24 hours after that, it will go from displaying 23:59:59 on Monday, December 31st, 2019 ... to displaying 00:00:00 on Tuesday, January 1st, 2019. It'll (appear to) jump BACK almost a whole year all at once.
1546329597 = 2019-12-31 23:59:57 PST 1546329598 = 2019-12-31 23:59:58 PST 1546329599 = 2019-12-31 23:59:59 PST 1546329600 = 2019-01-01 00:00:00 PST 1546329601 = 2019-01-01 00:00:01 PST
Why? That's "easy": theISO week begins on Monday, and that week "belongs" to 2019. Why is that? Well, it has to belong to one year or the other, and so you ask yourself "which year has more of the days". Only Monday the 31st is on 2018 in non-ISO-years, so the other six days (January 1-6) are 2019, and so it "wins".
Seriously, look how the week gets split up this time around.
$ cal 12 2018; cal 1 2019 December 2018 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 January 2019 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
In other years, the split is a little different, and you end up going from December 31st 23:59:59 to January 1st 00:00:00.. of the same year! This then persists for a couple of days, and then it goes back to "just working" again.
What happened? Someone read the strftime man page, and %G alpha-sorts before %Y, so they found it first. Then they didn't "get" the whole warning there, and it looked good enough, so they went with it. The rest pretty much follows from that.
The immediate fix is to change the %G to a %Y, naturally.
A better fix is to get people away from using format strings altogether. Do you really want all of your programmers learning this lesson? Or, do you want to have one person get it right, provide a handful of functions to render the approved formats for either "now" or a supplied time, and then ban all other attempts to use the strings directly, and then go on with life? I know which one I'd rather have.
I should note that folks who use other languages are not automatically immune to this. PHP in particular has a bunch of different ways to format strings, and the ISO year is one of those options. It's possible to make the same mistake, although with somewhat different letters involved.
There are a few people who actually need ISO years and weeks in their date strings, and odds are pretty good that they know who they are. Nobody else is going to want this, and seeing it in code that's intended for random ordinary people to use is a good sign that something may be wrong.
So, the next time your favorite site or app (or built-in tool, hello Apple!) breaks in the last week of one year or the first week of the next, and then "mysteriously fixes itself" three or four days later, it might just be this.
The Wizard of Q[anon] by Walter Kirn
In 2006, when the internet was younger and seemed to hold untapped artistic possibilities, I was asked to write a serial novel for Slate. The subject of the “book” was up to me, so I chose themes that seemed appropriate to the new medium: high-tech surveillance, cultural fragmentation, selfhood eroded by scrutiny. I imagined people reading my dark tale surreptitiously at their office computers and feeling almost as hunted as the characters, who were a mix of anarchists and federal agents, omniscient spies and hapless nobodies. I titled the novel The Unbinding and filled it with experimental devices—specifically, scores of hyperlinks—meant to hasten a Great Leap Forward for fiction. One of the hyperlinks took you to a video of a metal band from Scandinavia playing a sped-up, scary-sounding cover of Neil Diamond’s “Solitary Man.” How I thought it might help the story I no longer recall. I may have stuck it in just because I could.
The Unbinding was, needless to say, a flop. Few people ever found it on the web, and fewer still bought the printed version that followed (in which the hyperlinks appeared in bold but were functionally moot). Not surprising: it was borderline incoherent. When I started the book, I had a notion that I would use current events to shape the plot. It was a clever idea but not a good one. Fashioning a tale without an ending, a tale that swerved as the headlines changed yet retained its inner logic, was a stunt I simply couldn’t manage. I wrote it in installments, week by week, laying down a railroad track to nowhere. I should have called the project “The Unhinging,” since writing it nearly sent me around the bend.
To console myself for my failure I concluded that the internet and the novel were natural enemies. “Choose your own adventure” stories were not the future of literature. The author should be a dictator, a tyrant who treated the reader as his willing slave, not as a cocreator. And high-tech flourishes should be avoided. Novels weren’t meant to link to Neil Diamond songs or, say, refer to real plane crashes on the day they happen. Novels were closed structures, their boundaries fixed, not data-driven, dynamic feedback loops. Until quite recently, these were my beliefs, and no new works emerged to challenge my thinking.
Then, late last year, while knocking around on the internet one night, I came across a long series of posts originally published on 4chan, an anonymous message board. They described a sinister global power struggle only dimly visible to ordinary citizens. On one side of the fight, the posts explained, was a depraved elite, bound by unholy oaths and rituals, secretly sowing chaos and strife to create a pretext for their rule. On the other side was the public, we the people, brave and decent but easily deceived, not least because the news was largely scripted by the power brokers and their collaborators in the press. And yet there was hope, I read, because the shadow directorate had blundered. Aligned during the election with Hillary Clinton and unable to believe that she could lose, least of all to an outsider, it had underestimated Donald Trump—as well as the patriotism of the US military, which had recruited him for a last-ditch battle against the psychopathic deep-state spooks. The writer of the 4chan posts, who signed these missives “Q,” invited readers to join this battle. He—she? it?—promised to pass on orders from a commander and intelligence gathered by a network of spies.
I was hooked.
Known to its fan base as QAnon, the tale first appeared last year, around Halloween. Q’s literary brilliance wasn’t obvious at first. His obsessions were unoriginal, his style conventional, even dull. He suggested that Washington was being purged of globalist evildoers, starting with Clinton, who was awaiting arrest, supposedly, but allowed to roam free for reasons that weren’t clear. Soon a whole roster of villains had emerged, from John McCain to John Podesta to former president Obama, all of whom were set to be destroyed by something called the Storm, an allusion to a remark by President Trump last fall about “the calm before the storm.” Clinton’s friend and supporter Lynn Forrester de Rothschild, a member by marriage of the banking family abhorred by anti-Semites everywhere, came in for special abuse from Q and Co.—which may have contributed to her decision to delete her Twitter app. Along with George Soros, numerous other bigwigs, the FBI, the CIA, and Twitter CEO Jack Dorsey (by whom the readers of Q feel persecuted), these figures composed a group called the Cabal. The goal of the Cabal was dominion over all the earth. Its initiates tended to be pedophiles (or pedophilia apologists), the better to keep them blackmailed and in line, and its esoteric symbols were everywhere; the mainstream media served as its propaganda arm. Oh, and don’t forget the pope.
As I read further, the tradition in which Q was working became clearer. Q’s plot of plots is a retread, for the most part, of Cold War–era John Birch Society notions found in books such as None Dare Call It Conspiracy. These Bircher ideas were borrowings, in turn, from the works of a Georgetown University history professor by the name of Carroll Quigley. Said to be an important influence on Bill Clinton, Quigley was a legitimate scholar of twentieth-century Anglo-American politics. His 1966 book Tragedy and Hope, which concerned the power held by certain elites over social and military planning in the West, is not itself a paranoid creation, but parts of it have been twisted and reconfigured to support wild theories of all kinds. Does Q stand for Quigley? It’s possible, though there are other possibilities (such as the Department of Energy’s “Q” security clearance). The literature of right-wing political fear has a canon and a pantheon, and Q, whoever he is, seems deeply versed in it.
While introducing his cast of fiends, Q also assembled a basic story line. Justice was finally coming for the Cabal, whose evil deeds were “mind blowing,” Q wrote, and could never be “fully exposed” lest they touch off riots and revolts. But just in case this promised “Great Awakening” caused panic in the streets, the National Guard and the Marine Corps were ready to step in. So were panels of military judges, in whose courts the treasonous cabalists would be tried and convicted, then sent to Guantánamo. In the manner of doomsayers since time began, Q hinted that Judgment Day was imminent and seemed unabashed when it kept on not arriving. Q knew full well that making one’s followers wait for a definitive, cathartic outcome is a cult leader’s best trick—for the same reason that it’s a novelist’s best trick. Suspense is an irritation that’s also a pleasure, so there’s a sensual payoff from these delays. And the more time a devotee invests in pursuing closure and satisfaction, the deeper her need to trust the person in charge. It’s why Trump may be in no hurry to build his wall, or to finish it if he starts. It’s why he announced a military parade that won’t take place until next fall.
As the posts piled up and Q’s plot thickened, his writing style changed. It went from discursive to interrogative, from concise and direct to gnomic and suggestive. This was the breakthrough, the hook, the innovation, and what convinced me Q was a master, not just a prankster or a kook. He’d discovered a principle of online storytelling that had eluded me all those years ago but now seemed obvious: The audience for internet narratives doesn’t want to read, it wants to write. It doesn’t want answers provided, it wants to search for them. It doesn’t want to sit and be amused, it wants to be sent on a mission. It wants to do.
From November on, as his following on 4chan, Reddit, Twitter, and other platforms grew, Q turned his readers into spies and soldiers by issuing coded orders and predictions that required great effort to interpret and tended to remain ambiguous even after lengthy contemplation. The messages often consisted of stacked one-liners that looked like imagist poems. They radiated mystery and portent. Take this example from March 3:
Who controls the narrative?
WHO wrote the singular censorship algorithm?
WHO deployed the algorithm?
WHO instructed them to deploy the algorithm?
SAME embed across multiple platforms.
Why?
Why is the timing relevant?
Where is @Snowden?
Why did ES leave G?
To initiates, this set of clues (Q’s audience calls these “crumbs” and strives to “bake” them into “bread,” meaning plain English) alludes to an elaborate range of incidents related to Trump’s war on the Cabal and to the Cabal’s war—doomed to fail—on us, the innocents. “ES,” for instance, is Eric Schmidt, the former executive chairman of Alphabet, Google’s parent company, whose resignation had been linked in previous posts to covert dealings with North Korea, in Q mythology a CIA puppet state and a center of trafficking in drugs and sex slaves. The insidious censorship algorithm is the work of Edward Snowden, who isn’t a whistle-blower but a double or triple agent of murky allegiances who works with Twitter’s Dorsey in some obscure capacity to keep the citizenry blind and muzzled.
Preposterous, huh? Well, the Q people don’t think so. Indeed, they feel we’ll soon come over to their side, once we understand the true relationship between Q’s crumbs and the subsequent news events that the crumbs predicted. The North Korean peace talks, for example, which some students of Q saw coming last winter. Or the scandalous revelations about Facebook’s illicit peddling of users’ data. “Do you believe in coincidences?” asks Q repeatedly, and the answer he obviously wants is no. That’s why his minions labor to make connections between such disparate phenomena as the flight paths of jumbo jets and the alleged escape plans of A-list fugitives. “Expand your thinking,” Q exhorts his legions, particularly when they falter in their cryptography or lag in their online detective work. He’s the author as case officer, tasking slow-witted readers with enigmas whose solutions he already knows but insists that they discover on their own.
And his posts aren’t all nonsense. Some are quite uncanny in the way they anticipate the headlines. On March 9, he told his troops to watch for “liquidity events” in the stock charts of social media companies. Days later, Facebook fell into disgrace and suffered a sizable market sell-off. Then there are the intriguing correlations between the posts and the president’s Twitter outbursts, which Q would have us think are synchronized with split-second precision. The proofs he offers involve comparing time stamps, and mathematically minded Qbots swear by them. That they’re willing to fuss with such puzzles is a testament to the compulsive power of Q’s methods. By leaving more blanks in his stories than he fills in, he activates the portion of the mind that sees faces in clouds and hears melodies in white noise.
Could Q have actual foreknowledge? Was he somehow the oracle he purported to be? Having followed the posts for months now, I wish I could summarily dismiss them, but so outrageous is our current reality, so reliably unpredictable and odd, that it does not seem impossible to me that there might exist an internet seer stationed in the White House whose job is to brief lowly geeks on global intrigues. My friend Matthew, who saw combat in Afghanistan and has reported on intelligence issues, believes that Q may be the result of psyops conceived to maintain morale among Trump’s base. The trick, he says, is to fashion a mental filter that will make Trump’s losses look like victories, his missteps like chess moves, his caprices like plans. After all, if most news is fake, as Trump insists, the real news must be hidden out of sight. Q claims to offer glimpses of it, along with warnings about what would happen if we beheld it all at once. To wake in an instant to the Luciferian horrors of the Cabal’s perverted machinations would be like rushing forth from Plato’s cave—blinding, debilitating, maybe deadly. Instead, Q leads us gently toward the light, a patient guide, like Virgil was to Dante.
One night this spring, in northwest Arkansas, Matthew and I stayed up past midnight interpreting several recent posts from Q that trembled on the verge of clarity, seeming to offer highly privileged insights into a crisis rumored to be forthcoming. I sat on the couch. He paced. We thought out loud, competing to crack the message and setting different values for different variables. We argued our cases as the night slid by; we raved away in an ecstasy of guesswork. Q was being good to us. Q was delivering everything we craved.
Q is part fabulist, part fortune-teller, holding up a computer-screen-shaped mirror to our golden age of fraudulence. He composes in inklings, hunches, and wild guesses, aware that our hunger for order grows more acute the longer it goes unsatisfied. Q calls the vista he’s gradually revealing the map, and he knows how badly his people crave it, which is why he doesn’t disclose in one fell swoop Trump’s strategy for national salvation. A hope fulfilled is also a hope exhausted. Tension and foreboding, on the other hand, are thrills that keep on thrilling, for fear can never be fully put to rest. Even if his followers’ dreams come true and the Clintons, Podestas, Schmidts, and Dorseys are hustled off in chains to distant gulags, and even if Kim Jong-un is released from the CIA contract that requires him to play a nuclear madman to keep the world off balance so America’s spymasters can rule it, one can never be sure the Cabal won’t rise again. And it will, of course, since that’s what archfiends do: rise from the dead.
The novel is the same way. It dies and dies so it can live and live. The Q tale may be loathsome and deeply wicked, a magnet for bigots and ignoramuses whose ugly dreams it caters to and ratifies, but as a feat of New Age storytelling I find it curiously encouraging. The imagination lives. A talented bard can still grab and keep an audience. Now for a better story, with higher themes. Now for the bracing epic of recovery that the dark wizards have shown us how to write.
You are currently viewing this article as a guest. If you are a subscriber, please sign in.
If you aren't, please subscribe below and get access to the entire Harper's archive for only $45.99/year.
Or purchase this issue on your iOS or Android devices for $6.99.
No More Conference T-Shirts, Please
In an unexpected fit of spring-cleaning, I went through my wardrobe getting rid of all my old conference t-shirts.
Hundreds of 'em! They're all covered in logos for companies which long-ago went bust, or for events which are no-longer running, and most have... errr... "shrunk" in the wash.
I know I'm a grumpy old sod. But I've a couple of serious points to make. T-shirts are wasteful, exclusionary, and a bit of a crap gift.
I've just recycled a whole sack of conference t-shirts.
BarCamps, GovCamps, Cons, trade shows, festivals. Is it time to retire the T as schwag?
I mean, let's not go for branded fidget spinners(!) but is there something more useful which can be given away?♻👕👍
— ꧁Terence Eden꧂ ⏻ (@edent) May 11, 2018
Firstly, if you have spare cash at your conference - SPEND IT ON THE CONFERENCE! Make the tickets cheaper - or give them away to people who can't afford to come. Get better catering than stale sandwiches or soggy pizza. Reinvest it into the community. Pay your speakers.
Secondly, sponsors - I promise you that no one is buying your paradigm-shifting product because they wear your logo under their armpit.
Never understood the prevalence of giving away relatively ugly ill-fitting branded T-shirts at conferences (and I do like T-shirts on general).
— Joshua Mouldey (@desire_line) May 12, 2018
And they're usually just plain ugly...
— Sally Le Page (@sallylepage) May 11, 2018
I've blogged before about how t-shirts can be exclusionary. I'm not alone in thinking this.
Often the women's sizes are also only for tiny women.
— Jenny List (@Jenny_Alto) May 11, 2018
One of the reasons we didn't do tshirts for @DevOpsDaysLDN is because I've never been to a conference where any of the t-shirts would fit me. Even the ones we did just for us organizers didn't fit me.
— bob (@rjw1) May 11, 2018
There's a side argument. When you attend the 2018 conference wearing the t-shirt from the 2015 conference, you're sending a message: "I belong and you're just a newbie."
If you've ever been to a concert and seen a dude wearing a t-shirt from the band's original 1974 tour he's saying that he is a real fan - not like you Johnny-come-latelys.
Ewww.
Do you really want an unending supply of logo'd Ts? What can you possibly do with them all?
Youtube hoodies and jackets are the best. Old conference shirts are good for hair dying though
— Inés (@InesLauraDawson) May 11, 2018
I tend to use them for painting, gardening, mechanical work etc
— Lee Porte (@leeporte) May 11, 2018
Yeah, fair enough. But there's a limit to the number of times I can colour my hair while doing the gardening.
Alternatives
OK, so you want to give away something. You need to bribe your participants into loving you. What can you distribute instead?
Notebooks. You can never have too many notebooks. Not pens, though, because I have a million branded pens and they are all always shite.
— Suw (@Suw) May 12, 2018
Socks. Most popular schwag Dr Solomon’s ever did. I still get asked about them 20 years later.
— PJ Evans (@MrPJEvans) May 11, 2018
Keepcup, reusable straw, those bundles of reusable travel cutlery
— Haywards PicallEllie (@Ellayanor) May 11, 2018
Reusable insulated coffee cups with lids pic.twitter.com/6lkcFoDAkq
— Fae (@Faewik) May 11, 2018
Towels was a popular suggestion on a thread I read a while back.
— Jude Gibbons (@judeGibbons) May 11, 2018
Of course, you don't need to give crap away to attendees.
We refused to do swag at #ukgovcamp18 and gave a £5 to @Shelter for each visitor to the stand. Raised just over £500
— Chris Farthing (@A_C_Chris) May 11, 2018
A Pi to a school? Costs about 4-6 printed t-shirts I think.
— Ian Oates (@IanOates) May 12, 2018
Or, alternatively, turn those old shirts into a blanket.
WordCamp nap blanket for sale https://t.co/fT2zU0AVvf#genesiswp#WordPress#dradcast
— the one who makes the quilts (@andrea_r) November 1, 2016
Check Your Privilege
I'm lucky. I can afford to buy my own clothes. And my body-shape is pretty well available at most retailers. I strut with the confidence of a mediocre white man and don't need to prove myself in the workplace by conspicuously displaying symbols of my in-group membership.
Am I wrong? Do you have a source of secret survey data showing how much conference attendees love free branded t-shirts?
Shove your thoughts in the comment hole below.
Scientist Defined the Greenhouse Effect but Didn’t Get Credit Because Sexism
The morning of August 23, 1856, saw hundreds of men of science, inventors and curious persons gathered in Albany, New York, for the Eighth Annual Meeting of the American Association for the Advancement of Science, the largest attended to date. The annual meetings of the AAAS brought together scientists from around the United States to share groundbreaking new discoveries, discuss advancements in their fields and explore new areas of investigation. Yet this particular meeting failed to deliver any papers of quality—with one notable exception.
That exception was a paper entitled “Circumstances affecting the heat of the sun’s rays,” by Eunice Foote. In two brisk pages, Foote’s paper anticipated the revolution in climate science by experimentally demonstrating the effects of the sun on certain gases and theorizing how those gases would interact with Earth’s atmosphere for the first time. In a column of the September 1856 issue of Scientific American titled “Scientific Ladies,” Foote is praised for supporting her opinions with “practical experiments.” The writers noted: “this we are happy to say has been done by a lady.”
Foote’s paper demonstrated the interactions of the sun’s rays on different gases through a series of experiments using an air pump, four thermometers, and two glass cylinders. First, Foote placed two thermometers in each cylinder and, using the air pump, removed the air from one cylinder and condensed it in the other. Allowing both cylinders to reach the same temperature, she then placed the cylinders with their thermometers in the sun to measure temperature variance once heated and under various states of moisture. She repeated this process with hydrogen, common air and CO2, all heated after being exposed to the sun.
Looking back on Earth’s history, Foote explains that “an atmosphere of that gas would give to our earth a high temperature ... at one period of its history the air had mixed with it a larger proportion than at present, an increased temperature from its own action as well as from increased weight must have necessarily resulted.” Of the gases tested, she concluded that carbonic acid trapped the most heat, having a final temperature of 125 °F. Foote was years ahead of her time. What she described and theorized was the gradual warming of the Earth’s atmosphere—what today we call the greenhouse effect.
Three years later, the well-known Irish physicist John Tyndall published similar results demonstrating the greenhouse effects of certain gases, including carbonic acid. Controversial though well recognized at the time, Tyndall theorized that Northern Europe was once covered in ice but gradually melted over time due to atmospheric changes. This laid the groundwork for how atmospheric variations over time in addition carbon dioxide emissions could have profound effects on global climate. Presently, Tyndall’s work is widely accepted as the foundation of modern climate science, while Foote’s remains in obscurity.
Why?
It goes without saying that the 19th century was not an easy era to be a woman and scientifically curious. With limited opportunities in higher education for women and the gate-keeping of scientific institutions like AAAS, which was all-male until 1850, science was largely a male-dominated field. Even the Smithsonian Institution, one of America’s premier scientific research institutions, was built on the clause“for the increase and diffusion of knowledge among men” (emphasis added). Born in 1819, this is the landscape that Foote found herself navigating.
Although nothing is known about Foote’s early education, it is clear from her experiments that she must have received some form of higher education in science. Her appearance, along with her husband Elisha Foote, at the 1856 AAAS meeting is the first recorded account of her activity in science.
Unlike many other scientific societies, the AAAS did allow amateurs and women to become members. Astronomer Maria Mitchell became the first elected female member in 1850, and later Almira Phelps and Foote, though without election from its standing members. But despite the society’s seemingly open door policy, there were hierarchies within the society itself. Historian Margaret Rossiter, author of the comprehensive three volume series Women Scientists in America, notes that the AAAS created distinctions between male and female members by reserving the title of “professional” or “fellow” almost exclusively for men, whereas women were regarded as mere members.
These gender disparities were highlighted during the August 23 meeting, where Foote was not permitted to read her own paper. Instead, her work was presented by Professor Joseph Henry of the Smithsonian Institution. (Foote's husband, by contrast, was able to read his paper, also on gases.)
At the meeting, Henry appended Foote’s paper with his own added preface: “Science was of no country and of no sex. The sphere of woman embraces not only the beautiful and the useful, but the true.” The introduction, intended to praise Foote, more than anything highlights her difference as a woman in a sea of men, indicating that her presence among them was indeed unusual and needed justification. Even Scientific American’s praise of Foote’s paper was included in a column two pages after the AAAS meeting report. Though both Henry and Scientific American seemed to see Foote as an equal in scientific endeavors, she was still kept separate from the fold.
Adding insult to injury, Foote’s paper was left out of the society’s annual Proceedings, a published record of the papers presented at the annual meetings. In The Establishment of Science in America, historian Sally Gregory Kohlstedt gives some indication of why this might be.
In the 1850s, Alexander Dallas Bache, a leading force for the AAAS, promoted open membership. But Bache also enforced strict and critical reviews of all papers published in the Proceedings in order to cultivate a specific image and voice for American science; even if a local committee of the association approved papers for publication, the standing committee of the AAAS, on which Bache served, could reject them. Just by glancing at the member list and published papers, it is clear that image and that voice were predominantly male.
The only copy of Foote’s paper published in its entirety is found in The American Journal of Science and Arts, and without this outside publication, only Henry’s read version would remain. Compared to other papers published from this meeting, Foote’s—a demonstration of rigorous experimentation and sound reasoning—should arguably have been included in the 1856 collection.
I spoke with Raymond Sorenson, an independent researcher and co-editor for Oil-Industry History, who was the first to publish a paper on Foote in 2011. A collector of scientific manuals, Sorenson found Foote’s paper as read by Joseph Henry in David A. Wells’s Annual of Scientific Discovery. (Wells is the only known source to include Joseph Henry’s impromptu introduction, most likely retrieved through stenographer records of meetings.)
Sorenson says that Foote’s biographical information is difficult to find and piece together, but he has found her correspondence archived at the Library of Congress and has traced some of her familial connections. The more Sorenson researched Foote, the more he realized he has a book project on his hands. Yet before writing tha book, Sorenson decided to go ahead and publish his 2011 article because, as he says, “Eunice Foote deserves credit for being the first to recognize that certain atmospheric gases, such as carbon dioxide would absorb solar radiation and generate heat…[three] years before Tyndall’s research that is conventionally credited with this discovery.”
It now appears that Foote was the first to demonstrate the greenhouse effects of certain gases and also the first to theorize about their interaction with the Earth’s atmosphere over an extended period of time. Her explanation of the greenhouse effect—which would help scientists understand the underlying mechanisms behind global warming in the 20th century—predated Tyndall’s by three years.
For a woman like Eunice Foote—who was also active in the women’s rights movement—it could not have been easy to be relegated to the audience of her own discovery. The Road to Seneca Falls by Judith Wellman shows that Foote signed the 1848 Seneca Falls Convention Declaration of Sentiments, and was appointed alongside Elizabeth Cady Stanton herself to prepare the Convention proceedings for later publication. As with many women scientists forgotten by history, Foote’s story highlights the more subtle forms of discrimination that have kept women on the sidelines of science.
Foote’s work with greenhouse gases does not supersede that of Tyndall, whose body of work overall has been more integral to current climate science. Yet, by including Foote’s 1856 work in the history of climate science, we are reminded that the effort to understand the Earth’s atmosphere and human interactions with it has been an ongoing endeavor over a century in the making. And one of the first steps toward that understanding, it turns out, was taken by a lady.
TSA Rule for Lightsabers
'The Expanse' Canceled at Syfy
The current third season of the drama starring Steven Strait will be its last.
The current third season of Syfy drama The Expanse will be its last.
The NBCUniversal-owned cable network has made the decision to end the space drama with season three. The show's June 27 season finale will now serve as its series finale.
Starring Steven Strait and based on James S.A. Corey's best-selling book series of the same name, in the series written by Daniel Abraham and Ty Franck, Syfy only had the rights to the first-run linear episodes in the U.S. That limited the upside for the cable network, making live and linear viewership imperative.
Opening to promising reviews and a strong collection of loyal viewers, its first season averaged 581,000 viewers in the advertiser-coveted adults 18-49 demographic, and 1.4 million total viewers with three days of DVR. Season two, which returned more than a year later with a significant marketing push and a solid lead-in, was down 24 percent among total viewers and averaged 457,000 total viewers. That compares more to similar returns for Syfy's inexpensive co-productions like Dark Matter and Killjoys, than to the cabler's original scripted series like The Magicians and Happy.
Its third season, which returned in April, tumbled another 5 percent among total viewers and 12 percent in the demo from season two.
"The Expanse transported us across the solar system for three brilliant seasons of television. Everyone at Syfy is a massive fan of the series, and this was an incredibly difficult decision," said Chris McCumber, president of entertainment networks at NBCU Cable Entertainment. "We want to sincerely thank The Expanse’s amazing cast, crew and all the dedicated creatives who helped bring James S.A. Corey’s story to life. And to the series’ loyal fans, we thank you most of all.”
The decision to bring The Expanse to its end comes as Syfy has a packed scripted roster that also includes the upcoming George R.R. Martin drama Nightflyers, The Purge, Deadly Class, Krypton, The Magicians, anthology Channel Zero, Van Helsing, Wynonna Earp and Killjoys, with the latter set to wrap in 2019. The Expanse will be Syfy's second series to conclude this year, joining 12 Monkeys.
Starring Strait, Shohreh Aghdashloo and Dominique Tipper, The Expanse is set in a future where humanity has colonized the solar system. Mark Fergus and Hawk Ostby (Children of Men) served as showrunners and exec produced the Alcon TV Group drama alongside Naren Shankar.
Google's Plan to Make Tech Less Addictive
We know that our smartphones are making us unhappy. At its annual developer’s conference this week, Google revealed that 70% of its users actually want help balancing their digital lives. What’s not so clear is what the smartphone manufacturers of the world should do about it. After all, it’s in their business interests to make their phones as engaging–or addictive–as possible.
Yet at I/O, Google introduced a clever and aggressive response to its own habit-forming products. It’s a broad initiative called Digital Wellbeing that CEO Sundar Pichai says will ultimately affect every Google product. “It’s clear that technology can be a powerful force, but it’s equally clear that we can’t just be wide-eyed about [it],” said Pichai on stage at Google’s I/O conference. “We feel a deep sense of responsibility to get this right.”
For now, Google’s upcoming Android P operating system is introducing three great features to help us break–or at least, better manage–our screen addictions.
Shush
With a feature called Shush, Android P will automatically silence your calls and notifications when you flip your phone over, screen side down. That means you don’t have to push any buttons or dig through deep settings menus. To put the phone down you just . . . put the phone down.
What’s particularly brilliant about Shush is that its gesture is modeled directly after a behavior so many of us already do, as we place the phone face-down on the table during a meal we’d like to enjoy with friends or family. Now, that gesture will become more powerful, with software supporting your desired behavior. (Incidentally, design nerds may notice that Motorola developed this same idea a few years back–but it will definitely be more widely adopted as part of Android P.)
Wind Down
“We heard from people that they checked their phone right before bed, and before they knew it, an hour or two went by,” say Sameer Samat, VP of product management at Google. Google and Apple have both already introduced warm, color shifting modes at night so that your phone’s blue light doesn’t disrupt your natural sleep cycle. But with Digital Wellbeing, Google is doing more with a feature called Wind Down mode that turns your phone gray.
You set Wind Down when you’d like to go to bed, and Android P will shift into a gray-scale palette that takes some of that slot machine-style delight out of your phone. It essentially turns your device into a Mac from 1985.
Dashboard Data View
Most studies show that we check our phones more than 100 times a day. But that’s the sort of generalized stat that’s easy to brush off. Android P will have a personalized data visualization of your actual phone usage, from how many times you checked it in a day, to how many push notifications you received. It will even display what you did inside various apps–and on this front, third- party developers will be able to specify trackable metrics inside their software.
Exactly how specific this tracking will get is still a bit unclear–I can imagine something like “John spent six hours watching anime cartoons, and 15 minutes watching geometry proofs”–but Google wants to push what it calls “meaningful engagement,” not just garbage time on your phone. Hopefully developers feel the same way. Within this data view, you’ll also be able to set something akin to a parental control on yourself, asking apps like YouTube to notify you once you’ve watched a daily limit of videos.
Of course, all these new features still seem to offer users the option to override their own self-regulatory decisions, and re-enable their own phone addiction–much like throwing out a pack of cigarettes doesn’t prevent anyone from stopping off at the gas station to grab another. Now that Digital Wellbeing has launched, hopefully these are but the first experiments Google is trying to make its phones a healthier part of our lives. We’re looking at you next, Apple.
Well-capitalized startup seeks talented engineers
You should have a BS, MS, or PhD in Computer Science or the equivalent. Top-notch communication skills are essential.
Familiarity with web servers and HTML would be helpful but is not necessary.
Expect talented, motivated, intense, and interesting co-workers.
Must be willing to relocate to the San Francisco area (we will help cover moving costs).
Your compensation will include meaningful equity ownership.
Send resume and cover letter to Ryan Petersen:
E-mail: Ryan@flexport.com
US mail: Flexport, Inc. 760 Market St, 8th Floor, San Francisco CA 94102
We are an equal opportunity employer.
------------------------------------------- "It's easier to invent the future than to predict it." -- Alan Kay -------------------------------------------
Yubico sent marketing email to address submitted in bug reporting
A while back, Yubico had a little security issue that forced it to replace any number of Yubikey 4s, including mine. In order to do this, they required people to give them an email address so they could send you some necessary information; following my usual practice I gave them a tagged, individualized address. Today I received email to that address, received from the server of a domain called 'mktomail.com', that started out like this:
Subject: Passwordless authentication is here
Yubico scales across enterprise
Passwords are out. You're in!
The passswordless evolution of the FIDO U2F standard has arrived with FIDO2. [... marketing materials removed with prejudice ...]
You are receiving this email because you made a Yubico purchase or contacted Yubico.
I'm sorry, that's not how this works. In the normal course of events, people do not give you email addresses to do with as you will; people give you email addresses for specific purposes. In this case, I gave Yubico an email address to get a defective product fixed, but one might report a bug, contact product support, or perform other limited interactions with the company. These specific and limited purposes do not include 'receive unsolicited commercial marketing emails'.
Of course, the marketing department does not want to hear this. The marketing department wants to uise every plausible address it can get its hands on. People these days vaguely get that you usually cannot buy addresses from other people without getting badly burned, but they keep thinking that other addresses are fair game, regardless of the purpose for which they were originally handed to the company.
Some of the time, the company supports the marketing department, as it did at Yubico, and these addresses get used outside of the purpose they were given to the company. At that point the company betrays the trust of the people who handed over their email addresses in good faith and pisses off some number of people who have interacted with the company in the past, some of which have actually bought their products. The results are predictable, as is the resulting form-letter evasion.
(When enough companies do this sort of thing for long enough, you get things like the EU's GDPR, which will likely make this conduct illegal. Sadly it is probably not illegal under Canada's anti-spam legislation, and anyway I expect Yubico to ignore the GDPR issues until they or someone else visible gets slapped with a nice fine for this sort of thing.)
Sadly I have no idea what is a viable alternative to Yubikeys, but at least we're not likely to buy any more any time soon.
[deleted]
[deleted]
[deleted]
[deleted]
[removed]
[removed]
[deleted]
[removed]
[deleted]
[deleted]
[deleted]
[deleted]
[deleted]