R features

  1. Well-developed and effective programming language – R is a simple yet powerful language specifically designed for data analysis and statistical computing.

  2. Efficient data handling and storage – R provides robust structures for handling and storing large datasets efficiently.

  3. Rich set of operators – R includes a variety of operators for performing calculations on arrays, lists, vectors, and matrices.

  4. Comprehensive tools for data analysis – R offers numerous built-in functions and packages that support a wide range of data analysis tasks.

  5. Advanced graphical capabilities – R supports both basic and advanced graphical techniques for data visualization, aiding in better interpretation of results.

  6. Extensive packages for advanced applications – R has a vast collection of packages for data mining, machine learning, and big data analytics, making it highly suitable for modern data science workflows.

R Environment Workspace Description

Figure: R Environment Workspace

  1. R Script/File – This is where users write and save their R code. It allows you to edit, run, and manage reusable scripts for analysis and automation.

  2. Environment – Displays the current workspace, including all the variables, data frames, functions, and loaded objects that are active in your session.

  3. History – Keeps a record of all the R commands executed during the session, allowing users to review and reuse previous commands easily.

  4. Console – The command-line interface where users can directly enter and execute R commands and immediately see the output or results.

  5. Files – Provides access to the directory structure of your computer so that you can browse, open, or manage files and folders.

  6. Plots – Displays visual output generated from data visualizations, such as graphs and charts created using R’s plotting functions.

  7. Packages – Shows the list of R packages installed and loaded in the session. Users can install new packages or load/unload existing ones from here.

  8. Help – Offers documentation and help for R functions, packages, and commands. Users can search for and view detailed descriptions, usage, and examples.

The step-by-step instructions to download and install R programming and RStudio:

Step 1: Download and Install R

  1. Go to the CRAN R Project Website https://cran.r-project.org ,

  2. Choose your Operating System : Click on “Download R for Windows”, “Download R for macOS”, or “Download R for Linux” depending on your system.

  3. Download the R Installer: For Windows: Click “base” > then click “Download R x.x.x for Windows” (e.g., R 4.3.1). For macOS: Click the link for the latest .pkg installer

  4. Run the Installer: Open the downloaded file, Follow the instructions to install R (default settings are usually fine)

Step 2: Download and Install RStudio

  1. Go to the RStudio Website https://posit.co/download/rstudio-desktop/ ,Download RStudio Desktop (Free).

  2. Click on “Download RStudio Desktop for [Your OS]”. It will redirect you to the appropriate installer for Windows, macOS, or Linux

  3. Install RStudio

  4. Run the downloaded installer: Follow the on-screen instructions.

Packages and Libraries

R provides access to a vast ecosystem of packages, with more than 7,769 packages available through CRAN (Comprehensive R Archive Network). These packages extend R’s functionality and support a wide range of tasks in data science and statistical computing. Some of the key capabilities offered by R packages include:

Data visualization: Tools for creating charts, graphs, and interactive plots (e.g., ggplot2, plotly).

Data statistics and exploration: Functions to summarize, explore, and understand data distributions and relationships.

Data transformation: Utilities for cleaning, reshaping, and manipulating data (e.g., dplyr, tidyr).

Outlier detection: Methods for identifying and handling anomalies in data.

Feature selection: Techniques to select important variables that contribute most to prediction or classification.

Dimension reduction: Tools like PCA (Principal Component Analysis) to reduce the number of variables while preserving data structure.

Classification: Algorithms for supervised learning and assigning data to categories (e.g., decision trees, SVM).

Clustering: Unsupervised learning techniques for grouping similar data points (e.g., k-means, hierarchical clustering).

Regression validation: Tools to evaluate the performance of regression models.

Classification validation: Functions to assess accuracy, precision, recall, and F1-score of classification models.

Clustering validation: Metrics to validate the quality and effectiveness of clustering results (e.g., silhouette score).

Installing and Loading Packages in R Using RStudio GUI

Figure: Installing and Loading Packages in R

  1. Open RStudio: Start by opening the RStudio application on your computer.

  2. Install a Package Using the GUI: Go to the “Packages” tab in the bottom-right pane.

  3. Click on the “Install” button (usually at the top left of the “Packages” tab). A dialog box will appear. In the “Packages” field, type the name of the package you want to install (e.g., ggplot2). Make sure the checkbox “Install dependencies” is selected.

  4. Click the “Install” button. RStudio will now download and install the package from CRAN.

  5. Load a Package Using the GUI: After installation, stay in the “Packages” tab. Find the installed package in the list (e.g., ggplot2). Tick the checkbox next to the package name to load it into your R session.

Steps to Install and Load Packages in R

  1. Installing a Package: To install a package in R, you use the install.packages() function. This step downloads the package from CRAN and installs it on your system.

Example: install.packages(“ggplot2”)

This command installs the ggplot2 package, which is widely used for data visualization.

  1. Loading a Package : Once a package is installed, you need to load it into your current R session using the library( ) function.

Example: library(ggplot2)

This command loads the ggplot2 package so that you can use its functions.

  1. Check if a Package is Already Installed : You can check if a package is already installed using the require() function or by checking the installed packages list.

Example: require(ggplot2)

If the package is not installed, require() will return FALSE.

  1. Install and Load Multiple Packages You can install and load multiple packages using a vector and a loop.

Example:

packages <- c("dplyr", "tidyr", "ggplot2")

install.packages(packages)   # Install all

lapply(packages, library, character.only = TRUE)  # Load all
  1. Viewing Installed Packages : You can view all installed packages using:
installed.packages()
  1. Update Packages (Optional) : To update all installed packages:
update.packages()

Certainly! Here’s a detailed explanation of the basic data types in R, with proper sentences and examples for each:


Basic Data Types in R

R is a powerful programming language used for statistical computing and data analysis. It supports several basic data types, which are fundamental for handling and manipulating data. These data types include: numeric, integer, complex, character (string), and logical (boolean).


1. Numeric

  • The numeric data type represents real numbers (i.e., numbers with decimal points).
  • It is the default type for numbers in R unless specified otherwise.

Example:

x <- 3.14
class(x)  # Output: "numeric"
[1] "numeric"

Here, x is a numeric variable storing the value 3.14.


2. Integer

  • An integer is a whole number (without a decimal point).
  • In R, you must use an L suffix to explicitly define an integer.

Example:

y <- 10L
class(y)  # Output: "integer"
[1] "integer"

The L tells R to treat 10 as an integer rather than a numeric (which would be a double).


3. Complex

  • The complex data type represents complex numbers, which have both a real and imaginary part (e.g., 1 + 2i).
  • Useful in mathematical computations involving complex arithmetic.

Example:

z <- 2 + 3i
class(z)  # Output: "complex"
[1] "complex"

Here, z is a complex number with a real part 2 and an imaginary part 3i.


4. Character (String)

  • The character data type is used to store text or string values, such as words, phrases, or any sequence of characters.
  • Character data must be enclosed in either single ' or double " quotes.

Example:

name <- "Srinivas"
class(name)  # Output: "character"
[1] "character"

Here, "Srinivas" is a character string.


5. Logical (Boolean)

  • The logical data type stores TRUE or FALSE values.
  • This type is often used in conditions, comparisons, and filtering data.

Example:

is_senior <- TRUE
class(is_senior)  # Output: "logical"
[1] "logical"
age <- 25
age > 30  # Output: FALSE
[1] FALSE

Here, is_senior is a logical variable. The expression age > 30 also returns a logical value.


Summary Table

Data Type Description Example
Numeric Decimal or floating-point numbers x <- 5.6
Integer Whole numbers with L suffix y <- 100L
Complex Numbers with real + imaginary parts z <- 3 + 4i
Character Text or strings name <- "R User"
Logical Boolean values (TRUE or FALSE) flag <- FALSE


Arithmetic Operators in R

R provides a set of arithmetic operators that are used to perform basic mathematical operations on numeric values, vectors, or variables. These operators include addition, subtraction, multiplication, division, modulus, and exponentiation.


1. Addition (+)

The + operator is used to add two or more numbers.

Example:

a <- 10
b <- 5
result <- a + b
print(result)  # Output: 15
[1] 15

In this example, 10 and 5 are added to get 15.


2. Subtraction (-)

The - operator is used to subtract one number from another.

Example:

a <- 10
b <- 5
result <- a - b
print(result)  # Output: 5
[1] 5

Here, 5 is subtracted from 10 to get 5.


3. Multiplication (*)

The * operator is used to multiply numbers.

Example:

a <- 10
b <- 5
result <- a * b
print(result)  # Output: 50
[1] 50

The multiplication of 10 and 5 results in 50.


4. Division (/)

The / operator is used to divide one number by another.

Example:

a <- 10
b <- 5
result <- a / b
print(result)  # Output: 2
[1] 2

Here, 10 divided by 5 gives the result 2.


5. Modulus (%%)

The %% operator gives the remainder when one number is divided by another.

Example:

a <- 10
b <- 3
result <- a %% b
print(result)  # Output: 1
[1] 1

When 10 is divided by 3, the remainder is 1.


6. Exponentiation (^)

The ^ operator is used to raise a number to the power of another.

Example:

a <- 2
b <- 3
result <- a ^ b
print(result)  # Output: 8
[1] 8

In this case, 2 raised to the power of 3 equals 8.


Summary Table

Operator Description Example Result
+ Addition 5 + 3 8
- Subtraction 5 - 3 2
* Multiplication 5 * 3 15
/ Division 6 / 3 2
%% Modulus (remainder) 10 %% 3 1
^ Exponentiation 2 ^ 4 16

These arithmetic operators are frequently used in mathematical computations, statistical analysis, and data manipulation tasks in R.


Relational Operators in R

Relational operators in R are used to compare two values or expressions. The result of a relational operation is always a logical value: either TRUE or FALSE. These are essential for decision-making and conditional programming.


1. < (Less than)

This operator checks whether the value on the left is less than the value on the right.

Example:

a <- 10
b <- 20
c <- a < b
print(c)  # Output: TRUE
[1] TRUE

Explanation: Since 10 is less than 20, the result is TRUE.


2. > (Greater than)

Checks if the value on the left is greater than the value on the right.

Example:

a <- 10
b <- 20
c <- a > b
print(c)  # Output: FALSE
[1] FALSE

Explanation: 10 is not greater than 20, so the result is FALSE.


3. <= (Less than or equal to)

Checks if the left-hand side is less than or equal to the right-hand side.

Example:

a <- 10
b <- 10
c <- a <= b
print(c)  # Output: TRUE
[1] TRUE

Explanation: 10 is equal to 10, so it satisfies the condition.


4. >= (Greater than or equal to)

Checks if the value on the left is greater than or equal to the one on the right.

Example:

a <- 15
b <- 10
c <- a >= b
print(c)  # Output: TRUE
[1] TRUE

Explanation: 15 is greater than 10, so the result is TRUE.


5. == (Equal to)

Tests whether two values are equal.

Example:

a <- 10
b <- 10
c <- a == b
print(c)  # Output: TRUE
[1] TRUE

Explanation: Both values are equal, so it returns TRUE.


6. != (Not equal to)

Checks if the two values are not equal.

Example:

a <- 10
b <- 20
c <- a != b
print(c)  # Output: TRUE
[1] TRUE

Explanation: 10 and 20 are not equal, so the result is TRUE.


Summary Table

Operator Description Example Result
< Less than 10 < 20 TRUE
> Greater than 10 > 20 FALSE
<= Less than or equal to 10 <= 10 TRUE
>= Greater than or equal to 15 >= 10 TRUE
== Equal to 10 == 10 TRUE
!= Not equal to 10 != 20 TRUE

These relational operators are particularly useful in if-else conditions, filtering data, and loop control in R programming.


Logical Operators in R

Logical operators are used to combine or modify logical values (TRUE or FALSE) in R. They are especially useful in conditional statements, data filtering, and vectorized operations.


1. ! (Logical NOT)

This operator reverses the logical state of its operand. If a condition is TRUE, applying ! will make it FALSE, and vice versa.

Example:

x <- TRUE
result <- !x
print(result)  # Output: FALSE
[1] FALSE

Explanation: The value of x is TRUE. The ! operator flips it to FALSE.


2. & (Element-wise Logical AND)

This operator performs a logical AND element by element on two logical vectors. It returns TRUE if both elements are TRUE.

Example:

a <- c(TRUE, FALSE, TRUE)
b <- c(TRUE, TRUE, FALSE)
result <- a & b
print(result)  # Output: TRUE FALSE FALSE
[1]  TRUE FALSE FALSE

Explanation: It checks each corresponding pair:

  • TRUE & TRUETRUE
  • FALSE & TRUEFALSE
  • TRUE & FALSEFALSE

3. && (Logical AND – evaluates only first element)

This operator also performs logical AND, but only on the first element of each operand. It is often used in control structures like if statements.

Used for scalar (single logical) comparisons.

It only checks the first element of each logical vector.

If your vector has more than one element, you’ll get an error or unexpected result.

Example:

a <- c(TRUE, FALSE)
b <- c(TRUE, TRUE)
result <- (a & b)
print(result)  # Output: TRUE FALSE
[1]  TRUE FALSE
a <- c(TRUE, FALSE)
b <- c(TRUE, TRUE)
result <- (a && b )
Error in a && b : 'length = 2' in coercion to 'logical(1)'
a <- c(TRUE, FALSE)
b <- c(TRUE, TRUE)
result <- (a[1] && b[1])
print(result)  # Output: TRUE
[1] TRUE

Explanation: It checks only the first elements: TRUE && TRUETRUE


4. | (Element-wise Logical OR)

Performs logical OR element by element. It returns TRUE if either of the elements is TRUE.

Example:

a <- c(TRUE, FALSE, FALSE)
b <- c(FALSE, TRUE, FALSE)
result <- a | b
print(result)  # Output: TRUE TRUE FALSE
[1]  TRUE  TRUE FALSE

Explanation:

  • TRUE | FALSETRUE
  • FALSE | TRUETRUE
  • FALSE | FALSEFALSE

5. || (Logical OR – evaluates only first element)

This performs logical OR on only the first element of the logical vectors.

Example:

a <- c(FALSE, FALSE)
b <- c(TRUE, FALSE)
result <- a || b
Error in a || b : 'length = 2' in coercion to 'logical(1)'
a <- c(FALSE, FALSE)
b <- c(TRUE, FALSE)
result <- a[1] || b[1]
print(result)  # Output: TRUE
[1] TRUE

Explanation: It checks only the first elements: FALSE || TRUETRUE


Summary Table

Operator Name Works On Example Result
! Logical NOT Single value !TRUE FALSE
& Element-wise AND Vectors c(TRUE, FALSE) & c(TRUE, TRUE) TRUE FALSE
&& First-element AND Vectors c(TRUE, FALSE) && c(TRUE, TRUE) TRUE
| Element-wise Logical OR Element-wise OR Vectors `c(FALSE, FALSE) c(TRUE, FALSE)` TRUE FALSE
|| Logical OR First-element OR Vectors `c(FALSE, TRUE) c(TRUE, FALSE)` TRUE

These logical operators are fundamental for filtering rows in data frames, applying conditions, and building control flows in R programming.

Certainly! Here’s a detailed explanation of Assignment Operators in R with examples using proper sentences:


Assignment Operators in R

Assignment operators in R are used to assign values to variables. R provides multiple ways to assign values, including leftward, rightward, and equal sign assignments.


1. <- (Leftward Assignment)

  • Description: This is the most commonly used assignment operator in R. It assigns a value to a variable by pointing the arrow from the value to the variable.
  • Example:
x <- 10
print(x)
[1] 10
  • Explanation: The value 10 is assigned to the variable x. When you print x, it outputs 10.

2. <<- (Global or Upward Assignment)

  • Description: This operator assigns a value to a variable in a parent environment (used inside functions to update global variables).
  • Example:
updateVar <- function() {
  y <<- 50
}
updateVar()
print(y)
[1] 50
  • Explanation: The variable y is created in the global environment even though it is assigned inside a function using <<-.

3. = (Equal Sign Assignment)

  • Description: It assigns a value just like <-, but it’s more commonly used when passing arguments to functions.
  • Example:
  z = 20
  print(z)
[1] 20
  • Explanation: The value 20 is assigned to the variable z. Both <- and = can be used for simple assignments, but <- is preferred in R programming style.

Summary Table

Operator Usage Scope Common Use Case Example
<- Local/Global General assignment a <- 5
<<- Parent/Global env Inside functions (global) x <<- 10
= Local Assign values or function args x = 20

Certainly! Here’s a detailed explanation of Functions in R with proper structure, examples, and best practices:


FUNCTIONS IN R


What is a Function in R?

A function in R is a block of reusable code designed to perform a specific task. R provides many built-in functions, and it also allows users to define their own functions.


Why Use Functions?

  • To avoid repetition of code
  • To make code modular, clean, and readable
  • To simplify debugging and testing
  • To break complex problems into manageable parts

Syntax of a Function in R

function_name <- function(arg1, arg2, ...) {
  # Code block
  return(result)
}

Example: Simple Function in R

add_numbers <- function(a, b) {
  result <- a + b
  return(result)
}
add_numbers(5, 3)
[1] 8

Components of a Function

Component Description
function_name Name of the function
function() Keyword to define a function
arguments Input values passed to the function
return() Optional – returns output to the calling environment
Body Block of code that defines what the function does

Built-in Functions in R

R comes with many built-in functions:

Function Description Example
sum() Calculates sum of values sum(c(1, 2, 3))
mean() Calculates average mean(c(4, 5, 6))
sqrt() Square root sqrt(25)
length() Number of elements in a vector length(c(1,2,3))

User-defined Function with Default Values

greet <- function(name = "User") {
  paste("Hello", name)
}
greet("Srinivas")
[1] "Hello Srinivas"
greet()
[1] "Hello User"

Function Without Return Statement

If return() is not used, R will return the last evaluated expression:

multiply <- function(a, b) {
  a * b
}
multiply(4, 5)
[1] 20

Nested Function Example

outer <- function(x) {
  inner <- function(y) {
    return(y + 1)
  }
  return(inner(x) * 2)
}
outer(4)  # returns (4+1)*2 = 10
[1] 10

Anonymous Functions (No Name)

sapply(c(1, 2, 3), function(x) x^2)
[1] 1 4 9

Variable Scope in Functions

Variables created inside a function are local to that function:

myfunc <- function() {
  x <- 10  # Local variable
  print(x)
}
myfunc()
[1] 10
print(x)  # Error: object 'x' not found
[1] 10

Summary Table

Type Description Example
Built-in Predefined R functions sum(), mean(), sqrt()
User-defined Functions created by users my_function <- function() {...}
With defaults Functions with default argument vals greet <- function(name = "User")
Anonymous Functions without name function(x) x+1 in sapply()

LS0tDQp0aXRsZTogIkludHJvZHVjdGlvbiB0byBSIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMgUiBmZWF0dXJlcw0KDQoxLiAqKldlbGwtZGV2ZWxvcGVkIGFuZCBlZmZlY3RpdmUgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UqKiDigJMgUiBpcyBhIHNpbXBsZSB5ZXQgcG93ZXJmdWwgbGFuZ3VhZ2Ugc3BlY2lmaWNhbGx5IGRlc2lnbmVkIGZvciBkYXRhIGFuYWx5c2lzIGFuZCBzdGF0aXN0aWNhbCBjb21wdXRpbmcuDQoNCjIuICoqRWZmaWNpZW50IGRhdGEgaGFuZGxpbmcgYW5kIHN0b3JhZ2UqKiDigJMgUiBwcm92aWRlcyByb2J1c3Qgc3RydWN0dXJlcyBmb3IgaGFuZGxpbmcgYW5kIHN0b3JpbmcgbGFyZ2UgZGF0YXNldHMgZWZmaWNpZW50bHkuDQoNCjMuICoqUmljaCBzZXQgb2Ygb3BlcmF0b3JzKiog4oCTIFIgaW5jbHVkZXMgYSB2YXJpZXR5IG9mIG9wZXJhdG9ycyBmb3IgcGVyZm9ybWluZyBjYWxjdWxhdGlvbnMgb24gYXJyYXlzLCBsaXN0cywgdmVjdG9ycywgYW5kIG1hdHJpY2VzLg0KDQo0LiAqKkNvbXByZWhlbnNpdmUgdG9vbHMgZm9yIGRhdGEgYW5hbHlzaXMqKiDigJMgUiBvZmZlcnMgbnVtZXJvdXMgYnVpbHQtaW4gZnVuY3Rpb25zIGFuZCBwYWNrYWdlcyB0aGF0IHN1cHBvcnQgYSB3aWRlIHJhbmdlIG9mIGRhdGEgYW5hbHlzaXMgdGFza3MuDQoNCjUuICoqQWR2YW5jZWQgZ3JhcGhpY2FsIGNhcGFiaWxpdGllcyoqIOKAkyBSIHN1cHBvcnRzIGJvdGggYmFzaWMgYW5kIGFkdmFuY2VkIGdyYXBoaWNhbCB0ZWNobmlxdWVzIGZvciBkYXRhIHZpc3VhbGl6YXRpb24sIGFpZGluZyBpbiBiZXR0ZXIgaW50ZXJwcmV0YXRpb24gb2YgcmVzdWx0cy4NCg0KNi4gKipFeHRlbnNpdmUgcGFja2FnZXMgZm9yIGFkdmFuY2VkIGFwcGxpY2F0aW9ucyoqIOKAkyBSIGhhcyBhIHZhc3QgY29sbGVjdGlvbiBvZiBwYWNrYWdlcyBmb3IgZGF0YSBtaW5pbmcsIG1hY2hpbmUgbGVhcm5pbmcsIGFuZCBiaWcgZGF0YSBhbmFseXRpY3MsIG1ha2luZyBpdCBoaWdobHkgc3VpdGFibGUgZm9yIG1vZGVybiBkYXRhIHNjaWVuY2Ugd29ya2Zsb3dzLg0KDQoNCiMjIFIgRW52aXJvbm1lbnQgV29ya3NwYWNlIERlc2NyaXB0aW9uDQoNCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPg0KICA8aW1nIHNyYz0iUiBFbnZpcm9ubWVudC5KUEciIGFsdD0iRmlndXJlOiBSIEVudmlyb25tZW50IFdvcmtzcGFjZSIgd2lkdGg9IjcwJSI+DQo8L2Rpdj4NCg0KDQoxLiAqKlIgU2NyaXB0L0ZpbGUqKiDigJMgVGhpcyBpcyB3aGVyZSB1c2VycyB3cml0ZSBhbmQgc2F2ZSB0aGVpciBSIGNvZGUuIEl0IGFsbG93cyB5b3UgdG8gZWRpdCwgcnVuLCBhbmQgbWFuYWdlIHJldXNhYmxlIHNjcmlwdHMgZm9yIGFuYWx5c2lzIGFuZCBhdXRvbWF0aW9uLg0KDQoyLiAqKkVudmlyb25tZW50Kiog4oCTIERpc3BsYXlzIHRoZSBjdXJyZW50IHdvcmtzcGFjZSwgaW5jbHVkaW5nIGFsbCB0aGUgdmFyaWFibGVzLCBkYXRhIGZyYW1lcywgZnVuY3Rpb25zLCBhbmQgbG9hZGVkIG9iamVjdHMgdGhhdCBhcmUgYWN0aXZlIGluIHlvdXIgc2Vzc2lvbi4NCg0KMy4gKipIaXN0b3J5Kiog4oCTIEtlZXBzIGEgcmVjb3JkIG9mIGFsbCB0aGUgUiBjb21tYW5kcyBleGVjdXRlZCBkdXJpbmcgdGhlIHNlc3Npb24sIGFsbG93aW5nIHVzZXJzIHRvIHJldmlldyBhbmQgcmV1c2UgcHJldmlvdXMgY29tbWFuZHMgZWFzaWx5Lg0KDQo0LiAqKkNvbnNvbGUqKiDigJMgVGhlIGNvbW1hbmQtbGluZSBpbnRlcmZhY2Ugd2hlcmUgdXNlcnMgY2FuIGRpcmVjdGx5IGVudGVyIGFuZCBleGVjdXRlIFIgY29tbWFuZHMgYW5kIGltbWVkaWF0ZWx5IHNlZSB0aGUgb3V0cHV0IG9yIHJlc3VsdHMuDQoNCjUuICoqRmlsZXMqKiDigJMgUHJvdmlkZXMgYWNjZXNzIHRvIHRoZSBkaXJlY3Rvcnkgc3RydWN0dXJlIG9mIHlvdXIgY29tcHV0ZXIgc28gdGhhdCB5b3UgY2FuIGJyb3dzZSwgb3Blbiwgb3IgbWFuYWdlIGZpbGVzIGFuZCBmb2xkZXJzLg0KDQo2LiAqKlBsb3RzKiog4oCTIERpc3BsYXlzIHZpc3VhbCBvdXRwdXQgZ2VuZXJhdGVkIGZyb20gZGF0YSB2aXN1YWxpemF0aW9ucywgc3VjaCBhcyBncmFwaHMgYW5kIGNoYXJ0cyBjcmVhdGVkIHVzaW5nIFIncyBwbG90dGluZyBmdW5jdGlvbnMuDQoNCjcuICoqUGFja2FnZXMqKiDigJMgU2hvd3MgdGhlIGxpc3Qgb2YgUiBwYWNrYWdlcyBpbnN0YWxsZWQgYW5kIGxvYWRlZCBpbiB0aGUgc2Vzc2lvbi4gVXNlcnMgY2FuIGluc3RhbGwgbmV3IHBhY2thZ2VzIG9yIGxvYWQvdW5sb2FkIGV4aXN0aW5nIG9uZXMgZnJvbSBoZXJlLg0KDQo4LiAqKkhlbHAqKiDigJMgT2ZmZXJzIGRvY3VtZW50YXRpb24gYW5kIGhlbHAgZm9yIFIgZnVuY3Rpb25zLCBwYWNrYWdlcywgYW5kIGNvbW1hbmRzLiBVc2VycyBjYW4gc2VhcmNoIGZvciBhbmQgdmlldyBkZXRhaWxlZCBkZXNjcmlwdGlvbnMsIHVzYWdlLCBhbmQgZXhhbXBsZXMuDQoNCiMjIFRoZSBzdGVwLWJ5LXN0ZXAgaW5zdHJ1Y3Rpb25zIHRvIGRvd25sb2FkIGFuZCBpbnN0YWxsIFIgcHJvZ3JhbW1pbmcgYW5kIFJTdHVkaW86DQoNCioqU3RlcCAxOiBEb3dubG9hZCBhbmQgSW5zdGFsbCBSKioNCg0KMS4gR28gdG8gdGhlIENSQU4gUiBQcm9qZWN0IFdlYnNpdGUgaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcgLCANCg0KMi4gQ2hvb3NlIHlvdXIgT3BlcmF0aW5nIFN5c3RlbSA6IENsaWNrIG9uICJEb3dubG9hZCBSIGZvciBXaW5kb3dzIiwgIkRvd25sb2FkIFIgZm9yIG1hY09TIiwgb3IgIkRvd25sb2FkIFIgZm9yIExpbnV4IiBkZXBlbmRpbmcgb24geW91ciBzeXN0ZW0uDQoNCjMuIERvd25sb2FkIHRoZSBSIEluc3RhbGxlcjogIEZvciBXaW5kb3dzOiBDbGljayAiYmFzZSIgPiB0aGVuIGNsaWNrICJEb3dubG9hZCBSIHgueC54IGZvciBXaW5kb3dzIiAoZS5nLiwgUiA0LjMuMSkuIEZvciBtYWNPUzogQ2xpY2sgdGhlIGxpbmsgZm9yIHRoZSBsYXRlc3QgLnBrZyBpbnN0YWxsZXINCg0KNC4gUnVuIHRoZSBJbnN0YWxsZXI6IE9wZW4gdGhlIGRvd25sb2FkZWQgZmlsZSwgRm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgdG8gaW5zdGFsbCBSIChkZWZhdWx0IHNldHRpbmdzIGFyZSB1c3VhbGx5IGZpbmUpDQoNCioqU3RlcCAyOiBEb3dubG9hZCBhbmQgSW5zdGFsbCBSU3R1ZGlvKioNCg0KMS4gR28gdG8gdGhlIFJTdHVkaW8gV2Vic2l0ZSBodHRwczovL3Bvc2l0LmNvL2Rvd25sb2FkL3JzdHVkaW8tZGVza3RvcC8gLERvd25sb2FkIFJTdHVkaW8gRGVza3RvcCAoRnJlZSkuIA0KDQoyLiBDbGljayBvbiAiRG93bmxvYWQgUlN0dWRpbyBEZXNrdG9wIGZvciBbWW91ciBPU10iLiBJdCB3aWxsIHJlZGlyZWN0IHlvdSB0byB0aGUgYXBwcm9wcmlhdGUgaW5zdGFsbGVyIGZvciBXaW5kb3dzLCBtYWNPUywgb3IgTGludXgNCg0KMy4gSW5zdGFsbCBSU3R1ZGlvDQoNCjQuIFJ1biB0aGUgZG93bmxvYWRlZCBpbnN0YWxsZXI6IEZvbGxvdyB0aGUgb24tc2NyZWVuIGluc3RydWN0aW9ucy4NCg0KIyMgUGFja2FnZXMgYW5kIExpYnJhcmllcw0KDQpSIHByb3ZpZGVzIGFjY2VzcyB0byBhIHZhc3QgZWNvc3lzdGVtIG9mIHBhY2thZ2VzLCB3aXRoIG1vcmUgdGhhbiA3LDc2OSBwYWNrYWdlcyBhdmFpbGFibGUgdGhyb3VnaCBDUkFOIChDb21wcmVoZW5zaXZlIFIgQXJjaGl2ZSBOZXR3b3JrKS4gVGhlc2UgcGFja2FnZXMgZXh0ZW5kIFLigJlzIGZ1bmN0aW9uYWxpdHkgYW5kIHN1cHBvcnQgYSB3aWRlIHJhbmdlIG9mIHRhc2tzIGluIGRhdGEgc2NpZW5jZSBhbmQgc3RhdGlzdGljYWwgY29tcHV0aW5nLiBTb21lIG9mIHRoZSBrZXkgY2FwYWJpbGl0aWVzIG9mZmVyZWQgYnkgUiBwYWNrYWdlcyBpbmNsdWRlOg0KDQoqKkRhdGEgdmlzdWFsaXphdGlvbjoqKiBUb29scyBmb3IgY3JlYXRpbmcgY2hhcnRzLCBncmFwaHMsIGFuZCBpbnRlcmFjdGl2ZSBwbG90cyAoZS5nLiwgZ2dwbG90MiwgcGxvdGx5KS4NCg0KKipEYXRhIHN0YXRpc3RpY3MgYW5kIGV4cGxvcmF0aW9uOioqIEZ1bmN0aW9ucyB0byBzdW1tYXJpemUsIGV4cGxvcmUsIGFuZCB1bmRlcnN0YW5kIGRhdGEgZGlzdHJpYnV0aW9ucyBhbmQgcmVsYXRpb25zaGlwcy4NCg0KKipEYXRhIHRyYW5zZm9ybWF0aW9uOioqIFV0aWxpdGllcyBmb3IgY2xlYW5pbmcsIHJlc2hhcGluZywgYW5kIG1hbmlwdWxhdGluZyBkYXRhIChlLmcuLCBkcGx5ciwgdGlkeXIpLg0KDQoqKk91dGxpZXIgZGV0ZWN0aW9uOioqIE1ldGhvZHMgZm9yIGlkZW50aWZ5aW5nIGFuZCBoYW5kbGluZyBhbm9tYWxpZXMgaW4gZGF0YS4NCg0KKipGZWF0dXJlIHNlbGVjdGlvbjoqKiBUZWNobmlxdWVzIHRvIHNlbGVjdCBpbXBvcnRhbnQgdmFyaWFibGVzIHRoYXQgY29udHJpYnV0ZSBtb3N0IHRvIHByZWRpY3Rpb24gb3IgY2xhc3NpZmljYXRpb24uDQoNCioqRGltZW5zaW9uIHJlZHVjdGlvbjoqKiBUb29scyBsaWtlIFBDQSAoUHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcykgdG8gcmVkdWNlIHRoZSBudW1iZXIgb2YgdmFyaWFibGVzIHdoaWxlIHByZXNlcnZpbmcgZGF0YSBzdHJ1Y3R1cmUuDQoNCioqQ2xhc3NpZmljYXRpb246KiogQWxnb3JpdGhtcyBmb3Igc3VwZXJ2aXNlZCBsZWFybmluZyBhbmQgYXNzaWduaW5nIGRhdGEgdG8gY2F0ZWdvcmllcyAoZS5nLiwgZGVjaXNpb24gdHJlZXMsIFNWTSkuDQoNCioqQ2x1c3RlcmluZzoqKiBVbnN1cGVydmlzZWQgbGVhcm5pbmcgdGVjaG5pcXVlcyBmb3IgZ3JvdXBpbmcgc2ltaWxhciBkYXRhIHBvaW50cyAoZS5nLiwgay1tZWFucywgaGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcpLg0KDQoqKlJlZ3Jlc3Npb24gdmFsaWRhdGlvbjoqKiBUb29scyB0byBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgcmVncmVzc2lvbiBtb2RlbHMuDQoNCioqQ2xhc3NpZmljYXRpb24gdmFsaWRhdGlvbjoqKiBGdW5jdGlvbnMgdG8gYXNzZXNzIGFjY3VyYWN5LCBwcmVjaXNpb24sIHJlY2FsbCwgYW5kIEYxLXNjb3JlIG9mIGNsYXNzaWZpY2F0aW9uIG1vZGVscy4NCg0KKipDbHVzdGVyaW5nIHZhbGlkYXRpb246KiogTWV0cmljcyB0byB2YWxpZGF0ZSB0aGUgcXVhbGl0eSBhbmQgZWZmZWN0aXZlbmVzcyBvZiBjbHVzdGVyaW5nIHJlc3VsdHMgKGUuZy4sIHNpbGhvdWV0dGUgc2NvcmUpLg0KDQojIyBJbnN0YWxsaW5nIGFuZCBMb2FkaW5nIFBhY2thZ2VzIGluIFIgVXNpbmcgUlN0dWRpbyBHVUkgDQoNCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPg0KICA8aW1nIHNyYz0iSW5zdGFsbGluZyBwYWNrYWdlIGluIFJfYi5KUEciIGFsdD0iRmlndXJlOiBJbnN0YWxsaW5nIGFuZCBMb2FkaW5nIFBhY2thZ2VzIGluIFIiIHdpZHRoPSI2MCUiPg0KPC9kaXY+DQoNCg0KMS4gT3BlbiBSU3R1ZGlvOiBTdGFydCBieSBvcGVuaW5nIHRoZSBSU3R1ZGlvIGFwcGxpY2F0aW9uIG9uIHlvdXIgY29tcHV0ZXIuDQoNCjIuIEluc3RhbGwgYSBQYWNrYWdlIFVzaW5nIHRoZSBHVUk6IEdvIHRvIHRoZSAiUGFja2FnZXMiIHRhYiBpbiB0aGUgYm90dG9tLXJpZ2h0IHBhbmUuDQoNCjMuIENsaWNrIG9uIHRoZSAiSW5zdGFsbCIgYnV0dG9uICh1c3VhbGx5IGF0IHRoZSB0b3AgbGVmdCBvZiB0aGUgIlBhY2thZ2VzIiB0YWIpLiBBIGRpYWxvZyBib3ggd2lsbCBhcHBlYXIuIEluIHRoZSAiUGFja2FnZXMiIGZpZWxkLCB0eXBlIHRoZSBuYW1lIG9mIHRoZSBwYWNrYWdlIHlvdSB3YW50IHRvIGluc3RhbGwgKGUuZy4sIGdncGxvdDIpLiBNYWtlIHN1cmUgdGhlIGNoZWNrYm94ICJJbnN0YWxsIGRlcGVuZGVuY2llcyIgaXMgc2VsZWN0ZWQuDQoNCjQuIENsaWNrIHRoZSAiSW5zdGFsbCIgYnV0dG9uLiBSU3R1ZGlvIHdpbGwgbm93IGRvd25sb2FkIGFuZCBpbnN0YWxsIHRoZSBwYWNrYWdlIGZyb20gQ1JBTi4NCg0KNS4gTG9hZCBhIFBhY2thZ2UgVXNpbmcgdGhlIEdVSTogQWZ0ZXIgaW5zdGFsbGF0aW9uLCBzdGF5IGluIHRoZSAiUGFja2FnZXMiIHRhYi4gRmluZCB0aGUgaW5zdGFsbGVkIHBhY2thZ2UgaW4gdGhlIGxpc3QgKGUuZy4sIGdncGxvdDIpLiBUaWNrIHRoZSBjaGVja2JveCBuZXh0IHRvIHRoZSBwYWNrYWdlIG5hbWUgdG8gbG9hZCBpdCBpbnRvIHlvdXIgUiBzZXNzaW9uLg0KDQoNCiMjIFN0ZXBzIHRvIEluc3RhbGwgYW5kIExvYWQgUGFja2FnZXMgaW4gUg0KDQoxLiAqKkluc3RhbGxpbmcgYSBQYWNrYWdlKio6IFRvIGluc3RhbGwgYSBwYWNrYWdlIGluIFIsIHlvdSB1c2UgdGhlIGluc3RhbGwucGFja2FnZXMoKSBmdW5jdGlvbi4gVGhpcyBzdGVwIGRvd25sb2FkcyB0aGUgcGFja2FnZSBmcm9tIENSQU4gYW5kIGluc3RhbGxzIGl0IG9uIHlvdXIgc3lzdGVtLg0KDQoqKkV4YW1wbGU6KiogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KDQpUaGlzIGNvbW1hbmQgaW5zdGFsbHMgdGhlIGdncGxvdDIgcGFja2FnZSwgd2hpY2ggaXMgd2lkZWx5IHVzZWQgZm9yIGRhdGEgdmlzdWFsaXphdGlvbi4NCg0KMi4gKipMb2FkaW5nIGEgUGFja2FnZSoqIDogT25jZSBhIHBhY2thZ2UgaXMgaW5zdGFsbGVkLCB5b3UgbmVlZCB0byBsb2FkIGl0IGludG8geW91ciBjdXJyZW50IFIgc2Vzc2lvbiB1c2luZyB0aGUgbGlicmFyeSggKSBmdW5jdGlvbi4NCg0KRXhhbXBsZTogbGlicmFyeShnZ3Bsb3QyKQ0KDQpUaGlzIGNvbW1hbmQgbG9hZHMgdGhlIGdncGxvdDIgcGFja2FnZSBzbyB0aGF0IHlvdSBjYW4gdXNlIGl0cyBmdW5jdGlvbnMuDQoNCjMuICoqQ2hlY2sgaWYgYSBQYWNrYWdlIGlzIEFscmVhZHkgSW5zdGFsbGVkKiogOiANCllvdSBjYW4gY2hlY2sgaWYgYSBwYWNrYWdlIGlzIGFscmVhZHkgaW5zdGFsbGVkIHVzaW5nIHRoZSByZXF1aXJlKCkgZnVuY3Rpb24gb3IgYnkgY2hlY2tpbmcgdGhlIGluc3RhbGxlZCBwYWNrYWdlcyBsaXN0Lg0KDQpFeGFtcGxlOiByZXF1aXJlKGdncGxvdDIpDQoNCklmIHRoZSBwYWNrYWdlIGlzIG5vdCBpbnN0YWxsZWQsIHJlcXVpcmUoKSB3aWxsIHJldHVybiBGQUxTRS4NCg0KNC4gKipJbnN0YWxsIGFuZCBMb2FkIE11bHRpcGxlIFBhY2thZ2VzKiogDQpZb3UgY2FuIGluc3RhbGwgYW5kIGxvYWQgbXVsdGlwbGUgcGFja2FnZXMgdXNpbmcgYSB2ZWN0b3IgYW5kIGEgbG9vcC4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KcGFja2FnZXMgPC0gYygiZHBseXIiLCAidGlkeXIiLCAiZ2dwbG90MiIpDQoNCmluc3RhbGwucGFja2FnZXMocGFja2FnZXMpICAgIyBJbnN0YWxsIGFsbA0KDQpsYXBwbHkocGFja2FnZXMsIGxpYnJhcnksIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkgICMgTG9hZCBhbGwNCmBgYA0KDQoNCjUuICoqVmlld2luZyBJbnN0YWxsZWQgUGFja2FnZXMqKiA6IA0KWW91IGNhbiB2aWV3IGFsbCBpbnN0YWxsZWQgcGFja2FnZXMgdXNpbmc6DQoNCmBgYHtyfQ0KaW5zdGFsbGVkLnBhY2thZ2VzKCkNCmBgYA0KDQoNCjYuICoqVXBkYXRlIFBhY2thZ2VzIChPcHRpb25hbCkqKiA6IA0KVG8gdXBkYXRlIGFsbCBpbnN0YWxsZWQgcGFja2FnZXM6DQoNCmBgYHtyfQ0KdXBkYXRlLnBhY2thZ2VzKCkNCmBgYA0KDQoNCg0KQ2VydGFpbmx5ISBIZXJlJ3MgYSBkZXRhaWxlZCBleHBsYW5hdGlvbiBvZiB0aGUgKipiYXNpYyBkYXRhIHR5cGVzIGluIFIqKiwgd2l0aCBwcm9wZXIgc2VudGVuY2VzIGFuZCBleGFtcGxlcyBmb3IgZWFjaDoNCg0KLS0tDQoNCiMjICAqKkJhc2ljIERhdGEgVHlwZXMgaW4gUioqDQoNClIgaXMgYSBwb3dlcmZ1bCBwcm9ncmFtbWluZyBsYW5ndWFnZSB1c2VkIGZvciBzdGF0aXN0aWNhbCBjb21wdXRpbmcgYW5kIGRhdGEgYW5hbHlzaXMuIEl0IHN1cHBvcnRzIHNldmVyYWwgKipiYXNpYyBkYXRhIHR5cGVzKiosIHdoaWNoIGFyZSBmdW5kYW1lbnRhbCBmb3IgaGFuZGxpbmcgYW5kIG1hbmlwdWxhdGluZyBkYXRhLiBUaGVzZSBkYXRhIHR5cGVzIGluY2x1ZGU6ICoqbnVtZXJpYyoqLCAqKmludGVnZXIqKiwgKipjb21wbGV4KiosICoqY2hhcmFjdGVyIChzdHJpbmcpKiosIGFuZCAqKmxvZ2ljYWwgKGJvb2xlYW4pKiouDQoNCi0tLQ0KDQojIyMgMS4gICoqTnVtZXJpYyoqDQoNCiogVGhlICoqbnVtZXJpYyoqIGRhdGEgdHlwZSByZXByZXNlbnRzICoqcmVhbCBudW1iZXJzKiogKGkuZS4sIG51bWJlcnMgd2l0aCBkZWNpbWFsIHBvaW50cykuDQoqIEl0IGlzIHRoZSBkZWZhdWx0IHR5cGUgZm9yIG51bWJlcnMgaW4gUiB1bmxlc3Mgc3BlY2lmaWVkIG90aGVyd2lzZS4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KeCA8LSAzLjE0DQpjbGFzcyh4KSAgIyBPdXRwdXQ6ICJudW1lcmljIg0KYGBgDQoNCg0KSGVyZSwgYHhgIGlzIGEgbnVtZXJpYyB2YXJpYWJsZSBzdG9yaW5nIHRoZSB2YWx1ZSAzLjE0Lg0KDQotLS0NCg0KIyMjIDIuICAqKkludGVnZXIqKg0KDQoqIEFuICoqaW50ZWdlcioqIGlzIGEgd2hvbGUgbnVtYmVyICh3aXRob3V0IGEgZGVjaW1hbCBwb2ludCkuDQoqIEluIFIsIHlvdSBtdXN0IHVzZSBhbiAqKmBMYCBzdWZmaXgqKiB0byBleHBsaWNpdGx5IGRlZmluZSBhbiBpbnRlZ2VyLg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQp5IDwtIDEwTA0KY2xhc3MoeSkgICMgT3V0cHV0OiAiaW50ZWdlciINCmBgYA0KDQoNClRoZSBgTGAgdGVsbHMgUiB0byB0cmVhdCBgMTBgIGFzIGFuIGludGVnZXIgcmF0aGVyIHRoYW4gYSBudW1lcmljICh3aGljaCB3b3VsZCBiZSBhIGRvdWJsZSkuDQoNCi0tLQ0KDQojIyMgMy4gKipDb21wbGV4KioNCg0KKiBUaGUgKipjb21wbGV4KiogZGF0YSB0eXBlIHJlcHJlc2VudHMgKipjb21wbGV4IG51bWJlcnMqKiwgd2hpY2ggaGF2ZSBib3RoIGEgcmVhbCBhbmQgaW1hZ2luYXJ5IHBhcnQgKGUuZy4sIDEgKyAyaSkuDQoqIFVzZWZ1bCBpbiBtYXRoZW1hdGljYWwgY29tcHV0YXRpb25zIGludm9sdmluZyBjb21wbGV4IGFyaXRobWV0aWMuDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCnogPC0gMiArIDNpDQpjbGFzcyh6KSAgIyBPdXRwdXQ6ICJjb21wbGV4Ig0KYGBgDQoNCg0KSGVyZSwgYHpgIGlzIGEgY29tcGxleCBudW1iZXIgd2l0aCBhIHJlYWwgcGFydCBgMmAgYW5kIGFuIGltYWdpbmFyeSBwYXJ0IGAzaWAuDQoNCi0tLQ0KDQojIyMgNC4gICoqQ2hhcmFjdGVyIChTdHJpbmcpKioNCg0KKiBUaGUgKipjaGFyYWN0ZXIqKiBkYXRhIHR5cGUgaXMgdXNlZCB0byBzdG9yZSAqKnRleHQgb3Igc3RyaW5nIHZhbHVlcyoqLCBzdWNoIGFzIHdvcmRzLCBwaHJhc2VzLCBvciBhbnkgc2VxdWVuY2Ugb2YgY2hhcmFjdGVycy4NCiogQ2hhcmFjdGVyIGRhdGEgbXVzdCBiZSBlbmNsb3NlZCBpbiBlaXRoZXIgc2luZ2xlIGAnYCBvciBkb3VibGUgYCJgIHF1b3Rlcy4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KbmFtZSA8LSAiU3Jpbml2YXMiDQpjbGFzcyhuYW1lKSAgIyBPdXRwdXQ6ICJjaGFyYWN0ZXIiDQpgYGANCg0KDQpIZXJlLCBgIlNyaW5pdmFzImAgaXMgYSBjaGFyYWN0ZXIgc3RyaW5nLg0KDQotLS0NCg0KIyMjIDUuICoqTG9naWNhbCAoQm9vbGVhbikqKg0KDQoqIFRoZSAqKmxvZ2ljYWwqKiBkYXRhIHR5cGUgc3RvcmVzICoqVFJVRSoqIG9yICoqRkFMU0UqKiB2YWx1ZXMuDQoqIFRoaXMgdHlwZSBpcyBvZnRlbiB1c2VkIGluIGNvbmRpdGlvbnMsIGNvbXBhcmlzb25zLCBhbmQgZmlsdGVyaW5nIGRhdGEuDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmlzX3NlbmlvciA8LSBUUlVFDQpjbGFzcyhpc19zZW5pb3IpICAjIE91dHB1dDogImxvZ2ljYWwiDQoNCmFnZSA8LSAyNQ0KYWdlID4gMzAgICMgT3V0cHV0OiBGQUxTRQ0KYGBgDQoNCg0KSGVyZSwgYGlzX3NlbmlvcmAgaXMgYSBsb2dpY2FsIHZhcmlhYmxlLiBUaGUgZXhwcmVzc2lvbiBgYWdlID4gMzBgIGFsc28gcmV0dXJucyBhIGxvZ2ljYWwgdmFsdWUuDQoNCi0tLQ0KDQojIyAgU3VtbWFyeSBUYWJsZQ0KDQp8ICoqRGF0YSBUeXBlKiogfCAqKkRlc2NyaXB0aW9uKiogICAgICAgICAgICAgICAgICAgICB8ICoqRXhhbXBsZSoqICAgICAgICB8DQp8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLSB8DQp8IE51bWVyaWMgICAgICAgfCBEZWNpbWFsIG9yIGZsb2F0aW5nLXBvaW50IG51bWJlcnMgICB8IGB4IDwtIDUuNmAgICAgICAgICB8DQp8IEludGVnZXIgICAgICAgfCBXaG9sZSBudW1iZXJzIHdpdGggYExgIHN1ZmZpeCAgICAgICB8IGB5IDwtIDEwMExgICAgICAgICB8DQp8IENvbXBsZXggICAgICAgfCBOdW1iZXJzIHdpdGggcmVhbCArIGltYWdpbmFyeSBwYXJ0cyB8IGB6IDwtIDMgKyA0aWAgICAgICB8DQp8IENoYXJhY3RlciAgICAgfCBUZXh0IG9yIHN0cmluZ3MgICAgICAgICAgICAgICAgICAgICB8IGBuYW1lIDwtICJSIFVzZXIiYCB8DQp8IExvZ2ljYWwgICAgICAgfCBCb29sZWFuIHZhbHVlcyAoYFRSVUVgIG9yIGBGQUxTRWApICB8IGBmbGFnIDwtIEZBTFNFYCAgICB8DQoNCi0tLQ0KDQoNCi0tLQ0KDQojIyAqKkFyaXRobWV0aWMgT3BlcmF0b3JzIGluIFIqKg0KDQpSIHByb3ZpZGVzIGEgc2V0IG9mIGFyaXRobWV0aWMgb3BlcmF0b3JzIHRoYXQgYXJlIHVzZWQgdG8gcGVyZm9ybSBiYXNpYyBtYXRoZW1hdGljYWwgb3BlcmF0aW9ucyBvbiBudW1lcmljIHZhbHVlcywgdmVjdG9ycywgb3IgdmFyaWFibGVzLiBUaGVzZSBvcGVyYXRvcnMgaW5jbHVkZSAqKmFkZGl0aW9uKiosICoqc3VidHJhY3Rpb24qKiwgKiptdWx0aXBsaWNhdGlvbioqLCAqKmRpdmlzaW9uKiosICoqbW9kdWx1cyoqLCBhbmQgKipleHBvbmVudGlhdGlvbioqLg0KDQotLS0NCg0KIyMjIDEuICoqQWRkaXRpb24gKGArYCkqKg0KDQpUaGUgYCtgIG9wZXJhdG9yIGlzIHVzZWQgdG8gYWRkIHR3byBvciBtb3JlIG51bWJlcnMuDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmEgPC0gMTANCmIgPC0gNQ0KcmVzdWx0IDwtIGEgKyBiDQpwcmludChyZXN1bHQpICAjIE91dHB1dDogMTUNCmBgYA0KDQoNCkluIHRoaXMgZXhhbXBsZSwgMTAgYW5kIDUgYXJlIGFkZGVkIHRvIGdldCAxNS4NCg0KLS0tDQoNCiMjIyAyLiAqKlN1YnRyYWN0aW9uIChgLWApKioNCg0KVGhlIGAtYCBvcGVyYXRvciBpcyB1c2VkIHRvIHN1YnRyYWN0IG9uZSBudW1iZXIgZnJvbSBhbm90aGVyLg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIDEwDQpiIDwtIDUNCnJlc3VsdCA8LSBhIC0gYg0KcHJpbnQocmVzdWx0KSAgIyBPdXRwdXQ6IDUNCmBgYA0KDQoNCkhlcmUsIDUgaXMgc3VidHJhY3RlZCBmcm9tIDEwIHRvIGdldCA1Lg0KDQotLS0NCg0KIyMjIDMuICAqKk11bHRpcGxpY2F0aW9uIChgKmApKioNCg0KVGhlIGAqYCBvcGVyYXRvciBpcyB1c2VkIHRvIG11bHRpcGx5IG51bWJlcnMuDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmEgPC0gMTANCmIgPC0gNQ0KcmVzdWx0IDwtIGEgKiBiDQpwcmludChyZXN1bHQpICAjIE91dHB1dDogNTANCmBgYA0KDQoNClRoZSBtdWx0aXBsaWNhdGlvbiBvZiAxMCBhbmQgNSByZXN1bHRzIGluIDUwLg0KDQotLS0NCg0KIyMjIDQuICoqRGl2aXNpb24gKGAvYCkqKg0KDQpUaGUgYC9gIG9wZXJhdG9yIGlzIHVzZWQgdG8gZGl2aWRlIG9uZSBudW1iZXIgYnkgYW5vdGhlci4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KYSA8LSAxMA0KYiA8LSA1DQpyZXN1bHQgPC0gYSAvIGINCnByaW50KHJlc3VsdCkgICMgT3V0cHV0OiAyDQpgYGANCg0KDQpIZXJlLCAxMCBkaXZpZGVkIGJ5IDUgZ2l2ZXMgdGhlIHJlc3VsdCAyLg0KDQotLS0NCg0KIyMjIDUuICAqKk1vZHVsdXMgKGAlJWApKioNCg0KVGhlIGAlJWAgb3BlcmF0b3IgZ2l2ZXMgdGhlICoqcmVtYWluZGVyKiogd2hlbiBvbmUgbnVtYmVyIGlzIGRpdmlkZWQgYnkgYW5vdGhlci4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KYSA8LSAxMA0KYiA8LSAzDQpyZXN1bHQgPC0gYSAlJSBiDQpwcmludChyZXN1bHQpICAjIE91dHB1dDogMQ0KYGBgDQoNCg0KV2hlbiAxMCBpcyBkaXZpZGVkIGJ5IDMsIHRoZSByZW1haW5kZXIgaXMgMS4NCg0KLS0tDQoNCiMjIyA2LiAgKipFeHBvbmVudGlhdGlvbiAoYF5gKSoqDQoNClRoZSBgXmAgb3BlcmF0b3IgaXMgdXNlZCB0byByYWlzZSBhIG51bWJlciB0byB0aGUgcG93ZXIgb2YgYW5vdGhlci4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KYSA8LSAyDQpiIDwtIDMNCnJlc3VsdCA8LSBhIF4gYg0KcHJpbnQocmVzdWx0KSAgIyBPdXRwdXQ6IDgNCmBgYA0KDQoNCkluIHRoaXMgY2FzZSwgMiByYWlzZWQgdG8gdGhlIHBvd2VyIG9mIDMgZXF1YWxzIDguDQoNCi0tLQ0KDQojIyBTdW1tYXJ5IFRhYmxlDQoNCnwgT3BlcmF0b3IgfCBEZXNjcmlwdGlvbiAgICAgICAgIHwgRXhhbXBsZSAgIHwgUmVzdWx0IHwNCnwgLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tIHwgLS0tLS0tIHwNCnwgYCtgICAgICAgfCBBZGRpdGlvbiAgICAgICAgICAgIHwgYDUgKyAzYCAgIHwgOCAgICAgIHwNCnwgYC1gICAgICAgfCBTdWJ0cmFjdGlvbiAgICAgICAgIHwgYDUgLSAzYCAgIHwgMiAgICAgIHwNCnwgYCpgICAgICAgfCBNdWx0aXBsaWNhdGlvbiAgICAgIHwgYDUgKiAzYCAgIHwgMTUgICAgIHwNCnwgYC9gICAgICAgfCBEaXZpc2lvbiAgICAgICAgICAgIHwgYDYgLyAzYCAgIHwgMiAgICAgIHwNCnwgYCUlYCAgICAgfCBNb2R1bHVzIChyZW1haW5kZXIpIHwgYDEwICUlIDNgIHwgMSAgICAgIHwNCnwgYF5gICAgICAgfCBFeHBvbmVudGlhdGlvbiAgICAgIHwgYDIgXiA0YCAgIHwgMTYgICAgIHwNCg0KLS0tDQoNClRoZXNlIGFyaXRobWV0aWMgb3BlcmF0b3JzIGFyZSBmcmVxdWVudGx5IHVzZWQgaW4gbWF0aGVtYXRpY2FsIGNvbXB1dGF0aW9ucywgc3RhdGlzdGljYWwgYW5hbHlzaXMsIGFuZCBkYXRhIG1hbmlwdWxhdGlvbiB0YXNrcyBpbiBSLg0KDQotLS0NCg0KIyMgICoqUmVsYXRpb25hbCBPcGVyYXRvcnMgaW4gUioqDQoNClJlbGF0aW9uYWwgb3BlcmF0b3JzIGluIFIgYXJlIHVzZWQgdG8gKipjb21wYXJlIHR3byB2YWx1ZXMgb3IgZXhwcmVzc2lvbnMqKi4gVGhlIHJlc3VsdCBvZiBhIHJlbGF0aW9uYWwgb3BlcmF0aW9uIGlzIGFsd2F5cyBhICoqbG9naWNhbCB2YWx1ZSoqOiBlaXRoZXIgYFRSVUVgIG9yIGBGQUxTRWAuIFRoZXNlIGFyZSBlc3NlbnRpYWwgZm9yIGRlY2lzaW9uLW1ha2luZyBhbmQgY29uZGl0aW9uYWwgcHJvZ3JhbW1pbmcuDQoNCi0tLQ0KDQojIyMgMS4gYDxgIChMZXNzIHRoYW4pDQoNClRoaXMgb3BlcmF0b3IgY2hlY2tzIHdoZXRoZXIgdGhlIHZhbHVlIG9uIHRoZSBsZWZ0IGlzIGxlc3MgdGhhbiB0aGUgdmFsdWUgb24gdGhlIHJpZ2h0Lg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIDEwDQpiIDwtIDIwDQpjIDwtIGEgPCBiDQpwcmludChjKSAgIyBPdXRwdXQ6IFRSVUUNCmBgYA0KDQoNCkV4cGxhbmF0aW9uOiBTaW5jZSAxMCBpcyBsZXNzIHRoYW4gMjAsIHRoZSByZXN1bHQgaXMgYFRSVUVgLg0KDQotLS0NCg0KIyMjIDIuIGA+YCAoR3JlYXRlciB0aGFuKQ0KDQpDaGVja3MgaWYgdGhlIHZhbHVlIG9uIHRoZSBsZWZ0IGlzIGdyZWF0ZXIgdGhhbiB0aGUgdmFsdWUgb24gdGhlIHJpZ2h0Lg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIDEwDQpiIDwtIDIwDQpjIDwtIGEgPiBiDQpwcmludChjKSAgIyBPdXRwdXQ6IEZBTFNFDQpgYGANCg0KDQpFeHBsYW5hdGlvbjogMTAgaXMgbm90IGdyZWF0ZXIgdGhhbiAyMCwgc28gdGhlIHJlc3VsdCBpcyBgRkFMU0VgLg0KDQotLS0NCg0KIyMjIDMuIGA8PWAgKExlc3MgdGhhbiBvciBlcXVhbCB0bykNCg0KQ2hlY2tzIGlmIHRoZSBsZWZ0LWhhbmQgc2lkZSBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIHJpZ2h0LWhhbmQgc2lkZS4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KYSA8LSAxMA0KYiA8LSAxMA0KYyA8LSBhIDw9IGINCnByaW50KGMpICAjIE91dHB1dDogVFJVRQ0KYGBgDQoNCg0KRXhwbGFuYXRpb246IDEwIGlzIGVxdWFsIHRvIDEwLCBzbyBpdCBzYXRpc2ZpZXMgdGhlIGNvbmRpdGlvbi4NCg0KLS0tDQoNCiMjIyA0LiBgPj1gIChHcmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8pDQoNCkNoZWNrcyBpZiB0aGUgdmFsdWUgb24gdGhlIGxlZnQgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHRoZSBvbmUgb24gdGhlIHJpZ2h0Lg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIDE1DQpiIDwtIDEwDQpjIDwtIGEgPj0gYg0KcHJpbnQoYykgICMgT3V0cHV0OiBUUlVFDQpgYGANCg0KDQpFeHBsYW5hdGlvbjogMTUgaXMgZ3JlYXRlciB0aGFuIDEwLCBzbyB0aGUgcmVzdWx0IGlzIGBUUlVFYC4NCg0KLS0tDQoNCiMjIyA1LiBgPT1gIChFcXVhbCB0bykNCg0KVGVzdHMgd2hldGhlciB0d28gdmFsdWVzIGFyZSBlcXVhbC4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KYSA8LSAxMA0KYiA8LSAxMA0KYyA8LSBhID09IGINCnByaW50KGMpICAjIE91dHB1dDogVFJVRQ0KYGBgDQoNCg0KRXhwbGFuYXRpb246IEJvdGggdmFsdWVzIGFyZSBlcXVhbCwgc28gaXQgcmV0dXJucyBgVFJVRWAuDQoNCi0tLQ0KDQojIyMgNi4gYCE9YCAoTm90IGVxdWFsIHRvKQ0KDQpDaGVja3MgaWYgdGhlIHR3byB2YWx1ZXMgYXJlICoqbm90IGVxdWFsKiouDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmEgPC0gMTANCmIgPC0gMjANCmMgPC0gYSAhPSBiDQpwcmludChjKSAgIyBPdXRwdXQ6IFRSVUUNCmBgYA0KDQoNCkV4cGxhbmF0aW9uOiAxMCBhbmQgMjAgYXJlIG5vdCBlcXVhbCwgc28gdGhlIHJlc3VsdCBpcyBgVFJVRWAuDQoNCi0tLQ0KDQojIyBTdW1tYXJ5IFRhYmxlDQoNCnwgT3BlcmF0b3IgfCBEZXNjcmlwdGlvbiAgICAgICAgICAgICAgfCBFeGFtcGxlICAgIHwgUmVzdWx0IHwNCnwgLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tIHwgLS0tLS0tIHwNCnwgYDxgICAgICAgfCBMZXNzIHRoYW4gICAgICAgICAgICAgICAgfCBgMTAgPCAyMGAgIHwgVFJVRSAgIHwNCnwgYD5gICAgICAgfCBHcmVhdGVyIHRoYW4gICAgICAgICAgICAgfCBgMTAgPiAyMGAgIHwgRkFMU0UgIHwNCnwgYDw9YCAgICAgfCBMZXNzIHRoYW4gb3IgZXF1YWwgdG8gICAgfCBgMTAgPD0gMTBgIHwgVFJVRSAgIHwNCnwgYD49YCAgICAgfCBHcmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gfCBgMTUgPj0gMTBgIHwgVFJVRSAgIHwNCnwgYD09YCAgICAgfCBFcXVhbCB0byAgICAgICAgICAgICAgICAgfCBgMTAgPT0gMTBgIHwgVFJVRSAgIHwNCnwgYCE9YCAgICAgfCBOb3QgZXF1YWwgdG8gICAgICAgICAgICAgfCBgMTAgIT0gMjBgIHwgVFJVRSAgIHwNCg0KLS0tDQoNClRoZXNlIHJlbGF0aW9uYWwgb3BlcmF0b3JzIGFyZSBwYXJ0aWN1bGFybHkgdXNlZnVsIGluICoqaWYtZWxzZSBjb25kaXRpb25zKiosICoqZmlsdGVyaW5nIGRhdGEqKiwgYW5kICoqbG9vcCBjb250cm9sKiogaW4gUiBwcm9ncmFtbWluZy4NCg0KDQoNCi0tLQ0KDQojIyAgTG9naWNhbCBPcGVyYXRvcnMgaW4gUg0KDQpMb2dpY2FsIG9wZXJhdG9ycyBhcmUgdXNlZCB0byBjb21iaW5lIG9yIG1vZGlmeSBsb2dpY2FsIHZhbHVlcyAoYFRSVUVgIG9yIGBGQUxTRWApIGluIFIuIFRoZXkgYXJlIGVzcGVjaWFsbHkgdXNlZnVsIGluICoqY29uZGl0aW9uYWwgc3RhdGVtZW50cyoqLCAqKmRhdGEgZmlsdGVyaW5nKiosIGFuZCAqKnZlY3Rvcml6ZWQgb3BlcmF0aW9ucyoqLg0KDQotLS0NCg0KIyMjIDEuIGAhYCAoTG9naWNhbCBOT1QpDQoNClRoaXMgb3BlcmF0b3IgcmV2ZXJzZXMgdGhlIGxvZ2ljYWwgc3RhdGUgb2YgaXRzIG9wZXJhbmQuIElmIGEgY29uZGl0aW9uIGlzIGBUUlVFYCwgYXBwbHlpbmcgYCFgIHdpbGwgbWFrZSBpdCBgRkFMU0VgLCBhbmQgdmljZSB2ZXJzYS4NCg0KKipFeGFtcGxlOioqDQoNCmBgYHtyfQ0KeCA8LSBUUlVFDQpyZXN1bHQgPC0gIXgNCnByaW50KHJlc3VsdCkgICMgT3V0cHV0OiBGQUxTRQ0KYGBgDQoNCg0KKipFeHBsYW5hdGlvbjoqKiBUaGUgdmFsdWUgb2YgYHhgIGlzIGBUUlVFYC4gVGhlIGAhYCBvcGVyYXRvciBmbGlwcyBpdCB0byBgRkFMU0VgLg0KDQotLS0NCg0KIyMjIDIuIGAmYCAoRWxlbWVudC13aXNlIExvZ2ljYWwgQU5EKQ0KDQpUaGlzIG9wZXJhdG9yIHBlcmZvcm1zIGEgbG9naWNhbCBBTkQgKiplbGVtZW50IGJ5IGVsZW1lbnQqKiBvbiB0d28gbG9naWNhbCB2ZWN0b3JzLiBJdCByZXR1cm5zIGBUUlVFYCBpZiAqKmJvdGggZWxlbWVudHMqKiBhcmUgYFRSVUVgLg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIGMoVFJVRSwgRkFMU0UsIFRSVUUpDQpiIDwtIGMoVFJVRSwgVFJVRSwgRkFMU0UpDQpyZXN1bHQgPC0gYSAmIGINCnByaW50KHJlc3VsdCkgICMgT3V0cHV0OiBUUlVFIEZBTFNFIEZBTFNFDQpgYGANCg0KDQoqKkV4cGxhbmF0aW9uOioqIEl0IGNoZWNrcyBlYWNoIGNvcnJlc3BvbmRpbmcgcGFpcjoNCg0KKiBgVFJVRSAmIFRSVUVgIOKGkiBgVFJVRWANCiogYEZBTFNFICYgVFJVRWAg4oaSIGBGQUxTRWANCiogYFRSVUUgJiBGQUxTRWAg4oaSIGBGQUxTRWANCg0KLS0tDQoNCiMjIyAzLiBgJiZgIChMb2dpY2FsIEFORCDigJMgZXZhbHVhdGVzIG9ubHkgZmlyc3QgZWxlbWVudCkNCg0KVGhpcyBvcGVyYXRvciBhbHNvIHBlcmZvcm1zIGxvZ2ljYWwgQU5ELCBidXQgKipvbmx5IG9uIHRoZSBmaXJzdCBlbGVtZW50Kiogb2YgZWFjaCBvcGVyYW5kLiBJdCBpcyBvZnRlbiB1c2VkIGluIGNvbnRyb2wgc3RydWN0dXJlcyBsaWtlIGBpZmAgc3RhdGVtZW50cy4NCg0KDQpVc2VkIGZvciBzY2FsYXIgKHNpbmdsZSBsb2dpY2FsKSBjb21wYXJpc29ucy4NCg0KSXQgb25seSBjaGVja3MgdGhlIGZpcnN0IGVsZW1lbnQgb2YgZWFjaCBsb2dpY2FsIHZlY3Rvci4NCg0KSWYgeW91ciB2ZWN0b3IgaGFzIG1vcmUgdGhhbiBvbmUgZWxlbWVudCwgeW914oCZbGwgZ2V0IGFuIGVycm9yIG9yIHVuZXhwZWN0ZWQgcmVzdWx0Lg0KDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmEgPC0gYyhUUlVFLCBGQUxTRSkNCmIgPC0gYyhUUlVFLCBUUlVFKQ0KcmVzdWx0IDwtIChhICYgYikNCnByaW50KHJlc3VsdCkgICMgT3V0cHV0OiBUUlVFIEZBTFNFDQoNCmBgYA0KDQpgYGB7cn0NCmEgPC0gYyhUUlVFLCBGQUxTRSkNCmIgPC0gYyhUUlVFLCBUUlVFKQ0KcmVzdWx0IDwtIChhICYmIGIgKQ0KcHJpbnQocmVzdWx0KSAgIyBPdXRwdXQ6IFRSVUUNCmBgYA0KDQoNCmBgYHtyfQ0KYSA8LSBjKFRSVUUsIEZBTFNFKQ0KYiA8LSBjKFRSVUUsIFRSVUUpDQpyZXN1bHQgPC0gKGFbMV0gJiYgYlsxXSkNCnByaW50KHJlc3VsdCkgICMgT3V0cHV0OiBUUlVFDQoNCmBgYA0KDQoNCioqRXhwbGFuYXRpb246KiogSXQgY2hlY2tzIG9ubHkgdGhlIGZpcnN0IGVsZW1lbnRzOiBgVFJVRSAmJiBUUlVFYCDihpIgYFRSVUVgDQoNCi0tLQ0KDQojIyMgNC4gYHxgIChFbGVtZW50LXdpc2UgTG9naWNhbCBPUikNCg0KUGVyZm9ybXMgbG9naWNhbCBPUiAqKmVsZW1lbnQgYnkgZWxlbWVudCoqLiBJdCByZXR1cm5zIGBUUlVFYCBpZiAqKmVpdGhlcioqIG9mIHRoZSBlbGVtZW50cyBpcyBgVFJVRWAuDQoNCioqRXhhbXBsZToqKg0KDQpgYGB7cn0NCmEgPC0gYyhUUlVFLCBGQUxTRSwgRkFMU0UpDQpiIDwtIGMoRkFMU0UsIFRSVUUsIEZBTFNFKQ0KcmVzdWx0IDwtIGEgfCBiDQpwcmludChyZXN1bHQpICAjIE91dHB1dDogVFJVRSBUUlVFIEZBTFNFDQpgYGANCg0KDQoqKkV4cGxhbmF0aW9uOioqDQoNCiogYFRSVUUgfCBGQUxTRWAg4oaSIGBUUlVFYA0KKiBgRkFMU0UgfCBUUlVFYCDihpIgYFRSVUVgDQoqIGBGQUxTRSB8IEZBTFNFYCDihpIgYEZBTFNFYA0KDQotLS0NCg0KIyMjIDUuIGB8fGAgKExvZ2ljYWwgT1Ig4oCTIGV2YWx1YXRlcyBvbmx5IGZpcnN0IGVsZW1lbnQpDQoNClRoaXMgcGVyZm9ybXMgbG9naWNhbCBPUiBvbiBvbmx5IHRoZSAqKmZpcnN0IGVsZW1lbnQqKiBvZiB0aGUgbG9naWNhbCB2ZWN0b3JzLg0KDQoqKkV4YW1wbGU6KioNCg0KYGBge3J9DQphIDwtIGMoRkFMU0UsIEZBTFNFKQ0KYiA8LSBjKFRSVUUsIEZBTFNFKQ0KcmVzdWx0IDwtIGEgfHwgYg0KcHJpbnQocmVzdWx0KSAgIyBPdXRwdXQ6IFRSVUUNCmBgYA0KDQpgYGB7cn0NCmEgPC0gYyhGQUxTRSwgRkFMU0UpDQpiIDwtIGMoVFJVRSwgRkFMU0UpDQpyZXN1bHQgPC0gYVsxXSB8fCBiWzFdDQpwcmludChyZXN1bHQpICAjIE91dHB1dDogVFJVRQ0KYGBgDQoNCg0KDQoqKkV4cGxhbmF0aW9uOioqIEl0IGNoZWNrcyBvbmx5IHRoZSBmaXJzdCBlbGVtZW50czogYEZBTFNFIHx8IFRSVUVgIOKGkiBgVFJVRWANCg0KLS0tDQoNCiMjIFN1bW1hcnkgVGFibGUNCg0KfCBPcGVyYXRvciB8IE5hbWUgICAgICAgICAgICAgIHwgV29ya3MgT24gICAgICAgIHwgRXhhbXBsZSAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgUmVzdWx0ICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICB8ICAgICAgICB8DQp8IC0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tIHwNCnwgYCFgICAgICAgfCBMb2dpY2FsIE5PVCAgICAgICB8IFNpbmdsZSB2YWx1ZSAgICB8IGAhVFJVRWAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IGBGQUxTRWAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgfCAgICAgICAgfA0KfCBgJmAgICAgICB8IEVsZW1lbnQtd2lzZSBBTkQgIHwgVmVjdG9ycyAgICAgICAgIHwgYGMoVFJVRSwgRkFMU0UpICYgYyhUUlVFLCBUUlVFKWAgIHwgYFRSVUUgRkFMU0VgICAgICAgfCAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICB8ICAgICAgICB8DQp8IGAmJmAgICAgIHwgRmlyc3QtZWxlbWVudCBBTkQgfCBWZWN0b3JzICAgICAgICAgfCBgYyhUUlVFLCBGQUxTRSkgJiYgYyhUUlVFLCBUUlVFKWAgfCBgVFJVRWAgICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwNCnwgYHxgICAgICAgIHwgRWxlbWVudC13aXNlIExvZ2ljYWwgT1IgICAgICAgICAgICAgICAgfCBFbGVtZW50LXdpc2UgT1IgfCBWZWN0b3JzICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBcYGMoRkFMU0UsIEZBTFNFKSB8IGMoVFJVRSwgRkFMU0UpXGAgfCBgVFJVRSBGQUxTRWAgfCAgICAgICAgICAgICAgICAgIHwgICAgICAgIHwNCnwgYHx8YCAgICAgICB8ICAgTG9naWNhbCBPUiAgICAgICB8IEZpcnN0LWVsZW1lbnQgT1IgICAgICAgICAgICAgICAgICB8IFZlY3RvcnMgICAgICAgICAgIHwgXGBjKEZBTFNFLCBUUlVFKSB8ICAgICAgICAgICAgICB8IGMoVFJVRSwgRkFMU0UpXGAgfCBgVFJVRWAgfA0KDQotLS0NCg0KVGhlc2UgbG9naWNhbCBvcGVyYXRvcnMgYXJlIGZ1bmRhbWVudGFsIGZvciAqKmZpbHRlcmluZyByb3dzIGluIGRhdGEgZnJhbWVzKiosICoqYXBwbHlpbmcgY29uZGl0aW9ucyoqLCBhbmQgKipidWlsZGluZyBjb250cm9sIGZsb3dzKiogaW4gUiBwcm9ncmFtbWluZy4NCg0KDQpDZXJ0YWlubHkhIEhlcmUncyBhIGRldGFpbGVkIGV4cGxhbmF0aW9uIG9mICoqQXNzaWdubWVudCBPcGVyYXRvcnMgaW4gUioqIHdpdGggZXhhbXBsZXMgdXNpbmcgcHJvcGVyIHNlbnRlbmNlczoNCg0KLS0tDQoNCiMjIyAqKkFzc2lnbm1lbnQgT3BlcmF0b3JzIGluIFIqKg0KDQpBc3NpZ25tZW50IG9wZXJhdG9ycyBpbiBSIGFyZSB1c2VkIHRvIGFzc2lnbiB2YWx1ZXMgdG8gdmFyaWFibGVzLiBSIHByb3ZpZGVzIG11bHRpcGxlIHdheXMgdG8gYXNzaWduIHZhbHVlcywgaW5jbHVkaW5nIGxlZnR3YXJkLCByaWdodHdhcmQsIGFuZCBlcXVhbCBzaWduIGFzc2lnbm1lbnRzLg0KDQotLS0NCg0KIyMjIyAxLiBgPC1gIChMZWZ0d2FyZCBBc3NpZ25tZW50KQ0KDQoqICoqRGVzY3JpcHRpb24qKjogVGhpcyBpcyB0aGUgbW9zdCBjb21tb25seSB1c2VkIGFzc2lnbm1lbnQgb3BlcmF0b3IgaW4gUi4gSXQgYXNzaWducyBhIHZhbHVlIHRvIGEgdmFyaWFibGUgYnkgcG9pbnRpbmcgdGhlIGFycm93ICoqZnJvbSB0aGUgdmFsdWUgdG8gdGhlIHZhcmlhYmxlKiouDQoqICoqRXhhbXBsZSoqOg0KDQpgYGB7cn0NCnggPC0gMTANCnByaW50KHgpDQpgYGANCg0KDQoqICoqRXhwbGFuYXRpb24qKjogVGhlIHZhbHVlIGAxMGAgaXMgYXNzaWduZWQgdG8gdGhlIHZhcmlhYmxlIGB4YC4gV2hlbiB5b3UgcHJpbnQgYHhgLCBpdCBvdXRwdXRzIGAxMGAuDQoNCi0tLQ0KDQojIyMjIDIuIGA8PC1gIChHbG9iYWwgb3IgVXB3YXJkIEFzc2lnbm1lbnQpDQoNCiogKipEZXNjcmlwdGlvbioqOiBUaGlzIG9wZXJhdG9yIGFzc2lnbnMgYSB2YWx1ZSB0byBhIHZhcmlhYmxlICoqaW4gYSBwYXJlbnQgZW52aXJvbm1lbnQqKiAodXNlZCBpbnNpZGUgZnVuY3Rpb25zIHRvIHVwZGF0ZSBnbG9iYWwgdmFyaWFibGVzKS4NCiogKipFeGFtcGxlKio6DQoNCg0KYGBge3J9DQp1cGRhdGVWYXIgPC0gZnVuY3Rpb24oKSB7DQogIHkgPDwtIDUwDQp9DQp1cGRhdGVWYXIoKQ0KcHJpbnQoeSkNCmBgYA0KICANCiogKipFeHBsYW5hdGlvbioqOiBUaGUgdmFyaWFibGUgYHlgIGlzIGNyZWF0ZWQgaW4gdGhlIGdsb2JhbCBlbnZpcm9ubWVudCBldmVuIHRob3VnaCBpdCBpcyBhc3NpZ25lZCBpbnNpZGUgYSBmdW5jdGlvbiB1c2luZyBgPDwtYC4NCg0KLS0tDQoNCiMjIyMgMy4gYD1gIChFcXVhbCBTaWduIEFzc2lnbm1lbnQpDQoNCiogKipEZXNjcmlwdGlvbioqOiBJdCBhc3NpZ25zIGEgdmFsdWUganVzdCBsaWtlIGA8LWAsIGJ1dCBpdCdzIG1vcmUgY29tbW9ubHkgdXNlZCB3aGVuICoqcGFzc2luZyBhcmd1bWVudHMgdG8gZnVuY3Rpb25zKiouDQoqICoqRXhhbXBsZSoqOg0KDQpgYGB7cn0NCiAgeiA9IDIwDQogIHByaW50KHopDQpgYGANCg0KKiAqKkV4cGxhbmF0aW9uKio6IFRoZSB2YWx1ZSBgMjBgIGlzIGFzc2lnbmVkIHRvIHRoZSB2YXJpYWJsZSBgemAuIEJvdGggYDwtYCBhbmQgYD1gIGNhbiBiZSB1c2VkIGZvciBzaW1wbGUgYXNzaWdubWVudHMsIGJ1dCBgPC1gIGlzIHByZWZlcnJlZCBpbiBSIHByb2dyYW1taW5nIHN0eWxlLg0KDQotLS0NCg0KIyMjICBTdW1tYXJ5IFRhYmxlDQoNCnwgT3BlcmF0b3IgfCBVc2FnZSBTY29wZSAgICAgICB8IENvbW1vbiBVc2UgQ2FzZSAgICAgICAgICAgICAgICB8IEV4YW1wbGUgICAgfA0KfCAtLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLSB8DQp8IGA8LWAgICAgIHwgTG9jYWwvR2xvYmFsICAgICAgfCBHZW5lcmFsIGFzc2lnbm1lbnQgICAgICAgICAgICAgfCBgYSA8LSA1YCAgIHwNCnwgYDw8LWAgICAgfCBQYXJlbnQvR2xvYmFsIGVudiB8IEluc2lkZSBmdW5jdGlvbnMgKGdsb2JhbCkgICAgICB8IGB4IDw8LSAxMGAgfA0KfCBgPWAgICAgICB8IExvY2FsICAgICAgICAgICAgIHwgQXNzaWduIHZhbHVlcyBvciBmdW5jdGlvbiBhcmdzIHwgYHggPSAyMGAgICB8DQoNCi0tLQ0KDQoNCkNlcnRhaW5seSEgSGVyZSdzIGEgKipkZXRhaWxlZCBleHBsYW5hdGlvbiBvZiBGdW5jdGlvbnMgaW4gUioqIHdpdGggcHJvcGVyIHN0cnVjdHVyZSwgZXhhbXBsZXMsIGFuZCBiZXN0IHByYWN0aWNlczoNCg0KLS0tDQoNCiMjICAqKkZVTkNUSU9OUyBJTiBSKioNCg0KLS0tDQoNCiMjIyAgV2hhdCBpcyBhIEZ1bmN0aW9uIGluIFI/DQoNCkEgKipmdW5jdGlvbioqIGluIFIgaXMgYSBibG9jayBvZiByZXVzYWJsZSBjb2RlIGRlc2lnbmVkIHRvIHBlcmZvcm0gYSBzcGVjaWZpYyB0YXNrLiBSIHByb3ZpZGVzIG1hbnkgYnVpbHQtaW4gZnVuY3Rpb25zLCBhbmQgaXQgYWxzbyBhbGxvd3MgdXNlcnMgdG8gZGVmaW5lIHRoZWlyIG93biBmdW5jdGlvbnMuDQoNCi0tLQ0KDQojIyMgIFdoeSBVc2UgRnVuY3Rpb25zPw0KDQoqIFRvIGF2b2lkIHJlcGV0aXRpb24gb2YgY29kZQ0KKiBUbyBtYWtlIGNvZGUgbW9kdWxhciwgY2xlYW4sIGFuZCByZWFkYWJsZQ0KKiBUbyBzaW1wbGlmeSBkZWJ1Z2dpbmcgYW5kIHRlc3RpbmcNCiogVG8gYnJlYWsgY29tcGxleCBwcm9ibGVtcyBpbnRvIG1hbmFnZWFibGUgcGFydHMNCg0KLS0tDQoNCiMjIyAgU3ludGF4IG9mIGEgRnVuY3Rpb24gaW4gUg0KDQpgYGB7cn0NCmZ1bmN0aW9uX25hbWUgPC0gZnVuY3Rpb24oYXJnMSwgYXJnMiwgLi4uKSB7DQogICMgQ29kZSBibG9jaw0KICByZXR1cm4ocmVzdWx0KQ0KfQ0KYGBgDQoNCg0KLS0tDQoNCiMjIyAgRXhhbXBsZTogU2ltcGxlIEZ1bmN0aW9uIGluIFINCg0KYGBge3J9DQphZGRfbnVtYmVycyA8LSBmdW5jdGlvbihhLCBiKSB7DQogIHJlc3VsdCA8LSBhICsgYg0KICByZXR1cm4ocmVzdWx0KQ0KfQ0KYWRkX251bWJlcnMoNSwgMykNCmBgYA0KDQotLS0NCg0KIyMjICBDb21wb25lbnRzIG9mIGEgRnVuY3Rpb24NCg0KfCBDb21wb25lbnQgICAgICAgfCBEZXNjcmlwdGlvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8DQp8IGBmdW5jdGlvbl9uYW1lYCB8IE5hbWUgb2YgdGhlIGZ1bmN0aW9uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCBgZnVuY3Rpb24oKWAgICAgfCBLZXl3b3JkIHRvIGRlZmluZSBhIGZ1bmN0aW9uICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgYGFyZ3VtZW50c2AgICAgIHwgSW5wdXQgdmFsdWVzIHBhc3NlZCB0byB0aGUgZnVuY3Rpb24gICAgICAgICAgICAgICAgICB8DQp8IGByZXR1cm4oKWAgICAgICB8IE9wdGlvbmFsIOKAkyByZXR1cm5zIG91dHB1dCB0byB0aGUgY2FsbGluZyBlbnZpcm9ubWVudCB8DQp8IEJvZHkgICAgICAgICAgICB8IEJsb2NrIG9mIGNvZGUgdGhhdCBkZWZpbmVzIHdoYXQgdGhlIGZ1bmN0aW9uIGRvZXMgICAgfA0KDQotLS0NCg0KIyMjICBCdWlsdC1pbiBGdW5jdGlvbnMgaW4gUg0KDQpSIGNvbWVzIHdpdGggbWFueSBidWlsdC1pbiBmdW5jdGlvbnM6DQoNCnwgRnVuY3Rpb24gICB8IERlc2NyaXB0aW9uICAgICAgICAgICAgICAgICAgICB8IEV4YW1wbGUgICAgICAgICAgICB8DQp8IC0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0gfA0KfCBgc3VtKClgICAgIHwgQ2FsY3VsYXRlcyBzdW0gb2YgdmFsdWVzICAgICAgIHwgYHN1bShjKDEsIDIsIDMpKWAgIHwNCnwgYG1lYW4oKWAgICB8IENhbGN1bGF0ZXMgYXZlcmFnZSAgICAgICAgICAgICB8IGBtZWFuKGMoNCwgNSwgNikpYCB8DQp8IGBzcXJ0KClgICAgfCBTcXVhcmUgcm9vdCAgICAgICAgICAgICAgICAgICAgfCBgc3FydCgyNSlgICAgICAgICAgfA0KfCBgbGVuZ3RoKClgIHwgTnVtYmVyIG9mIGVsZW1lbnRzIGluIGEgdmVjdG9yIHwgYGxlbmd0aChjKDEsMiwzKSlgIHwNCg0KLS0tDQoNCiMjIyAgVXNlci1kZWZpbmVkIEZ1bmN0aW9uIHdpdGggRGVmYXVsdCBWYWx1ZXMNCg0KYGBge3J9DQpncmVldCA8LSBmdW5jdGlvbihuYW1lID0gIlVzZXIiKSB7DQogIHBhc3RlKCJIZWxsbyIsIG5hbWUpDQp9DQpncmVldCgiU3Jpbml2YXMiKQ0KZ3JlZXQoKQ0KYGBgDQoNCi0tLQ0KDQojIyMgIEZ1bmN0aW9uIFdpdGhvdXQgUmV0dXJuIFN0YXRlbWVudA0KDQpJZiBgcmV0dXJuKClgIGlzIG5vdCB1c2VkLCBSIHdpbGwgcmV0dXJuIHRoZSAqKmxhc3QgZXZhbHVhdGVkIGV4cHJlc3Npb24qKjoNCg0KYGBge3J9DQptdWx0aXBseSA8LSBmdW5jdGlvbihhLCBiKSB7DQogIGEgKiBiDQp9DQptdWx0aXBseSg0LCA1KQ0KYGBgDQoNCg0KLS0tDQoNCiMjIyAgTmVzdGVkIEZ1bmN0aW9uIEV4YW1wbGUNCg0KYGBge3J9DQpvdXRlciA8LSBmdW5jdGlvbih4KSB7DQogIGlubmVyIDwtIGZ1bmN0aW9uKHkpIHsNCiAgICByZXR1cm4oeSArIDEpDQogIH0NCiAgcmV0dXJuKGlubmVyKHgpICogMikNCn0NCm91dGVyKDQpICAjIHJldHVybnMgKDQrMSkqMiA9IDEwDQpgYGANCg0KDQotLS0NCg0KIyMjICBBbm9ueW1vdXMgRnVuY3Rpb25zIChObyBOYW1lKQ0KDQpgYGB7cn0NCnNhcHBseShjKDEsIDIsIDMpLCBmdW5jdGlvbih4KSB4XjIpDQpgYGANCg0KDQotLS0NCg0KIyMjICBWYXJpYWJsZSBTY29wZSBpbiBGdW5jdGlvbnMNCg0KVmFyaWFibGVzIGNyZWF0ZWQgKippbnNpZGUqKiBhIGZ1bmN0aW9uIGFyZSAqKmxvY2FsKiogdG8gdGhhdCBmdW5jdGlvbjoNCg0KYGBge3J9DQpteWZ1bmMgPC0gZnVuY3Rpb24oKSB7DQogIHggPC0gMTAgICMgTG9jYWwgdmFyaWFibGUNCiAgcHJpbnQoeCkNCn0NCm15ZnVuYygpDQpwcmludCh4KSAgIyBFcnJvcjogb2JqZWN0ICd4JyBub3QgZm91bmQNCmBgYA0KDQoNCi0tLQ0KDQojIyMgIFN1bW1hcnkgVGFibGUNCg0KfCBUeXBlICAgICAgICAgIHwgRGVzY3JpcHRpb24gICAgICAgICAgICAgICAgICAgICAgICAgIHwgRXhhbXBsZSAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwNCnwgQnVpbHQtaW4gICAgICB8IFByZWRlZmluZWQgUiBmdW5jdGlvbnMgICAgICAgICAgICAgICB8IGBzdW0oKWAsIGBtZWFuKClgLCBgc3FydCgpYCAgICAgICAgfA0KfCBVc2VyLWRlZmluZWQgIHwgRnVuY3Rpb25zIGNyZWF0ZWQgYnkgdXNlcnMgICAgICAgICAgIHwgYG15X2Z1bmN0aW9uIDwtIGZ1bmN0aW9uKCkgey4uLn1gICB8DQp8IFdpdGggZGVmYXVsdHMgfCBGdW5jdGlvbnMgd2l0aCBkZWZhdWx0IGFyZ3VtZW50IHZhbHMgfCBgZ3JlZXQgPC0gZnVuY3Rpb24obmFtZSA9ICJVc2VyIilgIHwNCnwgQW5vbnltb3VzICAgICB8IEZ1bmN0aW9ucyB3aXRob3V0IG5hbWUgICAgICAgICAgICAgICB8IGBmdW5jdGlvbih4KSB4KzFgIGluIGBzYXBwbHkoKWAgICAgfA0KDQotLS0NCg0K