text:
Next Meeting: April 21: Google Glass Next Installfest: TBD Latest News: Mar. 18: Google Glass at LUGOD's April meeting Page last updated: 2001 Dec 30 17:08
 The following is an archive of a post made to our 'vox-tech mailing list' by one of its subscribers. Report this post as spam: (Enter your email address)
[vox-tech] Another TeX question
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

# [vox-tech] Another TeX question

I was working on a chunk of Latex to be parsed by Template-Toolkit
to build code39 barcodes.  Someone at my work pointed out a TeX macro
which does the job (more easily, and I'm assuming it's been tested and
is accurate :) )

It works like so:

\begincodethirtynine{TEXT TO TURN TO BARCODE}\endcodethirtynine

Is there any reason anyone can think of why having the above inside a
tabular table would cause the "TEXT TO..." to actually appear as plaintext
versus being encoded into barcodes?

In other words, when I throw the above somewhere in the Latex code that
isn't in the table, it comes out fine:

|| || | || | ||| ||| |||  ||| ||  || ||

But when it's in the table, it looks like this:

|| | TEXT TO TURN TO BARCODE || |

(The barcodes on the left/right are the required starting/stopping codes,
which the TeX macro is somehow getting to appear just fine)

Here's a snippet:

\begin{tabular*}{3.25in}[t]{|llll|r@{:}}%
...
\multicolumn{4}{|l|}{\begincodethirtynine{ TEST }\endcodethirtynine}&\\%
...
\end{tabular*}%

Thx for any tips!

-bill!

 LUGOD Group on LinkedIn Sign up for LUGOD event announcements Your email address: LUGOD Group on Facebook 'Like' LUGOD on Facebook:

 Hosting provided by: Sunset Systems Sunset Systems offers preconfigured Linux systems, remote system administration and custom software development. LUGOD: Linux Users' Group of Davis PO Box 2082, Davis, CA 95617 Contact Us LUGOD is a 501(c)7 non-profit organization based in Davis, California and serving the Sacramento area. "Linux" is a trademark of Linus Torvalds. Sponsored in part by: For a significant contribution towards our projector, and a generous donation to allow us to continue meeting at the Davis Library.

format: plain


text:
#### Extractive Summarization via Weighted Dissimilarity and Importance Aligned Key Iterative Algorithm

We present importance aligned key iterative algorithm for extractive summarization that is faster than conventional algorithms keeping its accuracy. The computational complexity of our algorithm is O($SNlogN$) to summarize original $N$ sentences into final $S$ sentences. Our algorithm maximizes the weighted dissimilarity defined by the product of importance and cosine dissimilarity so that the summary represents the document and at the same time the sentences of the summary are not similar to each other. The weighted dissimilarity is heuristically maximized by iterative greedy search and binary search to the sentences ordered by importance. We finally show a benchmark score based on summarization of customer reviews of products, which highlights the quality of our algorithm comparable to human and existing algorithms. We provide the source code of our algorithm on github https://github.com/qhapaq-49/imakita .


text:
# Evaluating limits

• September 22nd 2008, 04:50 AM
Cyberman86
Evaluating limits
(Punch) I got stuck on this two, they don't look that bad but they are using Sin and i don't know exactly what to do.

lim (sin (3x) ) / over X
x->0

-------------------------------------------------------------

lim -2 / over sin (x)
x->0

as x approaches zero from the right
• September 22nd 2008, 04:55 AM
mr fantastic
Quote:

Originally Posted by Cyberman86
(Punch) I got stuck on this two, they don't look that bad but they are using Sin and i don't know exactly what to do.

lim (sin (3x) ) / over X
x->0

[snip]

$= 3 \lim_{x \rightarrow 0}\frac{\sin (3x)}{3x}$.

You know $\lim_{t \rightarrow 0} \frac{\sin (t)}{t} = 1$, right?
• September 22nd 2008, 04:58 AM
mr fantastic
Quote:

Originally Posted by Cyberman86
[snip]
lim -2 / over sin (x)
x->0

as x approaches zero from the right

This is very sloppy but makes the point: $\frac{-2}{0^+} = - \infty$


text:
# Thread: How to solve a complex exponential equation with one unknown???

1. ## How to solve a complex exponential equation with one unknown???

I need to solve this equation for 'B'. I am having trouble rearranging the equation to achieve a 'B=' answer. Can someone help me rearrange this equation to solve for B?

0=((DCRMg) - (DCRMgAl)) ∗ e^(-B∗((ρMg)+(ρAl)))+ ((DCRMgAl )- (DCRAl ))∗e^(-2∗B∗(ρMg))+((DCRAl) - (DCRMg)) e^(-B∗((ρMg)+(ρMgAl)))

2. ## Re: How to solve a complex exponential equation with one unknown???

replacing various constants with single letters, this is $a- be^x+ ce^{2x}+ de^x= 0$

where $a= (DCRM_g- DCRM_gIa)e^{\rho RAI}$, $b= (DCRM_gAI- DCRAI)$, $c= (DCRAI- DCRM_g)e^{\rho M_gAI}$, $d= (DCRAI- DCRM_g)e^{\rho M_gAI}$ and $x= B(\rho M_g)$.

If we further write $y= e^x$ that equation reduces to $cy^2+ (d- b)y+ a= 0$ which can be solved for y using the quadratic formula. Once we have $y= e^x$, $x= B(\rho M_g)= ln(y)$ and then $B= \frac{ln(y)}{\rho M_g}$.

3. ## Re: How to solve a complex exponential equation with one unknown???

Thank you for your help HallsofIvy. Could you possibly re-write the equation as 'B=.......' I am struggling with this....
'

4. ## Re: How to solve a complex exponential equation with one unknown???

I have been recently told that this equation must be solved using Excel Solver. I have no idea how to use this program in order to calculate B.
I have created an excel formula relative to the above equation, but I am stuck at this point. Are you able to show me how you would solve the equation for B in Excel Solver?

=(B50-C50)*EXP(-B*($H$44+$I$44))+(C50-D50)*EXP((-2*B($H$44)))+(D50-B50)*EXP((-B($H$44+$J$44)))

5. ## Re: How to solve a complex exponential equation with one unknown???

You can use exact solutions given here in your Excel module.


text:
Lemma 70.10.2. Let $k$ be a field with algebraic closure $\overline{k}$. Let $X$ be a quasi-separated algebraic space over $k$.

1. If there exists a field extension $k \subset K$ such that $X_ K$ is a scheme, then $X_{\overline{k}}$ is a scheme.

2. If $X$ is quasi-compact and there exists a field extension $k \subset K$ such that $X_ K$ is a scheme, then $X_{k'}$ is a scheme for some finite separable extension $k'$ of $k$.

Proof. Since every algebraic space is the union of its quasi-compact open subspaces, we see that the first part of the lemma follows from the second part (some details omitted). Thus we assume $X$ is quasi-compact and we assume given an extension $k \subset K$ with $K_ K$ representable. Write $K = \bigcup A$ as the colimit of finitely generated $k$-subalgebras $A$. By Limits of Spaces, Lemma 68.5.11 we see that $X_ A$ is a scheme for some $A$. Choose a maximal ideal $\mathfrak m \subset A$. By the Hilbert Nullstellensatz (Algebra, Theorem 10.33.1) the residue field $k' = A/\mathfrak m$ is a finite extension of $k$. Thus we see that $X_{k'}$ is a scheme. If $k' \supset k$ is not separable, let $k' \supset k'' \supset k$ be the subextension found in Fields, Lemma 9.14.6. Since $k'/k''$ is purely inseparable, by Lemma 70.10.1 the algebraic space $X_{k''}$ is a scheme. Since $k''|k$ is separable the proof is complete. $\square$

## Post a comment

Your email address will not be published. Required fields are marked.

In your comment you can use Markdown and LaTeX style mathematics (enclose it like $\pi$). A preview option is available if you wish to see how it works out (just click on the eye in the toolbar).

Unfortunately JavaScript is disabled in your browser, so the comment preview function will not work.

All contributions are licensed under the GNU Free Documentation License.

In order to prevent bots from posting comments, we would like you to prove that you are human. You can do this by filling in the name of the current tag in the following input field. As a reminder, this is tag 0B84. Beware of the difference between the letter 'O' and the digit '0'.


text:
# Finding the mach number of an aircraft

A supersonic aircraft is flying parallel to the ground. When the aircraft is directly overhead, an observer sees a rocket fired from the aircraft. 10.4 s later the observer hears the sonic boom, followed 3.37 s later by the sound of the rocket engine. What is the mach number of the aircraft?

I think I was too simple in my assumptions, but I used trig to find the half-angle of the mach cone. I used the adjacent side as 10.4, and the opposite side as 13.77, and took the inverse tan. I got an angle of 52.9375.

Then I used this to find the mach number by using this equation:

Mach # = 1/sin($$\theta$$)

=1/sin(52.9375) = 1.25317

Related Introductory Physics Homework Help News on Phys.org
Those 2 sides are not the 2 sides next to the 90 degree angle, so taking an inverse tan was wrong.

I calculated the distance from the point from where the sonic boom is first heard to the point where the rocket is released with pythagorars. (the other 2 sides are 13.77c and 10.4c where c is the speed of sound).
This distance is covered by the plane in 3.37s, so it's equal to 3.37v, where v is the speed of the plane.

I'm still a little confused by this. I am trying to set the triangle up and can't get past this diagram...I know you said it was wrong, but I can't picture the triangle you are describing.

I tried to attach a drawing I made, I hope it works

#### Attachments

• 1.6 KB Views: 377
Your triangle is actually Ok, (and mine wasn't) but to get $\tan{\phi}$ you need to find the length of the sides in meters, and not in seconds.
The vertical distance is $13.77 v_{sound}$ and the horizontal distance is $10.4 v_{plane}$

When you have an expression for $\tan{\phi}$, you can combine that with

$$\frac { v_{plane} } { v_{sound} } = \frac {1} {\sin{\phi}}$$


text:
# Trying to wire in LED to show cooker element is on/off

Hi I'm a mechanical engineer so please bear with me. I'm trying to wire in an LED to show whether a cooker element is on or off. Looking at the diagrams below, the easiest way to do this would be to wire an LED into the Aditec MKA-120 outputs between 06 and 07. Would it be that simple?

The images of the diagrams are below:

Internal switchboard: https://imgur.com/mpMYTDU External switchboard: https://imgur.com/GmqQpgk Aditec MKA-120 controller: https://imgur.com/uZ0zAjH Electric diagram for cooker: https://imgur.com/uOERoYz

• Welcome to EE.SE, Charlie. Your question hasn't attracted any comments or answers after an hour. That's unusual for this site so I suggest that the question full of links and no photos may be asking a bit much from your readers. You can embed photos - I think there's a limit of two for new users - and you could format the links properly using the [Description](http://website.com/folder/page.php) syntax (or use the link button on the editor toolbar). Make it easy for your readers. – Transistor Jan 24 at 22:35
• @Transistor thanks for the heads up. I will try redo it. – charlieS Jan 24 at 23:22
• could you use a neon indicator instead of an LED? I have some NOS that is rated 240VAC – jsolarski Jan 25 at 0:33

I doubt very much that an LED is appropriate in this case. All wiring except the temperature sensor is AC line wiring. In particular,06 connects to L1, the active AC line. Anything you connect to this will operate from 230 VAC. In this case, 07 is in series with the heating elements -81 and -82, so placing an LED across these contacts will result in 230 VAC appearing across the LED when the heater is not active.

While it's true you can do this, keep 3 things in mind.

1) You must provide current limiting to the LED, and this will dissipate much more power than the LED.

2) You must provide a diode to protect the LED from the reverse voltage (about 320 volts maximum) which will appear 50 times per second.

3) Because you will have connected directly to line, unless you know very clearly what you are doing, you stand a distinct chance that your modification will cause the cooker to become live, and for your body (or that of someone you know) to complete the circuit. This is called "auto-Darwination" and it is not a good thing.

• Won't the reverse voltage only appear 25 times per second? – Simeon R Jan 25 at 0:27
• @SimeonR - Nope. UK power is 50 Hz. That is, one positive half-cycle and one negative half-cycle every 20 msec. – WhatRoughBeast Jan 25 at 0:29
• Fantastic explanation, love the last bit. Few questions if you don't mind. Can I use a neon indicator instead, as mentioned in the comments above and not worry about current limiting and diodes? Also, you say 230VAC will appear across the LED when the heater is not active, but how can that be possible if the switch is between 05 and 06 and only supplies power to the heating coil when it switches to 06 and 07? If the switch is between 05 and 06, won't the circuit between 06 and 07 be open and any light wired between them is off? Or have I misunderstood the diagram? Thank you – charlieS Jan 28 at 17:56
• @charlieS - 1) Yes, a neon indicator is an excellent choice, but you do have to worry about a current limiting resistor. However, many neon indicators will have the resistor built in - check the data sheet. No diodes needed, since a neon works with both polarities. 2) No, 05 is not connected to anything. When 05 is switched to 06, there will be ~230 VAC between 06 and 07, which will light a neon. The voltage will be reduced a bit by the resistance of the heater elements, but that will be negligable for the currents a neon indicator uses. – WhatRoughBeast Jan 28 at 23:35
• I realise I thought one thing but wrote something else. If I put a light between 6 and 7, I am essentially short circuiting between 6 and 7. I need to put an LED in series with 7 and the coils so when the coils are powered, the light comes on! – charlieS Jan 30 at 1:24


text:
Top

# Pressure Formula

Force and Pressure are the concepts acting simultaneously on the body in motion. The force is nothing but the interaction between any two bodies or the push or pull between them while the pressure tells how much is the push or pull the body experiences when force is applied over a particular area.

Pressure
is the force exerted by one body on the another. It is denoted by P.

Pressure is expressed as force per unit area given as

Where,
F = Force applied by the body,
A = Total area of the object.

Pressure Formula is given by

Where,
h is the height,
$\rho$ is density,
g is gravity.

Pressure Formula is used to calculate pressure, force, area, density, height and gravity if some of these quantities are given. Pressure is expressed in Pascal (Pa).

 Related Calculators Pressure Calculator gauge pressure to absolute pressure calculator air pressure drop calculator boiling point pressure calculator

## Pressure Problems

Below are problems based on pressure which may be helpful for you.

### Solved Examples

Question 1: A 60 Kg girl wearing high heel shoes balances on a single heel. The heel is circular with a diameter of 1.5 cm. Find the pressure exerted by the heel on the horizontal floor?
Solution:

Given: Mass m = 60 kg,
Radius r = $\frac{D}{2}$ = $\frac{1.5 \times 10^{-2}}{2}$ m
Pressure is given by P = $\frac{F}{A}$
Force F = mg and Area A = $\pi$ r2
P = $\frac{mg}{\pi r^{2}}$
= $\frac{60 \times 9.8}{3.142 \times (0.75 \times 10^{-2})^{2}}$
= 3.32 $\times$ 106 Pa.

Question 2: A tank is filled with water is of height 1 m. Calculate the pressure exerted on the bottom of the tank.
(Density of water = 1000 kg / m3, Acceleration due to gravity = 9.8 m/s2).
Solution:

Given: Density of water = 1000 kg / m3,
Acceleration due to gravity = 9.8 m/s2
The pressure is given by P = $\rho$ $\times$ g $\times$ h
= 1000 $\times$ 9.8 $\times$ 1m
= 9800 Pascal.

 More topics in Pressure Formula Gas Pressure Formula
*AP and SAT are registered trademarks of the College Board.


text:
# Protect Tomcat Web App

## Get Started

If you haven’t read the get started article, please read it first, it described the basic structure and concepts of Protector4J.

## GUI Tool

Execute protector4j-ui[.exe] in the folder of Protector4J, you will see the interface below

For users of macOS, please just double click the Protector4J.app

If you have got the license, you can click the login button on the top-right corner and type your account information. Although, without the license, you can still try this tool.

### Choose app type

Click the “Tomcat Application” button on the app types page.

### Choose war/jar files to protect

Choose the war/jar files to protect, you can add single or multi war/jar files here.

### Options

Protect all classes

if this option is selected, all the classes will be encrypted

Protect the specified classes

If this option is selected, you can choose which classes to encrypt in the next step

Protect inner jars

If this option is checked, the classes in the inner jars will be encrypted too.

### Choose classes to protect

If you selected “Protect the specified classes”, you should type the classes that need to protect here manually, but also the classes need to exclude from the encryption

You can input the full class name like:

If you want to encrypt all the classes in the package, you can input a wildcard case like:

One * means all the classes in the package, but exclude the classes in sub packages

if you want to encrypt all the classes in the package including the classes in sub packages, please use the wildcard case like:

The class names or the package names above apply to all jar files, just like the classpath. We have the class information in the jars mixed together, and any classes in any jar files that meet the conditions will be encrypted or excluded, if you selected “Protect inner jars”, the classes in the inner jars will be processed too.

Although it needs to type the classes information manually, but we provide the class info tree on the right, you can view the struct there, and there is a context menu that could help you to edit the class list.

### Output options

On this page, you can specify the Java version, the Tomcat version, the output folder and target platforms. After this is done, click the “Next” button on the bottom, it will start the encryption task.

#### KeySeed

The seed to generate the encryption key, the same key seed will generate the same encryption key. If you want jars generated from diffrent encryption task can be used together, you can input the same keySeed. This feature is only valid for licensed user.

### Encryption process

It will take some time to finish the encryption process. After it is done, you can check the result in the output folder.

### Check the result

After the encryption process complete, please go to the output folder to check the result. There is a tomcat folder with the web apps and the custom java runtime in it.

### Run the encrypted app

Please go to the tomcat’s bin directory, and use the startup.sh or startup.bat shell script to launch it.

#### On Windows

Every encryption task will request a new and unique key. The files encrypted in different task can not be used together unless providing the key seed.

### Create Windows Service

If you need to create the windows service, please refer to here

## CLI Tool

### The configuration of task file

It needs to specify a task file as an argument to the command-line tool.

Please find the task.tomcat.yml in the task-templates directory, copy and modify a new one.

#### The account information

If you have purchased this tool, you would have got your account information including the email address and the password for the license. Please type them in the appropriate fields, the value of the password field should be the md5 value of the password, not the password itself. or you can leave the email and the password fields empty, just have a try.

#### Specify the jars and the classes need to be encrypted.

jarsPath

The jarsPath field is an array, which you could specify one or multi jar/war files that need to be processed in the encryption work.

or

protectAll

If this value is true, all the classes in the jar will be encrypted.

protectInnerJars

If this value is true, the classes in the inner jars will be encrypted too.

classesToProtect

In this field, you can specify the classes that need to encrypt. it can be a full class name, or wildcard case ones

or

* means all the classes in the package, but exclude the classes in the sub package

** means all the classes in the package including the classes in the sub package.

If the protectAll is true, this field will be ignored.

if you are using the version before 1.8.0, please add WEB-INF.classes prefix for each item for the classes in WEB-INF/classes, like WEB-INF.classes.vlinx.test.TestClass1

exclude

In this field, you can specify the classes to exclude from encryption, the format is the same as classesToProtect field.

#### javaVersion

The java versions supported now are Java 8 and Java 11, you can type “java-8” for Java 8 and type “java-11” for Java 11

#### tomcatVersion

The tomcat versions supported now are Tomcat 8.5 and Tomcat 9.0. You can type “tomcat-8.5” for Tomcat 8.5, “tomcat-9” for Tomcat 9.0

#### tempFolder

The temp folder for the files generated during the encryption process, after the task completed, the files in the temp folder will be cleaned up.

#### outputFolder

The encrypted app and the custom Java runtime will be placed into the output folder.

#### includeJavaFX

Whether include the JavaFX framework

#### keySeed

The seed to generate the encryption key, the same key seed will generate the same encryption key. If you want to jars generated from diffrent encryption task can be used together, you can input the same keySeed. This feature is only valid for licensed user.

#### targetPlatforms

This field is an array, the available values are [linux64, win64, mac, linux32, win32], you can set one or multi target platforms according to the requirement. Or leave it empty, if you just want to generate the app for current platform.

On windows, currently only supports win64 and win32 as the target platforms.

or

### Execute the encryption process

Go to the folder of Protector4J and execute the command below to run the encryption process

On Linux or macOS

For users of macOS, you can find the cli tool in Protector4J.app/Contents/protector4j-mac

On Windows

You can execute protector4j --help to see the detail arguments.

### Check the result

After the encryption process complete, please go to the output folder to check the result. There is a tomcat folder with the web apps and the custom java runtime in it.

### Run the encrypted app

Please go to the tomcat’s bin directory, and use the startup.sh or startup.bat to launch it.

#### For Windows

Every encryption task will request a new and unique key. The files encrypted in different task can not be used together unless providing the key seed.

### Create Windows Service

If you need to create the windows service, please refer to here

## Create Windows Service

### Create service

There is a “create-service.bat” script in tomcat/bin folder, if you need to create the windows service, just cd to the tomcat/bin folder then execute

Please execute this script as Administrator, it will create a Windows service then start it

### Delete service

If you need to delete the service, cd to tomcat/bin folder too, then execute

this script should run with Administrator too


text:
# Partial differential equation - DSolve gives no output, but solution exists

I have trouble obtaining solution for equation using DSolve:

My mathematica code is given by:

DSolve[\[Kappa]^2 *T + (1/2)*f[G, T] - (1/2) G *D[f[G, T], G] + T* D[f[G, T], T] - (2/(n - 1))*G ^2 D[D[f[G, T], G], G] - 3 n^2 (T/\[Rho]0)^(2/3 n) - (3 n)/(2 (n - 1))*G * T D[D[f[G, T], T], G] == 0, f[G, T], {G, T}]

Using this lines gives me no output (output is exactly my dsolve command) - from what i found on stackexchange it means that exact solution doesn't exist. Hoverver solution for this equation is given by: where $$d_i$$ are integration constants and $$\chi_i$$ are some combinations of $$d$$'s, $$n,\rho_0$$ and $$\kappa$$

How to solve this equation with DSolve command? Is there any mathematical trick to manipulate this equation?

Article [ https://link.springer.com/article/10.1140/epjc/s10052-016-4502-1 ] where this equation is given and solved doesn't gives any additional information about behaviour of function $$f(G,T)$$ or any additional equations - exept that the $$n>0$$

p[t_] := Refine[(po* t^(-3 n)), Assumptions -> n > 0];
G[t_] := Refine[(24*n^3/t^4)*(n - 1), Assumptions -> n > 0];
T[t_] := Refine[(p[t]), Assumptions -> n > 0];

eq = Refine[
k^2*T[t] + (1/2)*f[G[t], T[t]] - (1/2)*G[t]*D[f[G[t], T[t]], G] +
T[t]*D[f[G[t], T[t]], T[t]] - (2/(n - 1))*
G[t]^2 D[f[G[t], T[t]], {G[t], 2}] -
3 n^2 (T[t]/po)^(2/3 n) - (3 n/(2 (n - 1)))*G[t]*T[t] *
D[D[f[G[t], T[t]], {T[t], 1}], {G[t], 1}],
Assumptions -> {k \[Element] Reals, po \[Element] Reals, n > 0,
G[t] \[Element] Reals, T[t] \[Element] Reals,
f[G[t], T[t]] \[Element] Reals, t > 0}]

s1 = DSolve[{eq == 0}, f[G[t], T[t]], {G[t], T[t]}] /. Rule -> Equal

• You cannot solve PDE in this way. I mean, this won't give anything helpful when solving PDE, AFAIK. Just consider the simplest example: {DSolve[3 D[y[x1, x2], x1] + 5 D[y[x1, x2], x2] == x1 , y[x1, x2], {x2}], DSolve[3 D[y[x1, x2], x1] + 5 D[y[x1, x2], x2] == x1 , y[x1, x2], {x1}]}. – xzczd Apr 6 '19 at 16:22
• i looked up the article so i will edit this answer – Alrubaie Apr 6 '19 at 16:30
• you need to notice and define your G & T because they depend on time and they cancel some terms in the PDE, My problem i don't know how to define a function F with variable T&G that depend on function T&G with another variable t time! – Alrubaie Apr 6 '19 at 16:34
• So problem is with definitions? $G,T$ arent independent variables so i have to define them as functions dependent on $t$ and then, i have to solve it w.r.t $T$ and $G$? – StarPlatinumZaWardo Apr 6 '19 at 16:38
• i think so that's it – Alrubaie Apr 6 '19 at 16:40


text:
Deals Of The Week - hours only!Up to 80% off on all courses and bundles.-Close
Introduction
FIRST_VALUE, LAST_VALUE, NTH_VALUE
20. LAST_VALUE(x) with different sorting
Summary

## Instruction

Great! Let's do one more exercise

## Exercise

For each statistics rows with website_id = 1, show the day, the number of users, the number of users on the last day and the difference between these two values.

### Stuck? Here's a hint!

Use LAST_VALUE(users), but sort by the day.


text:
1. Engineering
2. Mechanical Engineering
3. hint can you solve it with applying the hint and...

# Question: hint can you solve it with applying the hint and...

###### Question details

Hint:

Can you solve it with applying the hint and step by step?


text:
MLIR

Multi-Level IR Compiler Framework

Defining Dialect Attributes and Types

This document describes how to define dialect attributes and types.

LangRef Refresher ¶

Before diving into how to define these constructs, below is a quick refresher from the MLIR LangRef.

Attributes ¶

Attributes are the mechanism for specifying constant data on operations in places where a variable is never allowed - e.g. the comparison predicate of a arith.cmpi operation, or the underlying value of a arith.constant operation. Each operation has an attribute dictionary, which associates a set of attribute names to attribute values.

Types ¶

Every SSA value, such as operation results or block arguments, in MLIR has a type defined by the type system. MLIR has an open type system with no fixed list of types, and there are no restrictions on the abstractions they represent. For example, take the following Arithmetic AddI operation:

  %result = arith.addi %lhs, %rhs : i64

It takes two input SSA values (%lhs and %rhs), and returns a single SSA value (%result). The inputs and outputs of this operation are of type i64, which is an instance of the Builtin IntegerType.

Attributes and Types ¶

The C++ Attribute and Type classes in MLIR (like Ops, and many other things) are value-typed. This means that instances of Attribute or Type are passed around by-value, as opposed to by-pointer or by-reference. The Attribute and Type classes act as wrappers around internal storage objects that are uniqued within an instance of an MLIRContext.

The structure for defining Attributes and Types is nearly identical, with only a few differences depending on the context. As such, a majority of this document describes the process for defining both Attributes and Types side-by-side with examples for both. If necessary, a section will explicitly call out any distinct differences.

Adding a new Attribute or Type definition ¶

As described above, C++ Attribute and Type objects in MLIR are value-typed and essentially function as helpful wrappers around an internal storage object that holds the actual data for the type. Similarly to Operations, Attributes and Types are defined declaratively via TableGen; a generic language with tooling to maintain records of domain-specific information. It is highly recommended that users review the TableGen Programmer’s Reference for an introduction to its syntax and constructs.

Starting the definition of a new attribute or type simply requires adding a specialization for either the AttrDef or TypeDef class respectively. Instances of the classes correspond to unqiue Attribute or Type classes.

Below show cases an example Attribute and Type definition. We generally recommend defining Attribute and Type classes in different .td files to better encapsulate the different constructs, and define a proper layering between them. This recommendation extends to all of the MLIR constructs, including Interfaces, Operations, etc.

// Include the definition of the necessary tablegen constructs for defining
// our types.
include "mlir/IR/AttrTypeBase.td"

// It's common to define a base classes for types in the same dialect. This
// removes the need to pass in the dialect for each type, and can also be used
// to define a few fields ahead of time.
class MyDialect_Type<string name, string typeMnemonic, list<Trait> traits = []>
: TypeDef<My_Dialect, name, traits> {
let mnemonic = typeMnemonic;
}

// Here is a simple definition of an "integer" type, with a width parameter.
def My_IntegerType : MyDialect_Type<"Integer", "int"> {
let summary = "Integer type with arbitrary precision up to a fixed limit";
let description = [{
Integer types have a designated bit width.
}];
/// Here we defined a single parameter for the type, which is the bitwidth.
let parameters = (ins "unsigned":$width); /// Here we define the textual format of the type declaratively, which will /// automatically generate parser and printer logic. This will allow for /// instances of the type to be output as, for example: /// /// !my.int<10> // a 10-bit integer. /// let assemblyFormat = "<$width >";

/// Indicate that our type will add additional verification to the parameters.
let genVerifyDecl = 1;
}

Below is an example of an Attribute:

// Include the definition of the necessary tablegen constructs for defining
// our attributes.
include "mlir/IR/AttrTypeBase.td"

// It's common to define a base classes for attributes in the same dialect. This
// removes the need to pass in the dialect for each attribute, and can also be used
// to define a few fields ahead of time.
class MyDialect_Attr<string name, string attrMnemonic, list<Trait> traits = []>
: AttrDef<My_Dialect, name, traits> {
let mnemonic = attrMnemonic;
}

// Here is a simple definition of an "integer" attribute, with a type and value parameter.
def My_IntegerAttr : MyDialect_Attr<"Integer", "int"> {
let summary = "An Attribute containing a integer value";
let description = [{
An integer attribute is a literal attribute that represents an integral
value of the specified integer type.
}];
/// Here we've defined two parameters, one is a "self" type parameter, and the
/// other is the integer value of the attribute. The self type parameter is
/// specially handled by the assembly format.
let parameters = (ins AttributeSelfTypeParameter<"">:$type, "APInt":$value);

/// Here we've defined a custom builder for the type, that removes the need to pass
/// in an MLIRContext instance; as it can be infered from the type.
let builders = [
AttrBuilderWithInferredContext<(ins "Type":$type, "const APInt &":$value), [{
return $_get(type.getContext(), type, value); }]> ]; /// Here we define the textual format of the attribute declaratively, which will /// automatically generate parser and printer logic. This will allow for /// instances of the attribute to be output as, for example: /// /// #my.int<50> : !my.int<32> // a 32-bit integer of value 50. /// /// Note that the self type parameter is not included in the assembly format. /// Its value is derived from the optional trailing type on all attributes. let assemblyFormat = "<$value >";

/// Indicate that our attribute will add additional verification to the parameters.
let genVerifyDecl = 1;

/// Indicate to the ODS generator that we do not want the default builders,
/// as we have defined our own simpler ones.
let skipDefaultBuilders = 1;
}

Class Name ¶

The name of the C++ class which gets generated defaults to <classParamName>Attr or <classParamName>Type for attributes and types respectively. In the examples above, this was the name template parameter that was provided to MyDialect_Attr and MyDialect_Type. For the definitions we added above, we would get C++ classes named IntegerType and IntegerAttr respectively. This can be explicitly overridden via the cppClassName field.

Documentation ¶

The summary and description fields allow for providing user documentation for the attribute or type. The summary field expects a simple single-line string, with the description field used for long and extensive documentation. This documentation can be used to generate markdown documentation for the dialect and is used by upstream MLIR dialects.

Mnemonic ¶

The mnemonic field, i.e. the template parameters attrMnemonic and typeMnemonic we specified above, are used to specify a name for use during parsing. This allows for more easily dispatching to the current attribute or type class when parsing IR. This field is generally optional, and custom parsing/printing logic can be added without defining it, though most classes will want to take advantage of the convenience it provides. This is why we added it as a template parameter in the examples above.

Parameters ¶

The parameters field is a variable length list containing the attribute or type’s parameters. If no parameters are specified (the default), this type is considered a singleton type (meaning there is only one possible instance). Parameters in this list take the form: "c++Type":$paramName. Parameter types with a C++ type that requires allocation when constructing the storage instance in the context require one of the following: • Utilize the AttrParameter or TypeParameter classes instead of the raw “c++Type” string. This allows for providing custom allocation code when using that parameter. StringRefParameter and ArrayRefParameter are examples of common parameter types that require allocation. • Set the genAccessors field to 1 (the default) to generate accessor methods for each parameter (e.g. int getWidth() const in the Type example above). • Set the hasCustomStorageConstructor field to 1 to generate a storage class that only declares the constructor, allowing for you to specialize it with whatever allocation code necessary. AttrParameter, TypeParameter, and AttrOrTypeParameter ¶ As hinted at above, these classes allow for specifying parameter types with additional functionality. This is generally useful for complex parameters, or those with additional invariants that prevent using the raw C++ class. Examples include documentation (e.g. the summary and syntax field), the C++ type, a custom allocator to use in the storage constructor method, a custom comparator to decide if two instances of the parameter type are equal, etc. As the names may suggest, AttrParameter is intended for parameters on Attributes, TypeParameter for Type parameters, and AttrOrTypeParameters for either. Below is an easy parameter pitfall, and highlights when to use these parameter classes. let parameters = (ins "ArrayRef<int>":$dims);

The above seems innocuous, but it is often a bug! The default storage constructor blindly copies parameters by value. It does not know anything about the types, meaning that the data of this ArrayRef will be copied as-is and is likely to lead to use-after-free errors when using the created Attribute or Type if the underlying does not have a lifetime exceeding that of the MLIRContext. If the lifetime of the data can’t be guaranteed, the ArrayRef<int> requires allocation to ensure that its elements reside within the MLIRContext, e.g. with dims = allocator.copyInto(dims).

Here is a simple example for the exact situation above:

def ArrayRefIntParam : TypeParameter<"::llvm::ArrayRef<int>", "Array of int"> {
let allocator = "$_dst =$_allocator.copyInto($_self);"; } The parameter can then be used as so: ... let parameters = (ins ArrayRefIntParam:$dims);

Below contains descriptions for other various available fields:

The allocator code block has the following substitutions:

• $_allocator is the TypeStorageAllocator in which to allocate objects. • $_dst is the variable in which to place the allocated data.

The comparator code block has the following substitutions:

• $_lhs is an instance of the parameter type. • $_rhs is an instance of the parameter type.

MLIR includes several specialized classes for common situations:

• APFloatParameter for APFloats.

• StringRefParameter<descriptionOfParam> for StringRefs.

• ArrayRefParameter<arrayOf, descriptionOfParam> for ArrayRefs of value types.

• SelfAllocationParameter<descriptionOfParam> for C++ classes which contain a method called allocateInto(StorageAllocator &allocator) to allocate itself into allocator.

• ArrayRefOfSelfAllocationParameter<arrayOf, descriptionOfParam> for arrays of objects which self-allocate as per the last specialization.

• AttributeSelfTypeParameter is a special AttrParameter that represents parameters derived from the optional trailing type on attributes.

Traits ¶

Similarly to operations, Attribute and Type classes may attach Traits that provide additional mixin methods and other data. Traits may be attached via the trailing template argument, i.e. the traits list parameter in the example above. See the main Trait documentation for more information on defining and using traits.

Interfaces ¶

Attribute and Type classes may attach Interfaces to provide an virtual interface into the Attribute or Type. Interfaces are added in the same way as Traits, by using the traits list template parameter of the AttrDef or TypeDef. See the main Interface documentation for more information on defining and using interfaces.

Builders ¶

For each attribute or type, there are a few builders(get/getChecked) automatically generated based on the parameters of the type. These are used to construct instances of the corresponding attribute or type. For example, given the following definition:

def MyAttrOrType : ... {
let parameters = (ins "int":$intParam); }  The following builders are generated: // Builders are named get, and return a new instance for a given set of parameters. static MyAttrOrType get(MLIRContext *context, int intParam); // If genVerifyDecl is set to 1, the following method is also generated. This method // is similar to get, but is failable and on error will return nullptr. static MyAttrOrType getChecked(function_ref<InFlightDiagnostic()> emitError, MLIRContext *context, int intParam);  If these autogenerated methods are not desired, such as when they conflict with a custom builder method, the skipDefaultBuilders field may be set to 1 to signal that the default builders should not be generated. Custom builder methods ¶ The default builder methods may cover a majority of the simple cases related to construction, but when they cannot satisfy all of an attribute or type’s needs, additional builders may be defined via the builders field. The builders field is a list of custom builders, either using TypeBuilder for types or AttrBuilder for attributes, that are added to the attribute or type class. The following will showcase several examples for defining builders for a custom type MyType, the process is the same for attributes except that attributes use AttrBuilder instead of TypeBuilder. def MyType : ... { let parameters = (ins "int":$intParam);

let builders = [
TypeBuilder<(ins "int":$intParam)>, TypeBuilder<(ins CArg<"int", "0">:$intParam)>,
TypeBuilder<(ins CArg<"int", "0">:$intParam), [{ // Write the body of the get builder inline here. return Base::get($_ctxt, intParam);
}]>,
TypeBuilderWithInferredContext<(ins "Type":$typeParam), [{ // This builder states that it can infer an MLIRContext instance from // its arguments. return Base::get(typeParam.getContext(), ...); }]>, TypeBuilder<(ins "int":$intParam), [{}], "IntegerType">,
];
}

In this example, we provide several different convenience builders that are useful in different scenarios. The ins prefix is common to many function declarations in ODS, which use a TableGen dag. What follows is a comma-separated list of types (quoted string or CArg) and names prefixed with the $ sign. The use of CArg allows for providing a default value to that argument. Let’s take a look at each of these builders individually The first builder will generate the declaration of a builder method that looks like:  let builders = [ TypeBuilder<(ins "int":$intParam)>,
];

class MyType : /*...*/ {
/*...*/
static MyType get(::mlir::MLIRContext *context, int intParam);
};

This builder is identical to the one that will be automatically generated for MyType. The context parameter is implicitly added by the generator, and is used when building the Type instance (with Base::get). The distinction here is that we can provide the implementation of this get method. With this style of builder definition only the declaration is generated, the implementor of MyType will need to provide a definition of MyType::get.

The second builder will generate the declaration of a builder method that looks like:

  let builders = [
TypeBuilder<(ins CArg<"int", "0">:$intParam)>, ];  class MyType : /*...*/ { /*...*/ static MyType get(::mlir::MLIRContext *context, int intParam = 0); };  The constraints here are identical to the first builder example except for the fact that intParam now has a default value attached. The third builder will generate the declaration of a builder method that looks like:  let builders = [ TypeBuilder<(ins CArg<"int", "0">:$intParam), [{
// Write the body of the get builder inline here.
return Base::get($_ctxt, intParam); }]>, ];  class MyType : /*...*/ { /*...*/ static MyType get(::mlir::MLIRContext *context, int intParam = 0); }; MyType MyType::get(::mlir::MLIRContext *context, int intParam) { // Write the body of the get builder inline here. return Base::get(context, intParam); }  This is identical to the second builder example. The difference is that now, a definition for the builder method will be generated automatically using the provided code block as the body. When specifying the body inline, $_ctxt may be used to access the MLIRContext * parameter.

The fourth builder will generate the declaration of a builder method that looks like:

  let builders = [
TypeBuilderWithInferredContext<(ins "Type":$typeParam), [{ // This builder states that it can infer an MLIRContext instance from // its arguments. return Base::get(typeParam.getContext(), ...); }]>, ];  class MyType : /*...*/ { /*...*/ static MyType get(Type typeParam); }; MyType MyType::get(Type typeParam) { // This builder states that it can infer an MLIRContext instance from its // arguments. return Base::get(typeParam.getContext(), ...); }  In this builder example, the main difference from the third builder example there is that the MLIRContext parameter is no longer added. This is because the builder used TypeBuilderWithInferredContext implies that the context parameter is not necessary as it can be inferred from the arguments to the builder. The fifth builder will generate the declaration of a builder method with a custom return type, like:  let builders = [ TypeBuilder<(ins "int":$intParam), [{}], "IntegerType">,
]

class MyType : /*...*/ {
/*...*/
static IntegerType get(::mlir::MLIRContext *context, int intParam);

};

This generates a builder declaration the same as the first three examples, but the return type of the builder is user-specified instead of the attribute or type class. This is useful for defining builders of attributes and types that may fold or canonicalize on construction.

Parsing and Printing ¶

If a mnemonic was specified, the hasCustomAssemblyFormat and assemblyFormat fields may be used to specify the assembly format of an attribute or type. Attributes and Types with no parameters need not use either of these fields, in which case the syntax for the Attribute or Type is simply the mnemonic.

For each dialect, two “dispatch” functions will be created: one for parsing and one for printing. These static functions placed alongside the class definitions and have the following function signatures:

static ParseResult generatedAttributeParser(DialectAsmParser& parser, StringRef *mnemonic, Type attrType, Attribute &result);
static LogicalResult generatedAttributePrinter(Attribute attr, DialectAsmPrinter& printer);

static ParseResult generatedTypeParser(DialectAsmParser& parser, StringRef *mnemonic, Type &result);
static LogicalResult generatedTypePrinter(Type type, DialectAsmPrinter& printer);

The above functions should be added to the respective in your Dialect::printType and Dialect::parseType methods, or consider using the useDefaultAttributePrinterParser and useDefaultTypePrinterParser ODS Dialect options if all attributes or types define a mnemonic.

The mnemonic, hasCustomAssemblyFormat, and assemblyFormat fields are optional. If none are defined, the generated code will not include any parsing or printing code and omit the attribute or type from the dispatch functions above. In this case, the dialect author is responsible for parsing/printing in the respective Dialect::parseAttribute/Dialect::printAttribute and Dialect::parseType/Dialect::printType methods.

Using hasCustomAssemblyFormat¶

Attributes and types defined in ODS with a mnemonic can define an hasCustomAssemblyFormat to specify custom parsers and printers defined in C++. When set to 1 a corresponding parse and print method will be declared on the Attribute or Type class to be defined by the user.

For Types, these methods will have the form:

• static Type MyType::parse(AsmParser &parser)

• Type MyType::print(AsmPrinter &p) const

For Attributes, these methods will have the form:

• static Attribute MyAttr::parse(AsmParser &parser, Type attrType)

• Attribute MyAttr::print(AsmPrinter &p) const

Using assemblyFormat¶

Attributes and types defined in ODS with a mnemonic can define an assemblyFormat to declaratively describe custom parsers and printers. The assembly format consists of literals, variables, and directives.

• A literal is a keyword or valid punctuation enclosed in backticks, e.g. keyword or <.
• A variable is a parameter name preceded by a dollar sign, e.g. $param0, which captures one attribute or type parameter. • A directive is a keyword followed by an optional argument list that defines special parser and printer behaviour. // An example type with an assembly format. def MyType : TypeDef<My_Dialect, "MyType"> { // Define a mnemonic to allow the dialect's parser hook to call into the // generated parser. let mnemonic = "my_type"; // Define two parameters whose C++ types are indicated in string literals. let parameters = (ins "int":$count, "AffineMap":$map); // Define the assembly format. Surround the format with less < and greater // > so that MLIR's printer uses the pretty format. let assemblyFormat = "<$count , map = $map >"; }  The declarative assembly format for MyType results in the following format in the IR: !my_dialect.my_type<42, map = affine_map<(i, j) -> (j, i)>>  Parameter Parsing and Printing ¶ For many basic parameter types, no additional work is needed to define how these parameters are parsed or printed. • The default printer for any parameter is $_printer << $_self, where $_self is the C++ value of the parameter and $_printer is an AsmPrinter. • The default parser for a parameter is FieldParser<$cppClass>::parse($_parser), where $cppClass is the C++ type of the parameter and $_parser is an AsmParser. Printing and parsing behaviour can be added to additional C++ types by overloading these functions or by defining a parser and printer in an ODS parameter class. Example of overloading: using MyParameter = std::pair<int, int>; AsmPrinter &operator<<(AsmPrinter &printer, MyParameter param) { printer << param.first << " * " << param.second; } template <> struct FieldParser<MyParameter> { static FailureOr<MyParameter> parse(AsmParser &parser) { int a, b; if (parser.parseInteger(a) || parser.parseStar() || parser.parseInteger(b)) return failure(); return MyParameter(a, b); } };  Example of using ODS parameter classes: def MyParameter : TypeParameter<"std::pair<int, int>", "pair of ints"> { let printer = [{$_printer << $_self.first << " * " <<$_self.second }];
let parser = [{ [&] -> FailureOr<std::pair<int, int>> {
int a, b;
if ($_parser.parseInteger(a) ||$_parser.parseStar() ||
$_parser.parseInteger(b)) return failure(); return std::make_pair(a, b); }() }]; }  A type using this parameter with the assembly format <$myParam > will look as follows in the IR:

!my_dialect.my_type<42 * 24>

Non-POD Parameters ¶

Parameters that aren’t plain-old-data (e.g. references) may need to define a cppStorageType to contain the data until it is copied into the allocator. For example, StringRefParameter uses std::string as its storage type, whereas ArrayRefParameter uses SmallVector as its storage type. The parsers for these parameters are expected to return FailureOr<$cppStorageType>. To add a custom conversion between the cppStorageType and the C++ type of the parameter, parameters can override convertFromStorage, which by default is "$_self" (i.e., it attempts an implicit conversion from cppStorageType).

Optional and Default-Valued Parameters ¶

An optional parameter can be omitted from the assembly format of an attribute or a type. An optional parameter is omitted when it is equal to its default value. Optional parameters in the assembly format can be indicated by setting defaultValue, a string of the C++ default value. If a value for the parameter was not encountered during parsing, it is set to this default value. If a parameter is equal to its default value, it is not printed. The comparator field of the parameter is used, but if one is not specified, the equality operator is used.

When using OptionalParameter, the default value is set to the C++ default-constructed value for the C++ storage type. For example, Optional<int> will be set to std::nullopt and Attribute will be set to nullptr. The presence of these parameters is tested by comparing them to their “null” values.

An optional group is a set of elements optionally printed based on the presence of an anchor. Only optional parameters or directives that only capture optional parameters can be used in optional groups. The group in which the anchor is placed is printed if it is present, otherwise the other one is printed. If a directive that captures more than one optional parameter is used as the anchor, the optional group is printed if any of the captured parameters is present. For example, a custom directive may only be used as an optional group anchor if it captures at least one optional parameter.

Suppose parameter a is an IntegerAttr.

( ( $a^ ) ) : (x)?  In the above assembly format, if a is present (non-null), then it will be printed as (5 : i32). If it is not present, it will be x. Directives that are used inside optional groups are allowed only if all captured parameters are also optional. An optional parameter can also be specified with DefaultValuedParameter, which specifies that a parameter should be omitted when it is equal to some given value. let parameters = (ins DefaultValuedParameter<"Optional<int>", "5">:$a)
let mnemonic = "default_valued";
let assemblyFormat = "(< $a^ >)?";  Which will look like: !test.default_valued // a = 5 !test.default_valued<10> // a = 10  For optional Attribute or Type parameters, the current MLIR context is available through $_ctxt. E.g.

DefaultValuedParameter<"IntegerType", "IntegerType::get($_ctxt, 32)">  The value of parameters that appear before the default-valued parameter in the parameter declaration list are available as substitutions. E.g. let parameters = (ins "IntegerAttr":$value,
DefaultValuedParameter<"Type", "$value.getType()">:$type
);

Attribute Self Type Parameter ¶

An attribute optionally has a trailing type after the assembly format of the attribute value itself. MLIR parses over the attribute value and optionally parses a colon-type before passing the Type into the dialect parser hook.

dialect-attribute  ::= # dialect-namespace < attr-data >
(: type)?
| # alias-name pretty-dialect-sym-body? (: type)?

AttributeSelfTypeParameter is an attribute parameter specially handled by the assembly format generator. Only one such parameter can be specified, and its value is derived from the trailing type. This parameter’s default value is NoneType::get($_ctxt). In order for the type to be printed by MLIR, however, the attribute must implement TypedAttrInterface. For example, // This attribute has only a self type parameter. def MyExternAttr : AttrDef<MyDialect, "MyExtern", [TypedAttrInterface]> { let parameters = (AttributeSelfTypeParameter<"">:$type);
let mnemonic = "extern";
let assemblyFormat = "";
}

This attribute can look like:

#my_dialect.extern // none
#my_dialect.extern : i32
#my_dialect.extern : tensor<4xi32>
#my_dialect.extern : !my_dialect.my_type

Assembly Format Directives ¶

Attribute and type assembly formats have the following directives:

• params: capture all parameters of an attribute or type.
• qualified: mark a parameter to be printed with its leading dialect and mnemonic.
• struct: generate a “struct-like” parser and printer for a list of key-value pairs.
• custom: dispatch a call to user-define parser and printer functions
• ref: in a custom directive, references a previously bound variable
params Directive ¶

This directive is used to refer to all parameters of an attribute or type, except for the attribute self type (which is handled separately from normal parameters). When used as a top-level directive, params generates a parser and printer for a comma-separated list of the parameters. For example:

def MyPairType : TypeDef<My_Dialect, "MyPairType"> {
let parameters = (ins "int":$a, "int":$b);
let mnemonic = "pair";
let assemblyFormat = "< params >";
}

In the IR, this type will appear as:

!my_dialect.pair<42, 24>

The params directive can also be passed to other directives, such as struct, as an argument that refers to all parameters in place of explicitly listing all parameters as variables.

qualified Directive ¶

This directive can be used to wrap attribute or type parameters such that they are printed in a fully qualified form, i.e., they include the dialect name and mnemonic prefix.

For example:

def OuterType : TypeDef<My_Dialect, "MyOuterType"> {
let parameters = (ins MyPairType:$inner); let mnemonic = "outer"; let assemblyFormat = "< pair :$inner >";
}
def OuterQualifiedType : TypeDef<My_Dialect, "MyOuterQualifiedType"> {
let parameters = (ins MyPairType:$inner); let mnemonic = "outer_qual"; let assemblyFormat = "< pair : qualified($inner) >";
}

In the IR, the types will appear as:

!my_dialect.outer<pair : <42, 24>>
!my_dialect.outer_qual<pair : !mydialect.pair<42, 24>>

If optional parameters are present, they are not printed in the parameter list if they are not present.

struct Directive ¶

The struct directive accepts a list of variables to capture and will generate a parser and printer for a comma-separated list of key-value pairs. If an optional parameter is included in the struct, it can be elided. The variables are printed in the order they are specified in the argument list but can be parsed in any order. For example:

def MyStructType : TypeDef<My_Dialect, "MyStructType"> {
let parameters = (ins StringRefParameter<>:$sym_name, "int":$a, "int":$b, "int":$c);
let mnemonic = "struct";
let assemblyFormat = "< $sym_name -> struct($a, $b,$c) >";
}

In the IR, this type can appear with any permutation of the order of the parameters captured in the directive.

!my_dialect.struct<"foo" -> a = 1, b = 2, c = 3>
!my_dialect.struct<"foo" -> b = 2, c = 3, a = 1>

Passing params as the only argument to struct makes the directive capture all the parameters of the attribute or type. For the same type above, an assembly format of < struct(params) > will result in:

!my_dialect.struct<b = 2, sym_name = "foo", c = 3, a = 1>

The order in which the parameters are printed is the order in which they are declared in the attribute’s or type’s parameter list.

custom and ref directive ¶

The custom directive is used to dispatch calls to user-defined printer and parser functions. For example, suppose we had the following type:

let parameters = (ins "int":$foo, "int":$bar);
let assemblyFormat = "custom<Foo>($foo) custom<Bar>($bar, ref($foo))";  The custom directive custom<Foo>($foo) will in the parser and printer respectively generate calls to:

LogicalResult parseFoo(AsmParser &parser, int &foo);
void printFoo(AsmPrinter &printer, int foo);

As you can see, by default parameters are passed into the parse function by reference. This is only possible if the C++ type is default constructible. If the C++ type is not default constructible, the parameter is wrapped in a FailureOr. Therefore, given the following definition:

let parameters = (ins "NotDefaultConstructible":$foobar); let assemblyFormat = "custom<Fizz>($foobar)";

It will generate calls expecting the following signature for parseFizz:

LogicalResult parseFizz(AsmParser &parser, FailureOr<NotDefaultConstructible> &foobar);

A previously bound variable can be passed as a parameter to a custom directive by wrapping it in a ref directive. In the previous example, $foo is bound by the first directive. The second directive references it and expects the following printer and parser signatures: LogicalResult parseBar(AsmParser &parser, int &bar, int foo); void printBar(AsmPrinter &printer, int bar, int foo);  More complex C++ types can be used with the custom directive. The only caveat is that the parameter for the parser must use the storage type of the parameter. For example, StringRefParameter expects the parser and printer signatures as: LogicalResult parseStringParam(AsmParser &parser, std::string &value); void printStringParam(AsmPrinter &printer, StringRef value);  The custom parser is considered to have failed if it returns failure or if any bound parameters have failure values afterwards. A string of C++ code can be used as a custom directive argument. When generating the custom parser and printer call, the string is pasted as a function argument. For example, parseBar and printBar can be re-used with a constant integer: let parameters = (ins "int":$bar);
let assemblyFormat = [{ custom<Bar>($foo, "1") }];  The string is pasted verbatim but with substitutions for $_builder and $_ctxt. String literals can be used to parameterize custom directives. Verification ¶ If the genVerifyDecl field is set, additional verification methods are generated on the class. • static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError, parameters...) These methods are used to verify the parameters provided to the attribute or type class on construction, and emit any necessary diagnostics. This method is automatically invoked from the builders of the attribute or type class. • AttrOrType getChecked(function_ref<InFlightDiagnostic()> emitError, parameters...) As noted in the Builders section, these methods are companions to get builders that are failable. If the verify invocation fails when these methods are called, they return nullptr instead of asserting. Storage Classes ¶ Somewhat alluded to in the sections above is the concept of a “storage class” (often abbreviated to “storage”). Storage classes contain all of the data necessary to construct and unique a attribute or type instance. These classes are the “immortal” objects that get uniqued within an MLIRContext and get wrapped by the Attribute and Type classes. Every Attribute or Type class has a corresponding storage class, that can be accessed via the protected getImpl() method. In most cases the storage class is auto generated, but if necessary it can be manually defined by setting the genStorageClass field to 0. The name and namespace (defaults to detail) can additionally be controlled via the The storageClass and storageNamespace fields. Defining a storage class ¶ User defined storage classes must adhere to the following: • Inherit from the base type storage class of AttributeStorage or TypeStorage respectively. • Define a type alias, KeyTy, that maps to a type that uniquely identifies an instance of the derived type. For example, this could be a std::tuple of all of the storage parameters. • Provide a construction method that is used to allocate a new instance of the storage class. • static Storage *construct(StorageAllocator &allocator, const KeyTy &key) • Provide a comparison method between an instance of the storage and the KeyTy. • bool operator==(const KeyTy &) const • Provide a method to generate the KeyTy from a list of arguments passed to the uniquer when building an Attribute or Type. (Note: This is only necessary if the KeyTy cannot be default constructed from these arguments). • static KeyTy getKey(Args...&& args) • Provide a method to hash an instance of the KeyTy. (Note: This is not necessary if an llvm::DenseMapInfo<KeyTy> specialization exists) • static llvm::hash_code hashKey(const KeyTy &) • Provide a method to generate the KeyTy from an instance of the storage class. • static KeyTy getAsKey() Let’s look at an example: /// Here we define a storage class for a ComplexType, that holds a non-zero /// integer and an integer type. struct ComplexTypeStorage : public TypeStorage { ComplexTypeStorage(unsigned nonZeroParam, Type integerType) : nonZeroParam(nonZeroParam), integerType(integerType) {} /// The hash key for this storage is a pair of the integer and type params. using KeyTy = std::pair<unsigned, Type>; /// Define the comparison function for the key type. bool operator==(const KeyTy &key) const { return key == KeyTy(nonZeroParam, integerType); } /// Define a hash function for the key type. /// Note: This isn't necessary because std::pair, unsigned, and Type all have /// hash functions already available. static llvm::hash_code hashKey(const KeyTy &key) { return llvm::hash_combine(key.first, key.second); } /// Define a construction function for the key type. /// Note: This isn't necessary because KeyTy can be directly constructed with /// the given parameters. static KeyTy getKey(unsigned nonZeroParam, Type integerType) { return KeyTy(nonZeroParam, integerType); } /// Define a construction method for creating a new instance of this storage. static ComplexTypeStorage *construct(StorageAllocator &allocator, const KeyTy &key) { return new (allocator.allocate<ComplexTypeStorage>()) ComplexTypeStorage(key.first, key.second); } /// Construct an instance of the key from this storage class. KeyTy getAsKey() const { return KeyTy(nonZeroParam, integerType); } /// The parametric data held by the storage class. unsigned nonZeroParam; Type integerType; };  Mutable attributes and types ¶ Attributes and Types are immutable objects uniqued within an MLIRContext. That being said, some parameters may be treated as “mutable” and modified after construction. Mutable parameters should be reserved for parameters that can not be reasonably initialized during construction time. Given the mutable component, these parameters do not take part in the uniquing of the Attribute or Type. TODO: Mutable parameters are currently not supported in the declarative specification of attributes and types, and thus requires defining the Attribute or Type class in C++. Defining a mutable storage ¶ In addition to the base requirements for a storage class, instances with a mutable component must additionally adhere to the following: • The mutable component must not participate in the storage KeyTy. • Provide a mutation method that is used to modify an existing instance of the storage. This method modifies the mutable component based on arguments, using allocator for any newly dynamically-allocated storage, and indicates whether the modification was successful. • LogicalResult mutate(StorageAllocator &allocator, Args ...&& args) Let’s define a simple storage for recursive types, where a type is identified by its name and may contain another type including itself. /// Here we define a storage class for a RecursiveType that is identified by its /// name and contains another type. struct RecursiveTypeStorage : public TypeStorage { /// The type is uniquely identified by its name. Note that the contained type /// is _not_ a part of the key. using KeyTy = StringRef; /// Construct the storage from the type name. Explicitly initialize the /// containedType to nullptr, which is used as marker for the mutable /// component being not yet initialized. RecursiveTypeStorage(StringRef name) : name(name), containedType(nullptr) {} /// Define the comparison function. bool operator==(const KeyTy &key) const { return key == name; } /// Define a construction method for creating a new instance of the storage. static RecursiveTypeStorage *construct(StorageAllocator &allocator, const KeyTy &key) { // Note that the key string is copied into the allocator to ensure it // remains live as long as the storage itself. return new (allocator.allocate<RecursiveTypeStorage>()) RecursiveTypeStorage(allocator.copyInto(key)); } /// Define a mutation method for changing the type after it is created. In /// many cases, we only want to set the mutable component once and reject /// any further modification, which can be achieved by returning failure from /// this function. LogicalResult mutate(StorageAllocator &, Type body) { // If the contained type has been initialized already, and the call tries // to change it, reject the change. if (containedType && containedType != body) return failure(); // Change the body successfully. containedType = body; return success(); } StringRef name; Type containedType; };  Type class definition ¶ Having defined the storage class, we can define the type class itself. Type::TypeBase provides a mutate method that forwards its arguments to the mutate method of the storage and ensures the mutation happens safely. class RecursiveType : public Type::TypeBase<RecursiveType, Type, RecursiveTypeStorage> { public: /// Inherit parent constructors. using Base::Base; /// Creates an instance of the Recursive type. This only takes the type name /// and returns the type with uninitialized body. static RecursiveType get(MLIRContext *ctx, StringRef name) { // Call into the base to get a uniqued instance of this type. The parameter // (name) is passed after the context. return Base::get(ctx, name); } /// Now we can change the mutable component of the type. This is an instance /// method callable on an already existing RecursiveType. void setBody(Type body) { // Call into the base to mutate the type. LogicalResult result = Base::mutate(body); // Most types expect the mutation to always succeed, but types can implement // custom logic for handling mutation failures. assert(succeeded(result) && "attempting to change the body of an already-initialized type"); // Avoid unused-variable warning when building without assertions. (void) result; } /// Returns the contained type, which may be null if it has not been /// initialized yet. Type getBody() { return getImpl()->containedType; } /// Returns the name. StringRef getName() { return getImpl()->name; } };  Extra declarations ¶ The declarative Attribute and Type definitions try to auto-generate as much logic and methods as possible. With that said, there will always be long-tail cases that won’t be covered. For such cases, extraClassDeclaration and extraClassDefinition can be used. Code within the extraClassDeclaration field will be copied literally to the generated C++ Attribute or Type class. Code within extraClassDefinition will be added to the generated source file inside the class’s C++ namespace. The substitution $cppClass will be replaced by the Attribute or Type’s C++ class name.

Note that these are mechanisms intended for long-tail cases by power users; for not-yet-implemented widely-applicable cases, improving the infrastructure is preferable.

Registering with the Dialect ¶

Once the attributes and types have been defined, they must then be registered with the parent Dialect. This is done via the addAttributes and addTypes methods. Note that when registering, the full definition of the storage classes must be visible.

void MyDialect::initialize() {
/// Add the defined attributes to the dialect.


text:
# Involvement of Importin-4 in the Transport of Transition Protein 2 into the Spermatid Nucleus

Pradeepa, MM and Manjunatha, S and Sathish, V and Agrawal, Shipra and Rao, MRS (2008) Involvement of Importin-4 in the Transport of Transition Protein 2 into the Spermatid Nucleus. In: Molecular and Cellular Biology, 28 (13). pp. 4331-4341.

Full text not available from this repository. (Request a copy)

## Abstract

Mammalian spermiogenesis is characterized by a unique chromatin-remodeling process in which histones are replaced by transition protein 1 (TP1), TP2, and TP4, which are further replaced by protamines. We showed previously that the import of TP2 into the haploid spermatid nucleus requires the components of cytosol and ATP. We have now arried out a detailed analysis to characterize the molecular components underlying the nuclear translocation of TP2. Real-time PCR analysis of the expression of different importins in testicular germ cells revealed that importin-4 and importin- \beta 3 are significantly up-regulated in tetraploid and haploid germ cells. We carried out physical interaction studies as well as an in vitro nuclear transport assay using recombinant TP2 and the nuclear localization ignal of TP2 (TP2NLS) fused to glutathione S-transferase in digitonin-permeabilized, haploid, round spermatids and identified importin-4 to be involved in the import of TP2. A three-dimensional model of the importin-4 protein was generated using the crystal structure of importin- \beta 1 as the template. Molecular docking simulations of $TP2_{NLS}$ with the importin-4 structure led to the identification of a $TP2_{NLS}$ binding pocket spanning the three helices (helices 21 to 23) of importin-4, which was experimentally confirmed by in vitro interaction and import studies with different deletion mutants of importin-4. In contrast to TP2, TP1 import was accomplished through a passive diffusion process.

Item Type: Journal Article Copyright of this article belongs to American Society for Microbiology. Division of Biological Sciences > Biochemistry 21 Jul 2008 27 Aug 2008 13:37 http://eprints.iisc.ernet.in/id/eprint/15181


text:
Calculus

# Differentiability: Level 3 Challenges

$\large{x^3+x^2-5x-1=0}$

Let $$\alpha,\beta,\gamma$$ be the roots of the equation above.

Evaluate $$\left\lfloor \alpha \right\rfloor +\left\lfloor \beta \right\rfloor +\left\lfloor \gamma \right\rfloor$$.

###### Image Credit: Wikimedia N.Mori.

Let $$f$$ be a twice differentiable function satisfying $$f(1)=1, f(2)=4, f(3)=9$$, then :

Let $$0<a<b<\frac { \pi }{ 2 }$$. If $$f\left( x \right) =\left| \begin{matrix} \sin { x } & \sin { a } & \sin { b } \\ \cos { x } & \cos { a } & \cos { b } \\ \tan { x } & \tan { a } & \tan { b } \end{matrix} \right|$$ , then minimum possible number of roots of $$f'\left( x \right) =0$$ lying in $$(a,b)$$ is:

Find the equation of common tangent to the curves $$y^2=8x$$ and $$xy=-1$$?

The curve of $$\sin { \left( ax \right) }$$ is tangent to the curve of $$\sin { \left( x \right) }$$ at $$x=\frac { 5\pi }{2 }$$.

If minimum positive value of $$a$$ can be expressed as $$\frac { A }{B }$$ for co-prime $$A$$ and $$B$$, then find $$A+B$$.

×