Company profile - Canadian Company Capabilities
Third-Party Information Liability Disclaimer
Some of the information on this Web page has been provided by external sources. The Government of Canada is not responsible for the accuracy, reliability or currency of the information supplied by external sources. Users wishing to rely upon this information should consult directly with the source of the information. Content provided by external sources is not subject to official languages, privacy and accessibility requirements.
Econotech Services Ltd.
Mailing Address:
852 Derwent WayDELTA, British Columbia
V3M 5R1
Location Address:
852 Derwent WayDELTA, British Columbia
V3M 5R1
Tel.:<PHONE_NUMBER>
Tel.:<PHONE_NUMBER>
Fax:<PHONE_NUMBER>
Logo
Company Profile
Supporting the pulp and paper industry since 1972, Econotech helps with your toughest problems: from specialized chemical analysis of pulp (woods & non-woods), pulping liquors, and other process chemicals (smelt, ash, condensates, lime), to physical and optical testing of pulp or paper, species analysis, contamination identification (scale and plastics), and confidential pulping and bleaching studies.
Full profile
Full profile
Contact information
Company description
541620 - Environmental Consulting Services
541710 - Research and Development in the Physical, Engineering and Life Sciences
Product / Service / Licensing
foreign, exotic and non-wood; weighted average fiber length
(WAFL); fiber coarseness; sclereids per o.d. gram of pulp; fiber
curl factor and kink count; cooking uniformity; cell wall
thickness and fiber diameter in wood or pulp; deinked pulp-ink
particle count and area or sticky count and area; contaminant
identification; paper defects investigation.
Wood and Chip Testing: moisture content; length and thickness
classification; bulk and basic density; species breakdown; wood
brightness; percent bark and rot.
Air Sampling and Testing: total particulate; asbestos in bulk
samples, fiber counts, on-site sampling.
latency removal mixer; flat screening; Pulmac shive analysis;
Bauer McNett fiber classification; Optest Fiber Quality
Analyzer-WAFL, coarseness, kink and curl indices; fiber length
index (DeMontigny); freeness measurement; handsheet preparation
(white water recirculation available).
Physical Testing: burst, tear, tensile, caliper, bulk, density,
fracture toughness, fold, internal bond, porosity (Sheffield or
Gurley), smoothness (Sheffield or Gurley), stiffness (Taber or
Gurley), softness (Gurley), coefficient of static friction,
concora, flat crush, ring crush, K & N ink absorption, water
absorption, Hercules size test, water retention value, water
vapor transmission rate, zero span and short span tensile,
stretch, TEA and MOE, Brecht Imset tear, Parker print surf,
Dennison wax pick, wet tensile testing, elongation, Cobb test.
Optical Testing: brightness and brightness reversion, opacity,
Hunter and CIE color coordinates, light scattering and absorption
coefficients, luminance factor, fluorescence, whiteness or
yellowness, tristimulus values, dirt count and identification,
ink particle, sticky counts and area determination, gloss.
Printability Testing: Vandercook proof press, MB Print
indicator, print density, mottleness, print through, IGT pick
test.
Fluff Properties Analysis: fluffing in hammermill, fiber damage
ratio, hardness index, nep or nodule count, resiliency and
absorption capacity and time, specific volume.
Other Services: permanence testing; sanitary product testing,
tissue towel and diaper testing; British Standard Sheet Machine
gridplate wire recovering; filler and additive evaluations.
BOD, COD, ammonia, total Kjeldahl nitrogen, phosphates,
alkalinity, acidity, pH, conductivity, turbidity, phenolic
substances, AOX, anions (chloride, sulfate, nitrate, nitrite,
fluoride, etc.), cations (sodium, calcium, magnesium, potassium,
etc.), cyanide, color, oil and grease, reactive silica and more;
trace level metals including chromium, lead, vanadium, iron,
zinc, manganese, titanium, and many others by ICP or AA; trace
level organics such as resin and fatty acids, PCBs, chlorinated
phenolics, formaldehyde, surfactants, methanol, chloroform,
volatile fatty acids (formic, acetic, buytric, etc.), chlorinated
acetic acids, polynuclear aromatic hydrocarbons, terpenes.
Soils, Sludges, Waste Materials: the majority of the above
effluent tests may also be applied to a wide variety of solid,
semi-solid and multiphased materials; other tests include:
1-hour aqueous extractions and 24-hour leaching per special waste
procedures, moisture, ash content, extractable organohalogen
(EOX), particle size analysis, infrared qualitative
identificaiton, and other tests; commercial solvent mixtures can
be quantified including mixtures of glycols and alcohols.
Air Samples, Industrial Hygiene: respirable quartz, organic
solvents, caustic mist, sulfuric acid mist, formaldehyde,
peroxide, total silica, oil mist, asbestos, total particulate in
air and others; mill particulate emissions including total dust
fall, anions or cations in dust fall or high volume filters.
DCM-solvent extractives (pitch control), hot water extractives,
calorific value, ash content, carbohydrates, metals and elemental
analysis, potential turpentine or tall oil.
Smelt, Green & White Liquor: A-B-C titration, trace metals,
reduction efficiency, anions (hydroxide, carbonate, chloride,
sulfide, sulfate, sulfite and thiosulfate).

Condensate: sulfide and methyl mercaptans, dimethyl sulfide and
dimethyl disulfide, methanol, Granatelli total reduced sulfur.
Pulp: carbohydrates (galactan, glucan, mannan, arabinan, xylan),
BOD, COD, aldehyde and carboxyl groups, pentosans, alpha, beta
and gamma cellulose, total (TOX, extractable (EOX) and adsorbable
(AOX) organic halogen, copper and kappa numbers, chloride,
DCM-solvent extractables (pitch), metals by ICP or AA, anions,
hexavalent chromium, viscosity, Klason lignin, total sulfur, pH,
extractable non-ionic surfactant.
Process Closure: full range of process and non-process elemental
analyses of all inputs and outputs for material balance and
corrosion studies.
Other Process Streams Analyzed: lime, limestone and reburned
lime; sulfite liquors; tall oil, spent acid; digester recovery
and other area scales.
pulping (EMCC, RDH) parameters necessary for production of ECF
and TCF pulps; evaluation of new fiber sources, including exotic
or non-wood fiber supplies; screening of pulping additives prior
to mill implementation; general pulping studies with different
chip blends to develop new fiber properties; layered cooking of
chips to determine economic benefits of chip thickness screening;
development of process parameters for mill modernization or
design of green field mills; evaluation of mill chip supplies for
pulp yield and strength; production of bleached and unbleached
pulp samples for sales staff; mechanical pulping simulations and
testing (TMP, CMP, CTMP).
Pulping Simulations and Other Capabilities: kraft batch and
continuous digester cooks, Kamyr EMCC, Kamyr MCC, Beloit RDH,
Bauer M&D cooks, kraft bomb digester cooks, soda, soda-AQ,
organosolv, ORGANOCELL, ALCELL, ASAM, acid sulfite, alkaline
sulfite, NSSC, green liquor cooks, high-yield soda ash cooks,
additives (AQ, polysulfide, surfactants), exotic or non-wood
fiber supplies or species, evaluation of mill chip supplies,
chipping, chip classification, bulk chip packing density, basic
wood density.
conditions for kraft and sulfite pulps; low-AOX and dioxin-free
bleaching sequences; peroxide and xylanase applications for
increasing ECF production capacity; recycling of office waste and
newsprint involving deinking and bleaching; dissolving pulp
bleaching, optimization and preparation of client samples;
bleaching options in modernizing and designing new bleach plants;
impact of bleach plant modification on costs, pulp strength and
effluent properties; bleaching of low-kappa EMCC and RDH pulps to
optimize strength and brightness; quantification of increased
bleaching costs caused by inter-stage carryover.
Bleaching Simulations Available: oxygen delignification, ozone,
hydrostatic oxygen (Eo), peroxide reinforcement (Eop), peroxide,
peracetic acid, performic acid, monopersulfuric acid, dimethyl
dioxirane (DMD); chlorinations (Cd, Dc or D100), chlorine
dioxide, hypochlorite, Monox-L, extractions, caustic
purifications; hydrosulfite, formamidine sulfinic acid (FAS),
borohydride; enzyme treatments, chelations.
Technology profile
expertise in chip testing, pulping, bleaching, pulp and paper
testing, dissolving pulp evaluation, microscopy, environmental
analysis and testing of process samples and liquors.
Environmental Group areas of expertise include evaluating and
assisting in solving toxicity problems. We analyze effluents,
condensates, pulps, black liquors and wood samples; testing
encompasses trace level organics, general water quality
parameters, effluent monitoring and nutrient analysis. The
Environmental lab is accredited by the Canadian Association for
Environmental Analytical Laboratories (CAEAL) and the Standards
Council of Canada (SCC) which meets or exceeds ISO 25.
The Process Chemical Group combines a knowledge of process
chemistry with analytical skills to perform both routine
evaluations and specialized tests, from black liquor calorific
value to pulp carbohydrate constituents. We can analyze process
stream samples from pulping, bleaching, recausticizing, recovery
and paper machine areas of a mill. We follow TAPPI, CPPA, SCAN,
ASTM and other standard methods.
Market profile
Industry sector market interests:
- Pulp and Paper
Geographic markets:
Export experience:
- Algeria
- Argentina
- Australia
- Brazil
- Chile
- China
- France
- Germany
- Hong Kong
- Indonesia
- Japan
- Mexico
- South Africa
- Alabama
- Alaska
- Arizona
- California
- Florida
- Georgia
- Louisiana
- Maine
- Massachusetts
- Michigan
- Minnesota
- Mississippi
- New Jersey
- New York
- Oregon
- Texas
- Washington
- Wisconsin
Third-Party Information Liability Disclaimer
Some of the information on this Web page has been provided by external sources. The Government of Canada is not responsible for the accuracy, reliability or currency of the information supplied by external sources. Users wishing to rely upon this information should consult directly with the source of the information. Content provided by external sources is not subject to official languages, privacy and accessibility requirements.
Contacts
Contact information
Description
Company description
541620 - Environmental Consulting Services
541710 - Research and Development in the Physical, Engineering and Life Sciences
Products, services and licensing
Product / Service / Licensing
foreign, exotic and non-wood; weighted average fiber length
(WAFL); fiber coarseness; sclereids per o.d. gram of pulp; fiber
curl factor and kink count; cooking uniformity; cell wall
thickness and fiber diameter in wood or pulp; deinked pulp-ink
particle count and area or sticky count and area; contaminant
identification; paper defects investigation.
Wood and Chip Testing: moisture content; length and thickness
classification; bulk and basic density; species breakdown; wood
brightness; percent bark and rot.
Air Sampling and Testing: total particulate; asbestos in bulk
samples, fiber counts, on-site sampling.
latency removal mixer; flat screening; Pulmac shive analysis;
Bauer McNett fiber classification; Optest Fiber Quality
Analyzer-WAFL, coarseness, kink and curl indices; fiber length
index (DeMontigny); freeness measurement; handsheet preparation
(white water recirculation available).
Physical Testing: burst, tear, tensile, caliper, bulk, density,
fracture toughness, fold, internal bond, porosity (Sheffield or
Gurley), smoothness (Sheffield or Gurley), stiffness (Taber or
Gurley), softness (Gurley), coefficient of static friction,
concora, flat crush, ring crush, K & N ink absorption, water
absorption, Hercules size test, water retention value, water
vapor transmission rate, zero span and short span tensile,
stretch, TEA and MOE, Brecht Imset tear, Parker print surf,
Dennison wax pick, wet tensile testing, elongation, Cobb test.
Optical Testing: brightness and brightness reversion, opacity,
Hunter and CIE color coordinates, light scattering and absorption
coefficients, luminance factor, fluorescence, whiteness or
yellowness, tristimulus values, dirt count and identification,
ink particle, sticky counts and area determination, gloss.
Printability Testing: Vandercook proof press, MB Print
indicator, print density, mottleness, print through, IGT pick
test.
Fluff Properties Analysis: fluffing in hammermill, fiber damage
ratio, hardness index, nep or nodule count, resiliency and
absorption capacity and time, specific volume.
Other Services: permanence testing; sanitary product testing,
tissue towel and diaper testing; British Standard Sheet Machine
gridplate wire recovering; filler and additive evaluations.
BOD, COD, ammonia, total Kjeldahl nitrogen, phosphates,
alkalinity, acidity, pH, conductivity, turbidity, phenolic
substances, AOX, anions (chloride, sulfate, nitrate, nitrite,
fluoride, etc.), cations (sodium, calcium, magnesium, potassium,
etc.), cyanide, color, oil and grease, reactive silica and more;
trace level metals including chromium, lead, vanadium, iron,
zinc, manganese, titanium, and many others by ICP or AA; trace
level organics such as resin and fatty acids, PCBs, chlorinated
phenolics, formaldehyde, surfactants, methanol, chloroform,
volatile fatty acids (formic, acetic, buytric, etc.), chlorinated
acetic acids, polynuclear aromatic hydrocarbons, terpenes.
Soils, Sludges, Waste Materials: the majority of the above
effluent tests may also be applied to a wide variety of solid,
semi-solid and multiphased materials; other tests include:
1-hour aqueous extractions and 24-hour leaching per special waste
procedures, moisture, ash content, extractable organohalogen
(EOX), particle size analysis, infrared qualitative
identificaiton, and other tests; commercial solvent mixtures can
be quantified including mixtures of glycols and alcohols.
Air Samples, Industrial Hygiene: respirable quartz, organic
solvents, caustic mist, sulfuric acid mist, formaldehyde,
peroxide, total silica, oil mist, asbestos, total particulate in
air and others; mill particulate emissions including total dust
fall, anions or cations in dust fall or high volume filters.
DCM-solvent extractives (pitch control), hot water extractives,
calorific value, ash content, carbohydrates, metals and elemental
analysis, potential turpentine or tall oil.
Smelt, Green & White Liquor: A-B-C titration, trace metals,
reduction efficiency, anions (hydroxide, carbonate, chloride,
sulfide, sulfate, sulfite and thiosulfate).

Condensate: sulfide and methyl mercaptans, dimethyl sulfide and
dimethyl disulfide, methanol, Granatelli total reduced sulfur.
Pulp: carbohydrates (galactan, glucan, mannan, arabinan, xylan),
BOD, COD, aldehyde and carboxyl groups, pentosans, alpha, beta
and gamma cellulose, total (TOX, extractable (EOX) and adsorbable
(AOX) organic halogen, copper and kappa numbers, chloride,
DCM-solvent extractables (pitch), metals by ICP or AA, anions,
hexavalent chromium, viscosity, Klason lignin, total sulfur, pH,
extractable non-ionic surfactant.
Process Closure: full range of process and non-process elemental
analyses of all inputs and outputs for material balance and
corrosion studies.
Other Process Streams Analyzed: lime, limestone and reburned
lime; sulfite liquors; tall oil, spent acid; digester recovery
and other area scales.
pulping (EMCC, RDH) parameters necessary for production of ECF
and TCF pulps; evaluation of new fiber sources, including exotic
or non-wood fiber supplies; screening of pulping additives prior
to mill implementation; general pulping studies with different
chip blends to develop new fiber properties; layered cooking of
chips to determine economic benefits of chip thickness screening;
development of process parameters for mill modernization or
design of green field mills; evaluation of mill chip supplies for
pulp yield and strength; production of bleached and unbleached
pulp samples for sales staff; mechanical pulping simulations and
testing (TMP, CMP, CTMP).
Pulping Simulations and Other Capabilities: kraft batch and
continuous digester cooks, Kamyr EMCC, Kamyr MCC, Beloit RDH,
Bauer M&D cooks, kraft bomb digester cooks, soda, soda-AQ,
organosolv, ORGANOCELL, ALCELL, ASAM, acid sulfite, alkaline
sulfite, NSSC, green liquor cooks, high-yield soda ash cooks,
additives (AQ, polysulfide, surfactants), exotic or non-wood
fiber supplies or species, evaluation of mill chip supplies,
chipping, chip classification, bulk chip packing density, basic
wood density.
conditions for kraft and sulfite pulps; low-AOX and dioxin-free
bleaching sequences; peroxide and xylanase applications for
increasing ECF production capacity; recycling of office waste and
newsprint involving deinking and bleaching; dissolving pulp
bleaching, optimization and preparation of client samples;
bleaching options in modernizing and designing new bleach plants;
impact of bleach plant modification on costs, pulp strength and
effluent properties; bleaching of low-kappa EMCC and RDH pulps to
optimize strength and brightness; quantification of increased
bleaching costs caused by inter-stage carryover.
Bleaching Simulations Available: oxygen delignification, ozone,
hydrostatic oxygen (Eo), peroxide reinforcement (Eop), peroxide,
peracetic acid, performic acid, monopersulfuric acid, dimethyl
dioxirane (DMD); chlorinations (Cd, Dc or D100), chlorine
dioxide, hypochlorite, Monox-L, extractions, caustic
purifications; hydrosulfite, formamidine sulfinic acid (FAS),
borohydride; enzyme treatments, chelations.
Technology
Technology profile
expertise in chip testing, pulping, bleaching, pulp and paper
testing, dissolving pulp evaluation, microscopy, environmental
analysis and testing of process samples and liquors.
Environmental Group areas of expertise include evaluating and
assisting in solving toxicity problems. We analyze effluents,
condensates, pulps, black liquors and wood samples; testing
encompasses trace level organics, general water quality
parameters, effluent monitoring and nutrient analysis. The
Environmental lab is accredited by the Canadian Association for
Environmental Analytical Laboratories (CAEAL) and the Standards
Council of Canada (SCC) which meets or exceeds ISO 25.
The Process Chemical Group combines a knowledge of process
chemistry with analytical skills to perform both routine
evaluations and specialized tests, from black liquor calorific
value to pulp carbohydrate constituents. We can analyze process
stream samples from pulping, bleaching, recausticizing, recovery
and paper machine areas of a mill. We follow TAPPI, CPPA, SCAN,
ASTM and other standard methods.
Market
Market profile
Industry sector market interests:
- Pulp and Paper
Geographic markets:
Export experience:
- Algeria
- Argentina
- Australia
- Brazil
- Chile
- China
- France
- Germany
- Hong Kong
- Indonesia
- Japan
- Mexico
- South Africa
- Alabama
- Alaska
- Arizona
- California
- Florida
- Georgia
- Louisiana
- Maine
- Massachusetts
- Michigan
- Minnesota
- Mississippi
- New Jersey
- New York
- Oregon
- Texas
- Washington
- Wisconsin


Welcome to Chapter 3 of the "Implementing a language with LLVM" tutorial. This chapter shows you how to transform the Abstract Syntax Tree, built in Chapter 2, into LLVM IR. This will teach you a little bit about how LLVM does things, as well as demonstrate how easy it is to use. It's much more work to build a lexer and parser than it is to generate LLVM IR code. :)
Please note: the code in this chapter and later require LLVM 2.2 or later. LLVM 2.1 and before will not work with it. Also note that you need to use a version of this tutorial that matches your LLVM release: If you are using an official LLVM release, use the version of the documentation included with your release or on the llvm.org releases page.
In order to generate LLVM IR, we want some simple setup to get started. First we define virtual code generation (codegen) methods in each AST class:
/// ExprAST - Base class for all expression nodes. class ExprAST { public: virtual ~ExprAST() {} virtual Value *Codegen() = 0; }; /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); }; ...
The Codegen() method says to emit IR for that AST node along with all the things it depends on, and they all return an LLVM Value object. "Value" is the class used to represent a "Static Single Assignment (SSA) register" or "SSA value" in LLVM. The most distinct aspect of SSA values is that their value is computed as the related instruction executes, and it does not get a new value until (and if) the instruction re-executes. In other words, there is no way to "change" an SSA value. For more information, please read up on Static Single Assignment - the concepts are really quite natural once you grok them.
Note that instead of adding virtual methods to the ExprAST class hierarchy, it could also make sense to use a visitor pattern or some other way to model this. Again, this tutorial won't dwell on good software engineering practices: for our purposes, adding a virtual method is simplest.
The second thing we want is an "Error" method like we used for the parser, which will be used to report errors found during code generation (for example, use of an undeclared parameter):
Value *ErrorV(const char *Str) { Error(Str); return 0; } static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); static std::map<std::string, Value*> NamedValues;
The static variables will be used during code generation. TheModule is the LLVM construct that contains all of the functions and global variables in a chunk of code. In many ways, it is the top-level structure that the LLVM IR uses to contain code.
The Builder object is a helper object that makes it easy to generate LLVM instructions. Instances of the IRBuilder class template keep track of the current place to insert instructions and has methods to create new instructions.
The NamedValues map keeps track of which values are defined in the current scope and what their LLVM representation is. (In other words, it is a symbol table for the code). In this form of Kaleidoscope, the only things that can be referenced are function parameters. As such, function parameters will be in this map when generating code for their function body.
With these basics in place, we can start talking about how to generate code for each expression. Note that this assumes that the Builder has been set up to generate code into something. For now, we'll assume that this has already been done, and we'll just use it to emit code.
Generating LLVM code for expression nodes is very straightforward: less than 45 lines of commented code for all four of our expression nodes. First we'll do numeric literals:
Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); }
In the LLVM IR, numeric constants are represented with the ConstantFP class, which holds the numeric value in an APFloat internally (APFloat has the capability of holding floating point constants of Arbitrary Precision). This code basically just creates and returns a ConstantFP. Note that in the LLVM IR that constants are all uniqued together and shared. For this reason, the API uses the "foo::get(...)" idiom instead of "new foo(..)" or "foo::Create(..)".
Value *VariableExprAST::Codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; return V ? V : ErrorV("Unknown variable name"); }
References to variables are also quite simple using LLVM. In the simple version of Kaleidoscope, we assume that the variable has already been emitted somewhere and its value is available. In practice, the only values that can be in the NamedValues map are function arguments. This code simply checks to see that the specified name is in the map (if not, an unknown variable is being referenced) and returns the value for it. In future chapters, we'll add support for loop induction variables in the symbol table, and for local variables.
Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); if (L == 0 || R == 0) return 0; switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); case '*': return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); default: return ErrorV("invalid binary operator"); } }
Binary operators start to get more interesting. The basic idea here is that we recursively emit code for the left-hand side of the expression, then the right-hand side, then we compute the result of the binary expression. In this code, we do a simple switch on the opcode to create the right LLVM instruction.
In the example above, the LLVM builder class is starting to show its value. IRBuilder knows where to insert the newly created instruction, all you have to do is specify what instruction to create (e.g. with CreateFAdd), which operands to use (L and R here) and optionally provide a name for the generated instruction.
One nice thing about LLVM is that the name is just a hint. For instance, if the code above emits multiple "addtmp" variables, LLVM will automatically provide each one with an increasing, unique numeric suffix. Local value names for instructions are purely optional, but it makes it much easier to read the IR dumps.
LLVM instructions are constrained by strict rules: for example, the Left and Right operators of an add instruction must have the same type, and the result type of the add must match the operand types. Because all values in Kaleidoscope are doubles, this makes for very simple code for add, sub and mul.
On the other hand, LLVM specifies that the fcmp instruction always returns an 'i1' value (a one bit integer). The problem with this is that Kaleidoscope wants the value to be a 0.0 or 1.0 value. In order to get these semantics, we combine the fcmp instruction with a uitofp instruction. This instruction converts its input integer into a floating point value by treating the input as an unsigned value. In contrast, if we used the sitofp instruction, the Kaleidoscope '<' operator would return 0.0 and -1.0, depending on the input value.
Value *CallExprAST::Codegen() { // Look up the name in the global module table. Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); std::vector<Value*> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); if (ArgsV.back() == 0) return 0; } return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); }
Code generation for function calls is quite straightforward with LLVM. The code above initially does a function name lookup in the LLVM Module's symbol table. Recall that the LLVM Module is the container that holds all of the functions we are JIT'ing. By giving each function the same name as what the user specifies, we can use the LLVM symbol table to resolve function names for us.
Once we have the function to call, we recursively codegen each argument that is to be passed in, and create an LLVM call instruction. Note that LLVM uses the native C calling conventions by default, allowing these calls to also call into standard library functions like "sin" and "cos", with no additional effort.
This wraps up our handling of the four basic expressions that we have so far in Kaleidoscope. Feel free to go in and add some more. For example, by browsing the LLVM language reference you'll find several other interesting instructions that are really easy to plug into our basic framework.
Code generation for prototypes and functions must handle a number of details, which make their code less beautiful than expression code generation, but allows us to illustrate some important points. First, lets talk about code generation for prototypes: they are used both for function bodies and external function declarations. The code starts with:
Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. std::vector<Type*> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
This code packs a lot of power into a few lines. Note first that this function returns a "Function*" instead of a "Value*". Because a "prototype" really talks about the external interface for a function (not the value computed by an expression), it makes sense for it to return the LLVM Function it corresponds to when codegen'd.
The call to FunctionType::get creates the FunctionType that should be used for a given Prototype. Since all function arguments in Kaleidoscope are of type double, the first line creates a vector of "N" LLVM double types. It then uses the Functiontype::get method to create a function type that takes "N" doubles as arguments, returns one double as a result, and that is not vararg (the false parameter indicates this). Note that Types in LLVM are uniqued just like Constants are, so you don't "new" a type, you "get" it.
The final line above actually creates the function that the prototype will correspond to. This indicates the type, linkage and name to use, as well as which module to insert into. "external linkage" means that the function may be defined outside the current module and/or that it is callable by functions outside the module. The Name passed in is the name the user specified: since "TheModule" is specified, this name is registered in "TheModule"s symbol table, which is used by the function call code above.
// If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name);
The Module symbol table works just like the Function symbol table when it comes to name conflicts: if a new function is created with a name that was previously added to the symbol table, the new function will get implicitly renamed when added to the Module. The code above exploits this fact to determine if there was a previous definition of this function.
In Kaleidoscope, I choose to allow redefinitions of functions in two cases: first, we want to allow 'extern'ing a function more than once, as long as the prototypes for the externs match (since all arguments have the same type, we just have to check that the number of arguments match). Second, we want to allow 'extern'ing a function and then defining a body for it. This is useful when defining mutually recursive functions.
In order to implement this, the code above first checks to see if there is a collision on the name of the function. If so, it deletes the function we just created (by calling eraseFromParent) and then calling getFunction to get the existing function with the specified name. Note that many APIs in LLVM have "erase" forms and "remove" forms. The "remove" form unlinks the object from its parent (e.g. a Function from a Module) and returns it. The "erase" form unlinks the object and then deletes it.
// If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } }
In order to verify the logic above, we first check to see if the pre-existing function is "empty". In this case, empty means that it has no basic blocks in it, which means it has no body. If it has no body, it is a forward declaration. Since we don't allow anything after a full definition of the function, the code rejects this case. If the previous reference to a function was an 'extern', we simply verify that the number of arguments for that definition and this one match up. If not, we emit an error.
// Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); // Add arguments to variable symbol table. NamedValues[Args[Idx]] = AI; } return F; }
The last bit of code for prototypes loops over all of the arguments in the function, setting the name of the LLVM Argument objects to match, and registering the arguments in the NamedValues map for future use by the VariableExprAST AST node. Once this is set up, it returns the Function object to the caller. Note that we don't check for conflicting argument names here (e.g. "extern foo(a b a)"). Doing so would be very straight-forward with the mechanics we have already used above.
Function *FunctionAST::Codegen() { NamedValues.clear(); Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0;
Code generation for function definitions starts out simply enough: we just codegen the prototype (Proto) and verify that it is ok. We then clear out the NamedValues map to make sure that there isn't anything in it from the last function we compiled. Code generation of the prototype ensures that there is an LLVM Function object that is ready to go for us.
// Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); if (Value *RetVal = Body->Codegen()) {
Now we get to the point where the Builder is set up. The first line creates a new basic block (named "entry"), which is inserted into TheFunction. The second line then tells the builder that new instructions should be inserted into the end of the new basic block. Basic blocks in LLVM are an important part of functions that define the Control Flow Graph. Since we don't have any control flow, our functions will only contain one block at this point. We'll fix this in Chapter 5 :).
if (Value *RetVal = Body->Codegen()) { // Finish off the function. Builder.CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); return TheFunction; }
Once the insertion point is set up, we call the CodeGen() method for the root expression of the function. If no error happens, this emits code to compute the expression into the entry block and returns the value that was computed. Assuming no error, we then create an LLVM ret instruction, which completes the function. Once the function is built, we call verifyFunction, which is provided by LLVM. This function does a variety of consistency checks on the generated code, to determine if our compiler is doing everything right. Using this is important: it can catch a lot of bugs. Once the function is finished and validated, we return it.
// Error reading body, remove function. TheFunction->eraseFromParent(); return 0; }
The only piece left here is handling of the error case. For simplicity, we handle this by merely deleting the function we produced with the eraseFromParent method. This allows the user to redefine a function that they incorrectly typed in before: if we didn't delete it, it would live in the symbol table, with a body, preventing future redefinition.
This code does have a bug, though. Since the PrototypeAST::Codegen can return a previously defined forward declaration, our code can actually delete a forward declaration. There are a number of ways to fix this bug, see what you can come up with! Here is a testcase:
extern foo(a b); # ok, defines foo. def foo(a b) c; # error, 'c' is invalid. def bar() foo(1, 2); # error, unknown function "foo"
For now, code generation to LLVM doesn't really get us much, except that we can look at the pretty IR calls. The sample code inserts calls to Codegen into the "HandleDefinition", "HandleExtern" etc functions, and then dumps out the LLVM IR. This gives a nice way to look at the LLVM IR for simple functions. For example:
ready> 4+5; Read top-level expression: define double @0() { entry: ret double 9.000000e+00 }
Note how the parser turns the top-level expression into anonymous functions for us. This will be handy when we add JIT support in the next chapter. Also note that the code is very literally transcribed, no optimizations are being performed except simple constant folding done by IRBuilder. We will add optimizations explicitly in the next chapter.
ready> def foo(a b) a*a + 2*a*b + b*b; Read function definition: define double @foo(double %a, double %b) { entry: %multmp = fmul double %a, %a %multmp1 = fmul double 2.000000e+00, %a %multmp2 = fmul double %multmp1, %b %addtmp = fadd double %multmp, %multmp2 %multmp3 = fmul double %b, %b %addtmp4 = fadd double %addtmp, %multmp3 ret double %addtmp4 }
This shows some simple arithmetic. Notice the striking similarity to the LLVM builder calls that we use to create the instructions.
ready> def bar(a) foo(a, 4.0) + bar(31337); Read function definition: define double @bar(double %a) { entry: %calltmp = call double @foo(double %a, double 4.000000e+00) %calltmp1 = call double @bar(double 3.133700e+04) %addtmp = fadd double %calltmp, %calltmp1 ret double %addtmp }
This shows some function calls. Note that this function will take a long time to execute if you call it.  Here you can see the big picture with all the functions referencing each other.
This wraps up the third chapter of the Kaleidoscope tutorial. Up next, we'll describe how to add JIT codegen and optimizer support to this so we can actually start running code!
Here is the complete code listing for our running example, enhanced with the LLVM code generator. Because this uses the LLVM libraries, we need to link them in. To do this, we use the llvm-config tool to inform our makefile/command line about which options to use:
# Compile clang++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy # Run ./toy
Here is the code:
// To build this: // See example below. #include "llvm/DerivedTypes.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Support/IRBuilder.h" #include <cstdio> #include <string> #include <map> #include <vector> using namespace llvm; //===----------------------------------------------------------------------===// // Lexer //===----------------------------------------------------------------------===// // The lexer returns tokens [0-255] if it is an unknown character, otherwise one // of these for known things. enum Token { tok_eof = -1, // commands tok_def = -2, tok_extern = -3, // primary tok_identifier = -4, tok_number = -5 }; static std::string IdentifierStr; // Filled in if tok_identifier static double NumVal; // Filled in if tok_number /// gettok - Return the next token from standard input. static int gettok() { static int LastChar = ' '; // Skip any whitespace. while (isspace(LastChar)) LastChar = getchar(); if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* IdentifierStr = LastChar; while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; if (IdentifierStr == "def") return tok_def; if (IdentifierStr == "extern") return tok_extern; return tok_identifier; } if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; LastChar = getchar(); } while (isdigit(LastChar) || LastChar == '.'); NumVal = strtod(NumStr.c_str(), 0); return tok_number; } if (LastChar == '#') { // Comment until end of line. do LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); if (LastChar != EOF) return gettok(); } // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; // Otherwise, just return the character as its ascii value. int ThisChar = LastChar; LastChar = getchar(); return ThisChar; } //===----------------------------------------------------------------------===// // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// /// ExprAST - Base class for all expression nodes. class ExprAST { public: virtual ~ExprAST() {} virtual Value *Codegen() = 0; }; /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); }; /// VariableExprAST - Expression class for referencing a variable, like "a". class VariableExprAST : public ExprAST { std::string Name; public: VariableExprAST(const std::string &name) : Name(name) {} virtual Value *Codegen(); }; /// BinaryExprAST - Expression class for a binary operator. class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; public: BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; std::vector<ExprAST*> Args; public: CallExprAST(const std::string &callee, std::vector<ExprAST*> &args) : Callee(callee), Args(args) {} virtual Value *Codegen(); }; /// PrototypeAST - This class represents the "prototype" for a function, /// which captures its name, and its argument names (thus implicitly the number /// of arguments the function takes). class PrototypeAST { std::string Name; std::vector<std::string> Args; public: PrototypeAST(const std::string &name, const std::vector<std::string> &args) : Name(name), Args(args) {} Function *Codegen(); }; /// FunctionAST - This class represents a function definition itself. class FunctionAST { PrototypeAST *Proto; ExprAST *Body; public: FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} Function *Codegen(); }; //===----------------------------------------------------------------------===// // Parser //===----------------------------------------------------------------------===// /// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current /// token the parser is looking at. getNextToken reads another token from the /// lexer and updates CurTok with its results. static int CurTok; static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. static std::map<char, int> BinopPrecedence; /// GetTokPrecedence - Get the precedence of the pending binary operator token. static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; return TokPrec; } /// Error* - These are little helper functions for error handling. ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } static ExprAST *ParseExpression(); /// identifierexpr /// ::= identifier /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; getNextToken(); // eat identifier. if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); // Call. getNextToken(); // eat ( std::vector<ExprAST*> Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); if (!Arg) return 0; Args.push_back(Arg); if (CurTok == ')') break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); getNextToken(); } } // Eat the ')'. getNextToken(); return new CallExprAST(IdName, Args); } /// numberexpr ::= number static ExprAST *ParseNumberExpr() { ExprAST *Result = new NumberExprAST(NumVal); getNextToken(); // consume the number return Result; } /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { getNextToken(); // eat (. ExprAST *V = ParseExpression(); if (!V) return 0; if (CurTok != ')') return Error("expected ')'"); getNextToken(); // eat ). return V; } /// primary /// ::= identifierexpr /// ::= numberexpr /// ::= parenexpr static ExprAST *ParsePrimary() { switch (CurTok) { default: return Error("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: return ParseNumberExpr(); case '(': return ParseParenExpr(); } } /// binoprhs /// ::= ('+' primary)* static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; // Okay, we know this is a binop. int BinOp = CurTok; getNextToken(); // eat binop // Parse the primary expression after the binary operator. ExprAST *RHS = ParsePrimary(); if (!RHS) return 0; // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { RHS = ParseBinOpRHS(TokPrec+1, RHS); if (RHS == 0) return 0; } // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } } /// expression /// ::= primary binoprhs /// static ExprAST *ParseExpression() { ExprAST *LHS = ParsePrimary(); if (!LHS) return 0; return ParseBinOpRHS(0, LHS); } /// prototype /// ::= id '(' id* ')' static PrototypeAST *ParsePrototype() { if (CurTok != tok_identifier) return ErrorP("Expected function name in prototype"); std::string FnName = IdentifierStr; getNextToken(); if (CurTok != '(') return ErrorP("Expected '(' in prototype"); std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); // success. getNextToken(); // eat ')'. return new PrototypeAST(FnName, ArgNames); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); if (Proto == 0) return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); return 0; } /// toplevelexpr ::= expression static FunctionAST *ParseTopLevelExpr() { if (ExprAST *E = ParseExpression()) { // Make an anonymous proto. PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>()); return new FunctionAST(Proto, E); } return 0; } /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { getNextToken(); // eat extern. return ParsePrototype(); } //===----------------------------------------------------------------------===// // Code Generation //===----------------------------------------------------------------------===// static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); static std::map<std::string, Value*> NamedValues; Value *ErrorV(const char *Str) { Error(Str); return 0; } Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); } Value *VariableExprAST::Codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; return V ? V : ErrorV("Unknown variable name"); } Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); if (L == 0 || R == 0) return 0; switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); case '*': return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); default: return ErrorV("invalid binary operator"); } } Value *CallExprAST::Codegen() { // Look up the name in the global module table. Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); std::vector<Value*> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); if (ArgsV.back() == 0) return 0; } return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. std::vector<Type*> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); // Add arguments to variable symbol table. NamedValues[Args[Idx]] = AI; } return F; } Function *FunctionAST::Codegen() { NamedValues.clear(); Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); if (Value *RetVal = Body->Codegen()) { // Finish off the function. Builder.CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); return TheFunction; } // Error reading body, remove function. TheFunction->eraseFromParent(); return 0; } //===----------------------------------------------------------------------===// // Top-Level parsing and JIT Driver //===----------------------------------------------------------------------===// static void HandleDefinition() { if (FunctionAST *F = ParseDefinition()) { if (Function *LF = F->Codegen()) { fprintf(stderr, "Read function definition:"); LF->dump(); } } else { // Skip token for error recovery. getNextToken(); } } static void HandleExtern() { if (PrototypeAST *P = ParseExtern()) { if (Function *F = P->Codegen()) { fprintf(stderr, "Read extern: "); F->dump(); } } else { // Skip token for error recovery. getNextToken(); } } static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { fprintf(stderr, "Read top-level expression:"); LF->dump(); } } else { // Skip token for error recovery. getNextToken(); } } /// top ::= definition | external | expression | ';' static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { case tok_eof: return; case ';': getNextToken(); break; // ignore top-level semicolons. case tok_def: HandleDefinition(); break; case tok_extern: HandleExtern(); break; default: HandleTopLevelExpression(); break; } } } //===----------------------------------------------------------------------===// // "Library" functions that can be "extern'd" from user code. //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. extern "C" double putchard(double X) { putchar((char)X); return 0; } //===----------------------------------------------------------------------===// // Main driver code. //===----------------------------------------------------------------------===// int main() { LLVMContext &Context = getGlobalContext(); // Install standard binary operators. // 1 is lowest precedence. BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); getNextToken(); // Make the module, which holds all the code. TheModule = new Module("my cool jit", Context); // Run the main "interpreter loop" now. MainLoop(); // Print out all of the generated code. TheModule->dump(); return 0; }


Contents
Overview - Details general art alt. information.
Art Listing - Lists all the art alts. present in the game.
Adding Art Alts. - Details how to add new art alts. to the game.
Remarks - General and misc. information.
Overview
Note, this page simply provides a reference of all the currently known art alts. that can be used. For information on how to modify the art_alts variable in the tilesets file, see the Art Alts. section on the Tilesets page.
Art alts. allow for instances of graphics to be swapped out with other graphics, allowing for a large amount of visual flexibility and variance. For more information on how to apply art alts, within an area, see the Art Alts. section of the Tilesets page.
Art Listing
The following listing displays all the known art alts. Many have pictures attached to provide a visual representation of what they look like, but for others just a description is supplied. The assets have been categorised, in the list below, to make finding the right art alt. easier.
General - Generic art assets and items.
Enemies - The hostile enemies.
Mini - Small decorative creatures.
Decorations - Decorative assets.
Retro - Retro entities and items.
NPCs - Interactive NPCs.
Tilesets - The tile graphics.
Overlays - Decorations on top of tile graphics.
Backgrounds - Background images.
Foregrounds - Foreground images.
Mix-FX Layers - Shader effect layer graphics.
Particles - Effects and particles.
Cutscenes - Video animations.
Transitions - Screen transitions and effects.
GUI - Interface elements and UI graphics.
Misc. - Assets that fit in no category above, or are unused.
General |
||||
|---|---|---|---|---|
Player |
Life |
BigLife |
CartConsole |
Cartridge |
cart2 |
cart3 |
Key |
Hopper |
ChainHitch |
ChainLink and ChainLink2 |
FloatingMine |
Jar |
OutWarp |
Gate1 |
Gate2 |
Gate3 |
Gate4 |
DeathGhost |
TheHead |
TheBody |
TheHeart |
Stand |
FinalSteve |
GlowShroom |
GlowShroomSmall |
Enemies |
||||
|---|---|---|---|---|
MovingOrbBlob |
orbblob |
OrbBlob2 |
OrbSmall |
OrbLarge |
OrbLarge2 |
OrbChomp |
AimSpitter |
AimSpitter2 |
eyeshooter |
SpitterX |
SpitterY |
Bullet |
eyebullet |
Floater |
ChargeSlug |
Slug |
BigCharger |
BigSlug |
Splatter |
Gasser |
GasCloud |
Cannon |
Cannonstand |
Cannonball |
Fireball |
ThwampEye |
ThwampGear |
CheepCheep |
Frog |
SkullCrow |
SkullFloater |
SkullFloaterBreaky |
SkullSlug |
Bouncer |
ChainChomp |
CreepingMass |
CreepEye |
Fish |
Fish2 |
Mask |
Revolver |
gface and ElectroBall |
Ghost |
Sentry |
Mini |
||||
|---|---|---|---|---|
MiniDrone |
MiniBird |
Fly and MiniFly |
MiniFish |
MiniFishWhite |
MiniFlea |
MiniFrog |
MiniFrogWhite |
MiniGhost |
MiniWisp |
MiniRat |
MiniRatWhite |
MiniWorm |
Decorations |
||||
|---|---|---|---|---|
Decoration0 |
Decoration1 |
decoration 8 and Deco10 |
Decoration9 |
Decoration4 |
Decoration5 |
Decoration6 |
Decoration7 |
Deco11 |
inst10 |
inst11 |
eyeball |
EscapeEnd |
Retro |
||||
|---|---|---|---|---|
MiniDrone |
Cannonretro |
Cannonstandretro |
cannonballretro |
cannonballfireretro |
Gasserretro |
GasCloudretro |
Floaterretro |
Floater2 |
FloaterGlitch |
SkullFloaterretro |
SkullSlugretro |
SkullCrowretro |
cheepretro |
Frogretro |
RetroOrbSmall |
RetroOrbLarge |
pacman |
RetroElectroBall |
RetroGhost |
Maskretro |
ChainChompretro |
ChainHitchretro |
ChainLinkretro |
Revolverretro |
Bouncerretro |
CreepingMassRetro |
hopperretro |
ThwampEyeRetro |
ThwampGearRetro |
Slugretro |
RetroChargerSlug |
Splatterretro |
bulletretro |
RetroFish |
SpitterZretro |
SpitterYretro |
SpitterXretro |
Coin |
cartend |
NPCs |
|||||
|---|---|---|---|---|---|
NPC0 |
NPC1 |
NPC2 |
NPC3 |
NPC4 |
NPC5 |
NPC6 |
NPC7 |
NPC8 |
NPC9 |
NPC10 |
NPC11 |
NPC12 |
NPC13 |
NPC14 |
NPC15 |
NPC16 |
NPC17 |
NPCB1 |
NPCB2 |
NPCB3 |
NPCB4 |
NPCB5 |
NPCB6 |
NPCB7 |
NPCG1 |
NPCG2 |
NPCG3 |
NPCG4 |
NPCG5 |
NPCG6 |
NPCG7 |
NPCD1 |
NPCD2 |
NPCD3 |
NPCD4 |
NPCD5 |
NPCD6 |
NPCD7 |
NPCX1 |
NPCX2 |
NPCX3 |
NPCX4 |
NPCX5 |
NPCH1 |
NPCH2 |
NPCH3 |
NPCH4 |
Tilesets |
|
|---|---|
Tilecity |
Tilefield |
Tilecaves |
Tiletox |
Tiletox2 |
Tilehell |
Tileairship |
Tilecomplex |
theglow |
TileEnd |
Tileretro |
TileGlitch |
Tilesewers |
Tile |
Overlays |
|
|---|---|
Overlayscity |
Overlaysfield |
Overlayscaves |
Overlaystox |
Overlaystox2 |
Overlayshell |
Overlaysairship |
Overlayscomplex |
Overlaystheglow |
Overlaysend |
Overlaysretro |
TileOverlays |
Backgrounds |
|
|---|---|
bg2 |
ch2bg |
ch3bg |
ch4abg |
Background |
hellbg |
airshipbg |
field2bg |
bgsolid |
neverbg |
bgretro |
bgretrox |
bgretro2 |
None |
Foregrounds |
|
|---|---|
fg1 |
fgretro |
Mid-FX Layers |
|
|---|---|
SolidBox |
ShadeBox |
(The following art alts. are simply listed, and have no graphical representations yet.)
Particles
ToxicParticle - Used in the toxic waterfall particle effect.
ToxicParticle2 - An unused variant of the toxic particle.
TestParticle - Used for the falling tile dust particle.
TestParticle2 - Used in a variety of different particle effects.
soliddrip - Used in a variety of liquid-based particle effects.
spark - A sparking particle.
spark2 - A slight variant on the other sparking particle.
Rock - Used in the rocks particle effect.
Rock2 - Used in a variety of block breaking particle effects.
Light - An orb of light used in a single particle effect.
Lightning - A lightning effect used in Nevermore and The Future.
Leaf - Falling leaves particle.
Leaf2 - A variant of the falling leaves particle.
goo1 - An unused goo particle.
goo2 - A goo particle used when splashing in toxic water.
Gibs - Unused player death particles.
Gibs2 - One of the particles used in the player’s death, chunks of gore.
DistortionParticle - Greeny-red blobs used in distortion-based particles.
DistortionParticle2 - A slight variation of the other distortion particle.
WindCloud - A variety of different cloud shapes.
cloud - Used in player/enemy bouncing particles and the exploding mines.
blackpart - One of the effects used in the player’s death, black circles.
Cutscenes
towerending - Completing the Acceptance cartridge.
allstarending - Completing the All Stars cartridge.
towercart - Collecting all Iron Carts.
supercart - Collecting all regular Cartridges.
NevermoreCutscene - The intro after losing 450 tumors, the giant orb expanding.
NevermoreCutscene_Win - The true ending for the game after beating Nevermore.
GameIntro - The intro cutscene before playing the cartridge.
CartIntro - The intro cutscene before playing the cartridge, with The End is Nigh cart intro as well.
IntroCutscene - Intro cutscene, after dying in the intro cartridge.
IntroCutscene_Egg - The cutscene played if the intro cartridge is completed.
GameOverCutscene - Game over cutscene in The Future levels.
GameOverCutscene_Cart - Game over screen in cartridge levels.
EscapeSequenceCutscene - The intro to the Acceptance escape sequence.
EscapeSequenceCutscene_Win - Beating the Acceptance escape sequence, the end of the game.
CartIntro2 - Cartridge cover intro with fade into the level.
ContinueCutscene - Continue screen when enough lives are lost in a retro cartridge.
CartWin - Beating a cartridge screen.
AssembleDudeCutscene - The cutscene of the friend being assembled.
Transitions
Wipetranswarp - Map warping and leaving a secret transition.
Wipetranssteven - Entering one of the The Future levels via a Steven.
Wipetransright - Screen wipe from left-to-right.
Wipetransleft - Screen wipe from right-to-left.
Wipetransdown - Screen wipe from bottom-to-top
Wipetransup - Screen wipe from top-to-bottom.
Wipetrans - The same as Wipetransright.
fadetrans - Fade to black.
retrofadetrans - Retro fade to black.
halfretrofadetrans - Retro fade to black and normal fade out from black.
GUI
Unlockinfo - "Cartridge Unlocked" pop-up message.
Unlockinfo2 - "Warp Point Unlocked" pop-up message.
TumorIcon - The various tumor icons used on the top-left tumor count in-game.
TitleScreen - The game intro followed by the title screen.
SpeechBubble - An NPC speech bubble.
SpeechBubble2 - An NPC speech bubble.
SkipPrompt - The "Skip Cutscene" prompt.
SaveFileCard - One of the save file ghosts, showcasing unlock info.
RetroLivesCounter - A counter of the current number of lives.
prog_cart - The progress counter on the left of regular carts: "1234!"
PauseMenu - The in-game pause menu screen.
MapPing - The downward arrow that points to important locations on the map.
MapIcon - The Ash icon that moves around the map.
map_node - A singular dotted-line and area icon, with text.
Map - The entire map menu, with all the nodes, elements, and the background.
MainMenu_Selector - The text featured on the title screen "Play", "Options", and "Quit".
LoadFile - The save file selection screen.
LevelTitle - The various area label frames fading in and out.
Letterbox - Screen letterboxing. (Used in cutscenes?)
HUD - The entirety of the on-screen HUD, including the escape counter.
DebugConsole - The debug console screen.
Misc.
BigLink - Three chain links with a red scribble drawn through them.
x - An unused game over message, using the normal font.
Warp - A static piece of the secret "Leave Area" warp.
OS_Indicator - A circle containing Ash’s face. (Potentially used to mark where/when Ash was off-screen?)
EscapeTrigger - A doodle of a character holding a bomb.
Carts - Placeholder cartridge art.
CamOverlay - Random text in the top-left corner of the screen.
PlayerTrail - The player’s trail. (In the air?)
PlayerTrailGround - The player’s trail on the ground.
PlayerTrailGround2 - A slightly different variant of the player’s trail on the ground.
PlayerTrailDucking - The player’s trail whilst ducking.
ButtonBlock_Out - A tile shrinking, used when a switch despawns a tile.
ButtonBlock_In - A tile expanding, used when a switch spawns a tile.
Adding Art Alts.
Adding art alts. can be done by modifying the game’s SWF. Making art alts. requires an understanding of existing art alts. so that frame and layer patterns can be replicated correctly based on what is being created (e.g. all tilesets require the same basic layout, just different graphics). Once the graphics have been developed, AS (ActionScript) linkage must be applied to that the game has a name it can use to reference the asset, just like with the other art alts.
[UNDER DEVELOPMENT: Current information is bare-bones and will be updated with more detail in a future update.]
Remarks
Art alts are used and referenced in a variety of different files to add graphics to certain entities within the game. These files are as follows: data\npcs.txt, data\tilesets.txt, and data\particles.txt. Clicking on any of these filenames will take you to their respective pages for more information (particles not yet available).
Not all art alts. will work in a usable fashion and be compatible with one another. A good example being any of the tilesets which, if applied to something like an NPC, will simply display all of its individual tile graphics in rapid succession. Noting down all of these potential incompatibilities would be far too large and complex of a list, so trial-and-error, as well as practice, is the best method for figuring out what will and will not work.
If the game crashes with an error referring to a movie clip not being found, it is most likely due to an art alt. being named incorrectly in one of the files referenced above.


| ZOBS | D | observed zenith distance of the source (radians) |
|---|---|---|
| HM | D | height of the observer above sea level (metre) |
| TDK | D | ambient temperature at the observer (degrees K) |
| PMB | D | pressure at the observer (mB) |
| RH | D | relative humidity at the observer (range 0-1) |
| WL | D | effective wavelength of the source () |
| PHI | D | latitude of the observer (radian, astronomical) |
| TLR | D | temperature lapse rate in the troposphere (degrees K per metre) |
| EPS | D | precision required to terminate iteration (radian) |
| REF | D | refraction: in vacuo ZD minus observed ZD (radians) |
|---|
for any reasonable combination of parameters. However, the improved water-vapour expressions do make a significant difference in the radio band, at zenith distance reaching almost for a hot, humid, low-altitude site during a period of low pressure.
SLALIB --- Positional Astronomy Library


This is meant to be a bare bones demonstration of the jQuery plugin. For more details, please refer to the documentation.


"""
Various NearNeighbors strategies to define local environments
of sites in structure/molecule. Most of them are directly
from pymatgen.analysis.local_env. The suitable NearNeighbors
should have get_nn_info method implemented and this method
needs to return a list of dict with each entry having following keys
['site', 'image', 'weight', 'site_index']
the weight will be used as the bond attributes in subsequent graph
construction
"""
from inspect import getfullargspec
from typing import Dict, List, Union
from pymatgen.core import Structure, Molecule
from pymatgen.analysis import local_env
from pymatgen.analysis.local_env import (
NearNeighbors,
VoronoiNN,
JmolNN,
MinimumDistanceNN,
OpenBabelNN,
CovalentBondNN,
MinimumVIRENN,
MinimumOKeeffeNN,
BrunnerNN_reciprocal,
BrunnerNN_real,
BrunnerNN_relative,
EconNN,
CrystalNN,
CutOffDictNN,
Critic2NN,
)
[docs]class MinimumDistanceNNAll(NearNeighbors):
"""
Determine bonded sites by fixed cutoff
"""
def __init__(self, cutoff: float = 4.0):
"""
Args:.
cutoff (float): cutoff radius in Angstrom to look for trial
near-neighbor sites (default: 4.0).
"""
self.cutoff = cutoff
[docs] def get_nn_info(self, structure: Structure, n: int) -> List[Dict]:
"""
Get all near-neighbor sites as well as the associated image locations
and weights of the site with index n using the closest neighbor
distance-based method.
Args:
structure (Structure): input structure.
n (integer): index of site for which to determine near
neighbors.
Returns:
siw (list of tuples (Site, array, float)): tuples, each one
of which represents a neighbor site, its image location,
and its weight.
"""
site = structure[n]
neighs_dists = structure.get_neighbors(site, self.cutoff)
siw = []
for nn in neighs_dists:
siw.append(
{
"site": nn,
"image": self._get_image(structure, nn),
"weight": nn.nn_distance,
"site_index": self._get_original_site(structure, nn),
}
)
return siw
[docs]class AllAtomPairs(NearNeighbors):
"""
Get all combinations of atoms as bonds in a molecule
"""
[docs] def get_nn_info(self, molecule: Molecule, n: int) -> List[Dict]:
"""
Get near neighbor information
Args:
molecule (Molecule): pymatgen Molecule
n (int): number of molecule
Returns: List of neighbor dictionary
"""
site = molecule[n]
siw = []
for i, s in enumerate(molecule):
if i != n:
siw.append({"site": s, "image": None, "weight": site.distance(s), "site_index": i})
return siw
[docs]def serialize(identifier: Union[str, NearNeighbors]):
"""
Serialize the local env objects to a dictionary
Args:
identifier: (NearNeighbors object/str/None)
Returns: dictionary or None
"""
if isinstance(identifier, str):
return identifier
if isinstance(identifier, NearNeighbors):
args = getfullargspec(identifier.__class__.__init__).args
d = {"@module": identifier.__class__.__module__, "@class": identifier.__class__.__name__}
for arg in args:
if arg == "self":
continue
try:
a = identifier.__getattribute__(arg)
d[arg] = a
except AttributeError:
raise ValueError("Cannot find the argument")
if hasattr(identifier, "kwargs"):
d.update(**identifier.kwargs)
return d
if identifier is None:
return None
raise ValueError("Unknown identifier for local environment ", identifier)
[docs]def deserialize(config: Dict):
"""
Deserialize the config dict to object
Args:
config: (dict) nn_strategy config dict from seralize function
Returns: object
"""
if config is None:
return None
if ("@module" not in config) or ("@class" not in config):
raise ValueError("The config dict cannot be loaded")
modname = config["@module"]
classname = config["@class"]
mod = __import__(modname, globals(), locals(), [classname])
cls_ = getattr(mod, classname)
data = {k: v for k, v in config.items() if not k.startswith("@")}
return cls_(**data)
NNDict = {
i.__name__.lower(): i
for i in [
NearNeighbors,
VoronoiNN,
JmolNN,
MinimumDistanceNN,
OpenBabelNN,
CovalentBondNN,
MinimumVIRENN,
MinimumOKeeffeNN,
BrunnerNN_reciprocal,
BrunnerNN_real,
BrunnerNN_relative,
EconNN,
CrystalNN,
CutOffDictNN,
Critic2NN,
MinimumDistanceNNAll,
AllAtomPairs,
]
}
[docs]def get(identifier: Union[str, Dict, NearNeighbors]) -> NearNeighbors:
"""
Deserialize the NearNeighbors
Args:
identifier (str, dict or NearNeighbors): target for deserialize
Returns: NearNeighbors instance
"""
# deserialize NearNeighbor from str
if isinstance(identifier, str):
if identifier.lower() in NNDict:
return NNDict.get(identifier.lower())
# try pymatgen's local_env module
nn = getattr(local_env, identifier, None)
if nn is not None:
return nn
if isinstance(identifier, dict):
return deserialize(identifier)
if isinstance(identifier, NearNeighbors):
return identifier
raise ValueError(f"{identifier} not identified")


Question Paper (Section)
Sections
- {{section['section_name']}}
View in:
{{option.text}}
{{option.text}}
{{sectionObject[activeSectionIndex]? sectionObject[activeSectionIndex].attempted: 0}}
Answered
{{sectionObject[activeSectionIndex]? sectionObject[activeSectionIndex].not_answered: 0}}
Not answered
{{sectionObject[activeSectionIndex]? sectionObject[activeSectionIndex].not_visited: 0}}
Not visited
{{sectionObject[activeSectionIndex]? sectionObject[activeSectionIndex].review_later: 0}}
Review later
{{sectionObject[activeSectionIndex]? sectionObject[activeSectionIndex].answered_marked : 0}}
Answered & marked for Review Later
{{ sectionObject[activeSectionIndex]?.section_name }}
Choose a question
{{ questionIndex + 1 }}


Another new editor screenshot. Also, I'm gone for a week++
Posted: Sat Jun 13, 2009 4:35 am
Yep, fire! Visual FX are now set up along with an intuitive point-and-click editor to see what they do. I have to code up all the other types (I've only got one particle type in there right now) but this will be done soon after I get back. Since I can attach effects to objects really easily, we'll be able to add bunches of nifty stuff to the game to make it more visually interesting to play.
See you when I get back,
Karl


The message must be at least 10 characters long. Try out what happens if you enter a shorter message.


|
BitShares-Core
6.1.0
BitShares blockchain implementation and command-line interface software
|
#include <sha512.hpp>
Classes | |
| class | encoder |
Public Member Functions | |
| sha512 () | |
| sha512 (const std::string &hex_str) | |
| std::string | str () const |
| operator std::string () const | |
| char * | data () const |
Static Public Member Functions | |
| static constexpr size_t | data_size () |
| static sha512 | hash (const char *d, uint32_t dlen) |
| static sha512 | hash (const std::string &) |
| template<typename T > | |
| static sha512 | hash (const T &t) |
Public Attributes | |
| boost::endian::little_uint64_buf_t | _hash [8] |
Friends | |
| template<typename T > | |
| T & | operator<< (T &ds, const sha512 &ep) |
| template<typename T > | |
| T & | operator>> (T &ds, sha512 &ep) |
| sha512 | operator<< (const sha512 &h1, uint32_t i) |
| bool | operator== (const sha512 &h1, const sha512 &h2) |
| bool | operator!= (const sha512 &h1, const sha512 &h2) |
| sha512 | operator^ (const sha512 &h1, const sha512 &h2) |
| bool | operator>= (const sha512 &h1, const sha512 &h2) |
| bool | operator> (const sha512 &h1, const sha512 &h2) |
| bool | operator< (const sha512 &h1, const sha512 &h2) |
Definition at line 9 of file sha512.hpp.
| fc::sha512::sha512 | ( | ) |
Definition at line 12 of file sha512.cpp.
|
explicit |
Definition at line 13 of file sha512.cpp.
| char * fc::sha512::data | ( | ) | const |
Definition at line 22 of file sha512.cpp.
|
inlinestatic |
Definition at line 19 of file sha512.hpp.
|
static |
Definition at line 34 of file sha512.cpp.
|
static |
Definition at line 39 of file sha512.cpp.
|
inlinestatic |
Definition at line 25 of file sha512.hpp.
| fc::sha512::operator std::string | ( | ) | const |
Definition at line 20 of file sha512.cpp.
| string fc::sha512::str | ( | ) | const |
Definition at line 17 of file sha512.cpp.
Definition at line 81 of file sha512.cpp.
Definition at line 78 of file sha512.cpp.
|
friend |
Definition at line 49 of file sha512.hpp.
Definition at line 55 of file sha512.cpp.
Definition at line 84 of file sha512.cpp.
Definition at line 75 of file sha512.cpp.
Definition at line 72 of file sha512.cpp.
|
friend |
Definition at line 55 of file sha512.hpp.
Definition at line 60 of file sha512.cpp.
| boost::endian::little_uint64_buf_t fc::sha512::_hash[8] |
Definition at line 67 of file sha512.hpp.


Workshops
Workshop 01
Workshop 02
Workshop 03 - Mean
Workshop 03 - Media
Workshop 03 - Mode
Workshop 04


SoftUni Exam
Home
Books
Login Search Form
Lorem Ipsum Site
Responsive Web Site
Task 1: Books
Task 2: Login Search Form
Task 3: Lorem Ipsum Site
Task 4: Responsive Web Site


Being born and raised in the outskirts of Nairobi, I never thought that i would love anything to do with computers. But here I am writing code like no ones buisness. Any way I pursed my primary education and managed to get myself a KCPE certificate and also was able to go to secondary school and also achieved my KCSE certificate to. From there i managed to acquire a job at floor masters where i worked for two years untill i managed to acquire a scholarship in moringa.
Why Moringa you may ask, coming to a point where you have to follow you passion where do you go but to a place where you know they are the best.
What are my hobbies, swimming is definately not one of them.I actually love listening to music, hiking, watching movies and travelling among many more others.


404: Page not found
Sorry, we've misplaced that URL or it's pointing to something that doesn't exist. Head back home to try finding it again.
{{ $baseUrl := .Site.BaseURL }} {{ partial "head.html" . }}
{{ partial "header.html" . }}Sorry, we've misplaced that URL or it's pointing to something that doesn't exist. Head back home to try finding it again.


Welcome to Bethany's Pie shop
For many years, Bethany has been baking the most delicious pies at her home. In 2013, we opened our first store in Brussels(Belgium) in a cosy little street near the Grand Market. People from all over the world fell in love with the soft cakes, heavenly cheese cakes, spicy apple pies... The store became a success in no time. In 2015, no less than 100 pies were sold eveeryday and Bethany's Pie shop moved to a larger building. After recieving many requests, it became clear that our next step was making it possible to order ppies from the comfort of your own home and from anywhere in the world. You are now looking at the result of this: our very own webstore,making it possible to order Bethany's delicious pies whenever you feel like it! Bethany is famous for using only the best ingredients. This way, we can make sure that our pies are absolutely the best From pecan to plum, our pies are made with the warmth and Take a moment to Browse our pies and see which of our delectable desserts are soon to arrive on your doorstep 2020 Bethany's Pie Shop - All rights reserved


RACRtune
· B01 Demo 1b: Distributed Indexing of Wikipedia Text Data
Commands
0
Ws
paper 01
paper 02
Console


Freelance Front-end Wed Developer and Technical Recruiter based in Atlanta GA
Experience in front end web application design & data base engineering
Password Generator
Eat-da-Burger Application
Project 2 - Ravens Athletic Club
Project 1 - The Traveller's Handbook
Code Quiz
Team Developer Profile Generator


Should be at least 8 characters long, contain upper and lowercase characters, at least 1 number and a special character.
Passwords do not match.


| Id | {{editedCard._id}} | ||
| Card version | |||
| Proofreading status | |||
| Inner type | {{editedCard.type}} | ||
| Name | |||
| Full name | |||
| Qualification | |||
| Warjack points | Warbeasts points | Cost | |
| Cost | points for models | ||
| Cost | / points for / models (set max cost and size to '-' if this unit has not a variable size/cost) | ||
| Field Allowance |


This page shows automated results of the Ursids 2007, based on visual data entered through the IMO electronic report form. Send your feedback regarding this page to Geert Barentsen or visit the project pages. Note that these automated results may not be suitable for scientific use!
Page generated on 29 March 2008 at 14:55 UT.
ZHRmax = 34 based on 179 Ursids in 148 data intervals, assuming fixed population index r = 2.5 and zenith correction 1/sin(hR).
| Time (UT) | Solarlon | nINT | nURS | ZHR | |
|---|---|---|---|---|---|
| 2007-12-19 01:47 | 266.655 | 6 | 7 | 3 | +-1 |
| 2007-12-21 03:15 | 268.752 | 16 | 18 | 6 | +-1 |
| 2007-12-22 09:50 | 270.050 | 5 | 17 | 12 | +-3 |
| 2007-12-22 18:33 | 270.419 | 18 | 24 | 20 | +-4 |
| 2007-12-22 20:19 | 270.495 | 25 | 33 | 30 | +-5 |
| 2007-12-22 21:16 | 270.534 | 33 | 50 | 34 | +-5 |
| 2007-12-22 22:09 | 270.572 | 20 | 22 | 23 | +-5 |
| 2007-12-23 00:38 | 270.678 | 25 | 8 | 6 | +-2 |
For each estimation interval: time is the middle of the interval, nINT is the number of observing periods and nURS is the number of Ursids involved. ZHR = (1 + sum nURS) / sum(Teff/C) where Teff is the effective observing time and C is the total correction for limiting magnitude, clouds and zenith correction. The solar longitudes refer to equinox J2000.0.
Data has been received from 21 observers in 11 countries. Thank you for your efforts!
| Observer | Country | Teff | nURS |
|---|---|---|---|
| Salvador Aguirre | Mexico | 10.20h | 8 |
| Karl Antier | France | 1.00h | 2 |
| Felix Bettonvil | Netherlands | 1.50h | 2 |
| Marcin Chwala | Poland | 1.50h | 3 |
| Sietse Dijkstra | Netherlands | 3.18h | 9 |
| Valentin Grigore | Romania | 4.64h | 10 |
| Vilem Heblik | Czech Republic | 1.50h | 2 |
| Carl Johannink | Netherlands | 5.42h | 7 |
| Jakub Koukal | Czech Republic | 4.00h | 13 |
| Jakub Koukal | Czech Republic | 6.00h | 16 |
| Peter Van Leuteren | Netherlands | 2.85h | 7 |
| Jiawei Ma | China | 0.44h | 7 |
| Koen Miskotte | Netherlands | 1.80h | 7 |
| Markku Nissinen | Finland | 3.10h | 20 |
| Tereza Novotna | Czech Republic | 1.00h | 2 |
| Krzysztof Polakowski | Poland | 5.00h | 16 |
| Alex Scholten | Netherlands | 2.00h | 6 |
| Tadeusz Sobczak | Poland | 2.15h | 6 |
| Izabela Spaleniak | Poland | 0.50h | 1 |
| Michel Vandeputte | Belgium | 9.00h | 27 |
| Lukasz Wozniak | Poland | 1.62h | 15 |
Create your own analysis!
Rate intervals: urs2007_rate.csv (CSV-format).
Magnitude distributions: urs2007_magn.csv (CSV-format).


If you’re a blogger, you might use MailChimp to build a subscriber list, and Story makes that easy. MailChimp also has the ability to automatically send your new content to the list from an RSS feed, and guess what—Story helps you create an RSS feed customized just for that if you like, too.
First, MailChimp subscriber forms. If you want to add a subscription form at the
bottom of each page, just add your MailChimp URL as a parameter in your
configuration file. Here’s a YAML example for config.yaml
:
params:
- mailchimp: "your URL here"
And here’s an example for config.toml
:
[params]
mailchimp = "your URL here"
You can copy the URL from the address bar of your MailChimp subscriber form. It
becomes the action
of the form, which will appear at the bottom of each page
near your author biography.
Next, an RSS feed. Story has an RSS layout customized to create summaries of
your content’s title, description, featured image, and summary content. The
summary content is either delimited explicitly by the <!--more-->
comment in
your Markdown source, or generated automatically by Hugo. (Read more
here.)
The default content of the RSS feed entries is generated from the page’s
description
front matter and .Summary
content, but you can provide your own
to override this. Simply add an excerpt in the tldr
front matter property.
To enable the RSS feed, you need to create a special .md
file that won’t
appear as regular content, but will render an extra RSS feed file. Its content
is ignored, and only its front matter is important. For example, you could
create it as content/mailchimp/_index.md
with the following contents, using YAML
front matter:
---
layout: mailchimp
outputs:
- rss
---
Now Hugo will build an extra feed at
/mailchimp/index.xml
, and you can use it to create
RSS campaigns in
MailChimp. Of
course, you can also use your normal RSS feed, but Story’s default is to put
full content into that, so it might be more than you want.
Read next: Story’s ‘talks’ feature for presentations.


NCI powers into global top 50 compute clusters
Pawsey, cloud providers drop off the radar.
by Matt JohnstonThe latest global ranking of high performance compute clusters is a mixed bag for Australia, saved by the National Computational Infrastructure’s (NCI) introduction of its new supercomputer.
Phase one of NCI’s Gadi, which was made available for user testing on Monday, stormed into 47th place based on Teraflops (Tflop/s) - the ability to execute one million million (1012) floating-point operations per second.
The Fujitsu-built cluster features 72,576 cores and has an Rmax of 4407.5 TFlop/s, with an Rpeak score of 7431.8 TFlop/s.
When completed, the NCI hopes Gadi will be among the top 25 most powerful machines globally.
The NCI’s ageing Raijin supercomputer was the next highest ranking Australian supercomputer, despite being slated for decommissioning in late January.
Raijin is currently ranked 239th in world, a slip of 66 places from the June Top500.
Australia’s other national HPC facility, the Pawsey Supercomputing Centre, has finally fallen out of the top 500 after only scraping into 454th position in the last listing. Pawsey was granted $70 million from the federal government in April 2018 to replace its Magnus supercomputer, and is currently seeking tenders for the new build.
Meanwhile, locally-based cloud providers have largely fallen out of the top 500 after making a sudden appearance in last year’s lists.
Of the three that debuted in 2018, only “Software Vendor (M)” remains, sitting in 249th spot with 57,600 cores. It’s a fall of 70 spaces compared to June’s list, and 144 spots since its debut in June last year.
IBM's Summit and Sierra machines at the US Department of Energy once again took out spots one and two respectively, followed by The National Supercomputing Center in Wuxi, China.
| Cluster | Rank | Previous Rank | Rmax (TFlop/s) | Rpeak (TFlop/s) | Cores |
| NCI Gadi Phase 1 | 47 | n/a | 4407.5 | 7431.8 | 72,576 |
| NCI Raijin | 239 | 173 | 1676.2 | 3801.4 | 87,224 |
| 'Cloud Provider' | 249 | 179 | 1649.1 | 2119.7 | 57,600 |


Small as a mouse, fast as a cheetah and available for free. NetSurf is a multi-platform web browser for RISC OS, UNIX-like platforms (including Linux) and more.
Whether you want to check your webmail, read the news or post to discussion forums, NetSurf is your lightweight gateway to the world wide web. Actively developed, NetSurf is continually evolving and improving.
Written in C, this award winning open source project features its own layout engine. It is licensed under GPL version 2.
Why choose NetSurf?
- Speed
- Efficiency lies at the heart of the NetSurf engine, allowing it to outwit the heavyweights of the web browser world. The NetSurf team continue to squeeze more speed out of their code.
- Interface innovation
- Simple to use and easy to grasp, NetSurf significantly raised the bar for user interface design on the RISC OS platform. Designed carefully by RISC OS users and developers to integrate well with the desktop, NetSurf is seen as the benchmark for future applications. NetSurf pioneered the concept of web page thumbnailing, offering an intuitive graphical tree-like view of visited web sites.
- Lean requirements
- From a modern monster PC to a humble 30MHz ARM 6 computer with 16MB of RAM, the web browser will keep you surfing the web whatever your system. Originally written for computer hardware normally found in PDAs, cable TV boxes, mobile phones and other hand-held gadgets, NetSurf is compact and low maintenance by design.
- Portable
- NetSurf can be built for a number of modern computer platforms 'out of the box'. Written in C, with portability in mind, NetSurf is developed by programmers from a wide range of computing backgrounds, ensuring it remains available for as many users as possible.
- Standards compliant
- Despite a myriad of standards to support, NetSurf makes surfing the web enjoyable and stress-free by striving for complete standards compliancy. As an actively developed project, NetSurf aims to stay abreast of new and upcoming web technologies.
See the project goals and progress page for further information on where NetSurf is headed.
Want to help?
There are always things that need doing, and not enough time in the day, so we'd be delighted if you want to help develop NetSurf. Visit the "How can I help?" page to see ideas for contributing to the project.
If you can program and you'd like to improve NetSurf, then we'd love to hear from you. Pick an area you'd like to improve or a feature you want to add and contact the developers. Also, take a look at the developer and contributor area of this site.
Latest news
- NetSurf 2.6 released 21 Sep 2010
- NetSurf 2.6 is primarily a bug fix release. It contains some improvements to page rendering, fetching & caching, memory usage, as well as some front-end specific fixes. Full details in the change log. We recommend all users upgrade.
- NetSurf 2.5 released 24 Apr 2010
- NetSurf 2.5 contains many improvements over the previous release. The major changes are the use of our brand new CSS parser and selection engine (LibCSS), and a newly designed cache for fetched content. Full details in the change log. We recommend all users upgrade.
- NetSurf at Wakefield Show 2010 14 Jan 2010
- NetSurf 2.5 is expected to be released at the Wakefield RISC OS Show. The release will focus on the CSS engine, memory usage and speed, as well as fixing bugs. NetSurf 2.5 is likely to be the last release for RISC OS.
NetSurf 2.6 features
NetSurf 2.6 is available for: RISC OS; Linux and other UNIX-like systems; and AmigaOS 4.
- General
-
- Web standards: HTML 4.01 and CSS 2.1
- Image formats: PNG, GIF, JPEG, SVG, JNG, MNG and BMP
- HTTPS for secure online transactions
- Unicode text
- Web page thumbnailing
- Local history trees
- Global history
- URL completion
- Text selection
- Scale view
- Search-as-you-type text search highlighting
- Save pages complete with images
- RISC OS only
-
- Image formats: Sprite, Drawfile and ArtWorks
- Hotlist management (bookmarks)
- Cookie viewer
- Drawfile export
Awards
NetSurf picked up another accolade, winning in the "best non-commercial product" category at The Icon Bar Awards 2009. NetSurf had previously been nominated by The Icon Bar's readers.
At Drobe Launch Pad's annual awards, NetSurf triumphed again in the category for "best non-commercial software", winning the 2008 award.


bzegrep
Find extended regular expression patterns in bzip2 compressed files using egrep.
More information: home page
- Search for extended regular expressions (supporting `?`, `+`, `{}`, `()` and `|`) in a compressed file (case-sensitive):
bzegrep "search_pattern" path/to/file
- Search for extended regular expressions (supporting `?`, `+`, `{}`, `()` and `|`) in a compressed file (case-insensitive):
bzegrep --ignore-case "search_pattern" path/to/file
- Search for lines that do not match a pattern:
bzegrep --invert-match "search_pattern" path/to/file
- Print file name and line number for each match:
bzegrep --with-filename --line-number "search_pattern" path/to/file
- Search for lines matching a pattern, printing only the matched text:
bzegrep --only-matching "search_pattern" path/to/file
- Recursively search files in a bzip2 compressed tar archive for a pattern:
bzegrep --recursive "search_pattern" path/to/file


Restaurant cooked food in kitchen with 60 cockroaches in its microwave
A restaurant was shut down after health inspectors found 60 live cockroaches inside a microwave in its kitchen.
Parallel China Express in Kansas City, Kansas was temporarily closed by the Kansas Department of Agriculture after two failed inspections in late October and early November found an apparent cockroach infestation.
The inspector found six ‘priority’ violations when they visited the restaurant on October 29, noting five live roaches in the dish area and 30 live roaches on the cooks’ line, on the wall and in equipment.
Roaches were also found in holes in the ceiling and wall, behind the steam table and in reach of the cooler. The restaurant’s latest pest invoice did not indicate any roach activity, according to the Kansas City Star.
The restaurant had a reopening inspection on the next day, but the inspector found about a dozen live roaches, although the restaurant’s manager provided a pest control invoice for October 29.
Parallel China Express had another reopening inspection on November 1 – which is when the inspector found 60 live roaches in the restaurant’s microwave.
Advertisement Advertisement
The microwave was taken outside and pest control was contacted.
According to the inspector, a ‘deep cleaning of the establishment has taken place.’
The restaurant reportedly had no violations during a November 3 reopening inspection. It was allowed to open but will be inspected later this month.


CCL mice inflammatory brain Figure hpi monocyte acute infiltration OpenUrl infection CCR TMEV neurons hippocampal monocytes virus cells analyzed hippocampus reduced levels hpi. measured -fold expression following neutrophils chemokine collected production CrossRef reporter Dunnett's genes increased number CCL-deficient infection. inoculation neuron-specific separate upregulated using IgG changes flow Abstract Ccl-RFP Syn-Cre encephalitis leukocytes one-way receptor viral FREE Text experiments hpi, role serum tissue RNA adhesion calculated ligand neuronal pairwise response results trafficking P<;. anti-CCL control findings fl/fl intracranial mean microglia model relative represents significantly ANOVA Brain-infiltrating P=. analysis data deletion goat hiCDb increase infected parent pattern primary signal source stratum used (A), ANOVA; Data ELISA GFP Neurosci. RFP Serum Theiler's associated cell central encephalitis. flox/flox gate. hours induces induction injury leukocyte motif previously uninfected values -/- CBl/ CCL, Chemokine TMEV. animals cells, compared detected exhibited infiltrating inoculated isolated mechanisms nervous neutrophil new observed present pyramidal reveal revealed robust serum, shown timepoints %CI (C) **: CA, CCL-RFP CCL: CCL:CCR D). Download E). Expression Hippocampal Howe Mayo Open P<;.; Science Web West axis bar brain, circles data-hide-link-title=""> data-icon-position="" dot early encephalomyelitis example, factor figure infection, large mortality murine notable observations performed plots protein sections sham tab timepoint timepoint. −CCL (F=., ;<;div CCL. CXCL Ccl-RFP<;sup>;fl/fl<;/sup>; Clinic Flow Fujinami However, Immunol. Inflammatory PBS PFU RT-PCR Tukey-Kramer Virus [[#xB]] absence brain-infiltrating brain. cellular chemokines conclude conditions contrast current described directly epilepsy. excitatory expression. factors groups highly host immunodepletion individual inflammation injection intracranially line monocytes, mouse neuron population prepared range rapid recruitment robustly spatial specific strain suggest systemic two-way upregulation wildtype xmlns=";http://www.w.org//xhtml";>;<;span >;-fold (A, (A-C) (B), (D, (E, (F) (F, (P=. (clone (−CCL AMPA B), Brain Buenz C-X-C CCR-deficient CCR-dependent CNS CXCR Finally, Lafrance-Corey Libbey NMDA Nile Notably, P<;.. P<;..<;/div>;<;/div>;" Patel Zeiss animal; antibody controls cytometry cytometry. decreased development diffuse downregulated effect epilepsy established experiments. expressed graph heatmapped highlight hpi: immune incubated induced inhibition lacunosum live method) mice. microarray min molecule need neural pathogen picornavirus postinfection program received recognition reduces regarding requires respond responses resulting seizures significant site suggests support system. time total virus, wt).


{# This module will display a single video thumbnail, along with the modal that will allow to play the video edit its related tags and metadata and download it. #} {% from conf import Conf %} {% for i in range(video['nbSnapshots']) %} /download/snapshot/{{video['_id'] + '/' + str(i)}} {% end %}


machine
— functions related to the hardware¶
The machine
module contains specific functions related to the hardware
on a particular board. Most functions in this module allow to achieve direct
and unrestricted access to and control of hardware blocks on a system
(like CPU, timers, buses, etc.). Used incorrectly, this can lead to
malfunction, lockups, crashes of your board, and in extreme cases, hardware
damage.
A note of callbacks used by functions and class methods of machine
module:
all these callbacks should be considered as executing in an interrupt context.
This is true for both physical devices with IDs >= 0 and “virtual” devices
with negative IDs like -1 (these “virtual” devices are still thin shims on
top of real hardware and real hardware interrupts). See Writing interrupt handlers.
Miscellaneous functions¶
-
machine.
unique_id
()¶ Returns a byte string with a unique identifier of a board/SoC. It will vary from a board/SoC instance to another, if underlying hardware allows. Length varies by hardware (so use substring of a full value if you expect a short ID). In some MicroPython ports, ID corresponds to the network MAC address.
-
machine.
time_pulse_us
(pin, pulse_level, timeout_us=1000000, /)¶ Time a pulse on the given pin, and return the duration of the pulse in microseconds. The pulse_level argument should be 0 to time a low pulse or 1 to time a high pulse.
If the current input value of the pin is different to pulse_level, the function first (*) waits until the pin input becomes equal to pulse_level, then (**) times the duration that the pin is equal to pulse_level. If the pin is already equal to pulse_level then timing starts straight away.
The function will return -2 if there was timeout waiting for condition marked (*) above, and -1 if there was timeout during the main measurement, marked (**) above. The timeout is the same for both cases and given by timeout_us (which is in microseconds).
-
machine.
rng
()¶ Return a 24-bit software generated random number.
Availability: WiPy.
Constants¶
Classes¶
- class Pin – control I/O pins
- class Signal – control and sense external I/O devices
- class ADC – analog to digital conversion
- class UART – duplex serial communication bus
- class SPI – a Serial Peripheral Interface bus protocol (master side)
- class I2C – a two-wire serial protocol
- class RTC – real time clock
- class Timer – control hardware timers
- class WDT – watchdog timer
- class SD – secure digital memory card (cc3200 port only)
- class SDCard – secure digital memory card


ImageZilla
Simplicity at its finest.
Upload File
Basic
Advanced
Blur
Brightness
Contrast
Grayscale
Hue Rotate (deg)
Invert
Saturation
Sepia
Advanced features are coming soon!


Not the response of a hero. That was a trick question, just to make sure you were paying attention. You do not have what it takes. Goodbye.
©2020 Chaalam Wilson | Binghamton University


Choose your System
Basic, Home, or Business Systems
S‑Vidia Recorders
Representing the pinnacle of surveillance technology, S‑VIDIA recorders are engineered from the ground up to deliver supreme performance and versatility for whatever you have in store. From basic set-ups to startups to corporate giants, these potent stations offer the ultimate solutions to any of your professional projects.


Next: Tilde Greater-Than-Sign-> End of Justification, Previous: Tilde T-> Tabulate, Up: FORMAT Layout Control
~mincol,colinc,minpad,padchar<str~>
This justifies the text produced by processing str within a field at least mincol columns wide. str may be divided up into segments with ~;, in which case the spacing is evenly divided between the text segments.
With no modifiers, the leftmost text segment is left justified in the field, and the rightmost text segment is right justified. If there is only one text element, as a special case, it is right justified. The : modifier causes spacing to be introduced before the first text segment; the @ modifier causes spacing to be added after the last. The minpad parameter (default 0) is the minimum number of padding characters to be output between each segment. The padding character is supplied by padchar, which defaults to the space character. If the total width needed to satisfy these constraints is greater than mincol, then the width used is mincol+k*colinc for the smallest possible non-negative integer value k. colinc defaults to 1, and mincol defaults to 0.
Note that str may include format directives. All the clauses in str are processed in order; it is the resulting pieces of text that are justified.
The ~^ directive may be used to terminate processing of the clauses prematurely, in which case only the completely processed clauses are justified.
If the first clause of a ~< is terminated with ~:; instead of ~;, then it is used in a special way. All of the clauses are processed (subject to ~^ , of course), but the first one is not used in performing the spacing and padding. When the padded result has been determined, then if it will fit on the current line of output, it is output, and the text for the first clause is discarded. If, however, the padded text will not fit on the current line, then the text segment for the first clause is output before the padded text. The first clause ought to contain a newline (such as a ~% directive). The first clause is always processed, and so any arguments it refers to will be used; the decision is whether to use the resulting segment of text, not whether to process the first clause. If the ~:; has a prefix parameter n, then the padded text must fit on the current line with n character positions to spare to avoid outputting the first clause’s text. For example, the control string
"~
can be used to print a list of items separated by commas without breaking items over line boundaries, beginning each line with ;; . The prefix parameter 1 in ~1:; accounts for the width of the comma that will follow the justified item if it is not the last element in the list, or the period if it is. If ~:; has a second prefix parameter, then it is used as the width of the line, thus overriding the natural line width of the output stream. To make the preceding example use a line width of 50, one would write
"~
If the second argument is not supplied, then format uses the line width of the destination output stream. If this cannot be determined (for example, when producing a string result), then format uses 72 as the line length.
See also Tilde Less-Than-Sign-> Logical Block.
Next: Tilde Greater-Than-Sign-> End of Justification, Previous: Tilde T-> Tabulate, Up: FORMAT Layout Control