setwd("D:/BTL/BTL XSTK/archive")
Warning: The working directory was changed to D:/BTL/BTL XSTK/archive inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
#Import data:
gpus = read.csv("All_GPUs.csv", header = TRUE)
gpus
# Khởi tạo danh sách các cột cần xóa
columns_to_remove <- c()
# Lặp qua từng cột trong dataframe 'gpus'
for (column in names(gpus)) {
numCellNAorBlank <- sum(is.na(gpus[[column]]) | gpus[[column]] == "" | gpus[[column]] == "\n- ")
numCell <- length(gpus[[column]])
napercentage <- numCellNAorBlank / numCell
print(paste(column, napercentage))
# Nếu phần trăm giá trị NA lớn hơn hoặc bằng 0.2, thêm tên cột vào danh sách cần xóa
if (napercentage >= 0.2) {
columns_to_remove <- c(columns_to_remove, column)
}
}
[1] "Architecture 0.0182031708749266"
[1] "Best_Resolution 0.188490898414563"
[1] "Boost_Clock 0.575455079271873"
[1] "Core_Speed 0.266294773928362"
[1] "DVI_Connection 0.220199647680564"
[1] "Dedicated 0.00411039342337052"
[1] "Direct_X 0.00176159718144451"
[1] "DisplayPort_Connection 0.748385202583676"
[1] "HDMI_Connection 0.224016441573693"
[1] "Integrated 0.00411039342337052"
[1] "L2_Cache 0"
[1] "Manufacturer 0"
[1] "Max_Power 0.18349970640047"
[1] "Memory 0.123311802701116"
[1] "Memory_Bandwidth 0.0355255431591309"
[1] "Memory_Bus 0.0182031708749266"
[1] "Memory_Speed 0.0308279506752789"
[1] "Memory_Type 0.0164415736934821"
[1] "Name 0"
[1] "Notebook_GPU 0"
[1] "Open_GL 0.0117439812096301"
[1] "PSU 0.344979448032883"
[1] "Pixel_Rate 0.159718144450969"
[1] "Power_Connector 0.208162066940693"
[1] "Process 0.135936582501468"
[1] "ROPs 0.157956547269524"
[1] "Release_Date 0"
[1] "Release_Price 0.836758661186142"
[1] "Resolution_WxH 0.0572519083969466"
[1] "SLI_Crossfire 0"
[1] "Shader 0.0314151497357604"
[1] "TMUs 0.157956547269524"
[1] "Texture_Rate 0.159718144450969"
[1] "VGA_Connection 0.22254844392249"
print("Các cột bị xóa:")
[1] "Các cột bị xóa:"
print(columns_to_remove)
[1] "Boost_Clock" "Core_Speed"
[3] "DVI_Connection" "DisplayPort_Connection"
[5] "HDMI_Connection" "PSU"
[7] "Power_Connector" "Release_Price"
[9] "VGA_Connection"
# Xóa tất cả các cột trong danh sách cần xóa
lessNA_gpus <- gpus[, !(names(gpus) %in% columns_to_remove)]
# In ra số lượng cột còn lại
print(paste("Số cột còn lại: ", length(names(lessNA_gpus))))
[1] "Số cột còn lại: 25"
#Bỏ một số cột không cần thiết/bị lỗi
rem_cols = c("ROPs", "L2_Cache", "Name", "Integrated", "Resolution_WxH", "Best_Resolution")
lessNA_gpus = lessNA_gpus[, !(names(lessNA_gpus) %in% rem_cols)]
names(lessNA_gpus)
[1] "Architecture" "Dedicated" "Direct_X"
[4] "Manufacturer" "Max_Power" "Memory"
[7] "Memory_Bandwidth" "Memory_Bus" "Memory_Speed"
[10] "Memory_Type" "Notebook_GPU" "Open_GL"
[13] "Pixel_Rate" "Process" "Release_Date"
[16] "SLI_Crossfire" "Shader" "TMUs"
[19] "Texture_Rate"
#Kiểm tra và xóa hàng trùng
duplicate_rows = lessNA_gpus[duplicated(lessNA_gpus),]
non_dup_gpus = unique(lessNA_gpus)
#Chuyển các cột categorical về dạng số
library(dplyr)
# Cài đặt và tải thư viện forcats
# install.packages("forcats")
library(forcats)
non_dup_gpus$Dedicated <- recode(non_dup_gpus$Dedicated, 'Yes' = 1, 'No' = 0)
Warning: Unreplaced values treated as NA as `.x` is not compatible.
non_dup_gpus$Direct_X <- fct_lump(non_dup_gpus$Direct_X, n = 5, other_level = "Other")
non_dup_gpus$Notebook_GPU <- recode(non_dup_gpus$Notebook_GPU, 'Yes' = 1, 'No' = 0)
non_dup_gpus$SLI_Crossfire <- recode(non_dup_gpus$SLI_Crossfire, 'Yes' = 1, 'No' = 0)
#Xử lý cột Release_Date, chuyển thành cột Release_Year
# Loại bỏ các khoảng trắng và dấu xuống dòng không cần thiết
non_dup_gpus$Release_Date <- trimws(non_dup_gpus$Release_Date)
# Chuyển đổi cột Release_Date thành đối tượng ngày
date_conversion <- as.Date(non_dup_gpus$Release_Date, format="%d-%b-%Y")
# Tìm các hàng có giá trị ngày hợp lệ
valid_dates <- !is.na(date_conversion)
# Giữ lại chỉ các hàng có giá trị ngày hợp lệ
non_dup_gpus <- non_dup_gpus[valid_dates, ]
# Tạo cột Release_Year và chuyển đổi thành số
non_dup_gpus$Release_Year <- as.numeric(format(date_conversion[valid_dates], "%Y"))
# Xóa cột Release_Date
non_dup_gpus$Release_Date <- NULL
# Bỏ đơn vị và chuyển các cột kiểu character thành kiểu số
non_dup_gpus$Max_Power <- as.numeric(gsub(" Watts", "", non_dup_gpus$Max_Power))
non_dup_gpus$Memory <- as.numeric(gsub(" MB", "", non_dup_gpus$Memory))
non_dup_gpus$Memory_Bandwidth <- as.numeric(gsub("GB/sec", "", non_dup_gpus$Memory_Bandwidth))
Warning: NAs introduced by coercion
non_dup_gpus$Memory_Bus <- as.numeric(gsub(" Bit", "", non_dup_gpus$Memory_Bus))
non_dup_gpus$Memory_Speed <- as.numeric(gsub(" MHz", "", non_dup_gpus$Memory_Speed))
non_dup_gpus$Pixel_Rate <- as.numeric(gsub(" GPixel/s", "", non_dup_gpus$Pixel_Rate))
non_dup_gpus$Process <- as.numeric(gsub("nm", "", non_dup_gpus$Process))
non_dup_gpus$TMUs <- as.numeric(non_dup_gpus$TMUs)
non_dup_gpus$Texture_Rate <- as.numeric(gsub(" GTexel/s", "", non_dup_gpus$Texture_Rate))
# Cài đặt và tải các thư viện cần thiết
# install.packages(c(tidyverse"))
library(tidyverse)
# In ra số dòng dữ liệu khuyết của mỗi cột
colSums(is.na(non_dup_gpus))
Architecture Dedicated Direct_X Manufacturer
0 14 0 0
Max_Power Memory Memory_Bandwidth Memory_Bus
579 337 118 57
Memory_Speed Memory_Type Notebook_GPU Open_GL
98 0 0 36
Pixel_Rate Process SLI_Crossfire Shader
503 423 0 83
TMUs Texture_Rate Release_Year
497 503 0
# Xử lý dữ liệu khuyết trên các cột kiểu số
# Tạo DataFrame gom nhóm theo Manufacturer
grouped_df <- non_dup_gpus %>% group_by(Manufacturer)
# Thay thế N/A bằng trung vị của nhóm
non_dup_gpus <- grouped_df %>% mutate_if(is.numeric, funs(ifelse(is.na(.) | . == "", median(., na.rm = TRUE), .)))
`mutate_if()` ignored the following grouping variables:Warning: `funs()` was deprecated in dplyr 0.8.0.
Please use a list of either functions or lambdas:
# Simple named list:
list(mean = mean, median = median)
# Auto named with `tibble::lst()`:
tibble::lst(mean, median)
# Using lambdas
list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
# Thay thế 0 bằng trung vị của cột
non_dup_gpus <- non_dup_gpus %>% mutate_if(is.numeric, funs(ifelse(. == 0, median(., na.rm = TRUE), .)))
`mutate_if()` ignored the following grouping variables:Warning: `funs()` was deprecated in dplyr 0.8.0.
Please use a list of either functions or lambdas:
# Simple named list:
list(mean = mean, median = median)
# Auto named with `tibble::lst()`:
tibble::lst(mean, median)
# Using lambdas
list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
# Xử lý dữ liệu khuyết trên các biến phân loại
# Thay thế N/A bằng giá trị có tần suất xuất hiện cao nhất
non_dup_gpus <- non_dup_gpus %>% mutate_if(is.factor, funs(ifelse(is.na(.) | . == "", names(which.max(table(.))), .)))
`mutate_if()` ignored the following grouping variables:Warning: `funs()` was deprecated in dplyr 0.8.0.
Please use a list of either functions or lambdas:
# Simple named list:
list(mean = mean, median = median)
# Auto named with `tibble::lst()`:
tibble::lst(mean, median)
# Using lambdas
list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
# Thay thế N/A hoặc rỗng bằng giá trị có tần suất xuất hiện cao nhất
non_dup_gpus <- non_dup_gpus %>% mutate_if(is.character, funs(ifelse(is.na(.) | . == "", names(which.max(table(na.omit(.[. != "" & . != " "])))), .)))
`mutate_if()` ignored the following grouping variables:Warning: `funs()` was deprecated in dplyr 0.8.0.
Please use a list of either functions or lambdas:
# Simple named list:
list(mean = mean, median = median)
# Auto named with `tibble::lst()`:
tibble::lst(mean, median)
# Using lambdas
list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
# Bỏ đi biến Manufacturer
non_dup_gpus$Manufacturer <- NULL
# Kiểm tra lại số dòng dữ liệu N/A
colSums(is.na(non_dup_gpus) | non_dup_gpus == "")
Architecture Dedicated Direct_X Max_Power
0 0 0 0
Memory Memory_Bandwidth Memory_Bus Memory_Speed
0 0 0 0
Memory_Type Notebook_GPU Open_GL Pixel_Rate
0 0 0 0
Process SLI_Crossfire Shader TMUs
0 0 0 0
Texture_Rate Release_Year
0 0
new_gpus = non_dup_gpus
# Cài đặt và tải gói writexl
install.packages('writexl')
Error in install.packages : Updating loaded packages
library(writexl)
# Lưu DataFrame thành file Excel
write_xlsx(new_gpus, 'new_GPUs.xlsx')
#THỐNG KÊ TẢ
#Tính trung bình mẫu
mean<-apply(non_dup_gpus[,c("Memory","Memory_Bandwidth","Memory_Bus","Memory_Speed",
"Open_GL", "Pixel_Rate","Shader","TMUs","Texture_Rate",
"Release_Year","Direct_X")], 2, mean)
#Tính độ lệch chuẩn
sd<-apply(non_dup_gpus[,c("Memory","Memory_Bandwidth","Memory_Bus","Memory_Speed",
"Open_GL", "Pixel_Rate","Shader","TMUs","Texture_Rate",
"Release_Year","Direct_X")], 2, sd)
#Tính phân vị 1
Q1<-apply(non_dup_gpus[,c("Memory","Memory_Bandwidth","Memory_Bus","Memory_Speed",
"Open_GL", "Pixel_Rate","Shader","TMUs","Texture_Rate",
"Release_Year","Direct_X")], 2, quantile, probs = 0.25)
#Tính trung vị
med<-apply(non_dup_gpus[,c("Memory","Memory_Bandwidth","Memory_Bus","Memory_Speed",
"Open_GL", "Pixel_Rate","Shader","TMUs","Texture_Rate",
"Release_Year","Direct_X")], 2, median)
#Tính phân vị 3
Q3<-apply(non_dup_gpus[,c("Memory","Memory_Bandwidth","Memory_Bus","Memory_Speed",
"Open_GL", "Pixel_Rate","Shader","TMUs","Texture_Rate",
"Release_Year","Direct_X")], 2, quantile, probs = 0.75)
#Tính giá trị lớn nhất
Max<-apply(non_dup_gpus[,c("Memory","Memory_Bandwidth","Memory_Bus","Memory_Speed",
"Open_GL", "Pixel_Rate","Shader","TMUs","Texture_Rate",
"Release_Year","Direct_X")], 2, max)
#Tính giá trị nhỏ nhất
Min<-apply(non_dup_gpus[,c("Memory","Memory_Bandwidth","Memory_Bus","Memory_Speed",
"Open_GL", "Pixel_Rate","Shader","TMUs","Texture_Rate",
"Release_Year","Direct_X")], 2, min)
data.frame(mean, sd, Q1, med, Q3, Max, Min)
#VẼ ĐỒ THJ PHÂN PHỐI CỦA BIẾN Memory_Speed
hist(non_dup_gpus$Memory_Speed, main = "Histogram of Memory_Speed", xlab = "Memory_Speed",
xlim = c(0,2500), ylim = c(0,600), labels=T, col = "lightblue", border = "darkblue",
freq = TRUE
)

#VẼ ĐỒ THỊ PHÂN PHỐI CỦA BIẾN Memory_Speed THEO BIẾN Memory
plot(non_dup_gpus$Memory_Speed~non_dup_gpus$Memory,
main = "Memory_Speed by Memory",
xlab = "Memory",
ylab = "Memory_Speed",
col = "navy"
)
abline(lm(Memory_Speed~Memory,data=non_dup_gpus),col="red3")

#VẼ ĐỒ THỊ PHÂN PHỐI CỦA BIẾN Memory_Speed THEO BIẾN Memory_Bandwidth
plot(non_dup_gpus$Memory_Speed~non_dup_gpus$Memory_Bandwidth,
main = "Memory_Speed by Memory_Bandwidth",
xlab = "Memory_Bandwidth",
ylab = "Memory_Speed",
col = "darkblue"
)
abline(lm(Memory_Speed~Memory_Bandwidth,data=non_dup_gpus),col="red3")

#VẼ ĐỒ THỊ PHÂN PHỐI CỦA BIẾN Memory_Speed THEO BIẾN Memory_Bus
plot(non_dup_gpus$Memory_Speed~non_dup_gpus$Memory_Bus,
main = "Memory_Speed by Memory_Bus",
xlab = "Memory_Bus",
ylab = "Memory_Speed",
col = "darkgreen"
)
abline(lm(Memory_Speed~Memory_Bandwidth,data=non_dup_gpus),col="red3")

D#VẼ ĐỒ THỊ PHÂN PHỐI CỦA BIẾN Memory_Speed THEO BIẾN Open_GL
function (expr, name)
.External(C_doD, expr, name)
<bytecode: 0x0000021aacfd50a0>
<environment: namespace:stats>
plot(non_dup_gpus$Memory_Speed~non_dup_gpus$Open_GL,
main = "Memory_Speed by Open_GL",
xlab = "Open_GL",
ylab = "Memory_Speed",
col = "red4"
)
abline(lm(Memory_Speed~Open_GL,data=non_dup_gpus),col="red3")

#VẼ ĐỒ THỊ PHÂN PHỐI CỦA BIẾN Memory_Speed THEO BIẾN Direct_X
plot(non_dup_gpus$Memory_Speed~non_dup_gpus$Direct_X,
main = "Memory_Speed by Direct_X",
xlab = "Direct_X",
ylab = "Memory_Speed",
col = "seagreen"
)
abline(lm(Memory_Speed~Direct_X,data=non_dup_gpus),col="red3")

#VẼ ĐỒ THỊ PHÂN PHỐI CỦA BIẾN Memory_Speed THEO BIẾN Release_Year
plot(non_dup_gpus$Memory_Speed~non_dup_gpus$Release_Year,
main = "Memory_Speed by Release_Year",
xlab = "Release_Year",
ylab = "Memory_Speed",
col = "navy"
)
abline(lm(Memory_Speed~Release_Year,data=non_dup_gpus),col="red3")

###########################1Way-ANOVA#######################################
#Xử lí và lọc dữ liệu#
type_table<-table(non_dup_gpus$Memory_Type)
print(type_table)
DDR DDR2 DDR3 DDR4 eDRAM GDDR2 GDDR3 GDDR4 GDDR5 GDDR5X HBM-1
110 99 593 27 3 4 293 8 1679 46 6
HBM-2
6
data_filtered <- non_dup_gpus[non_dup_gpus$Memory_Type %in% names(type_table[type_table > 10]), ]
table(data_filtered$Memory_Type)
DDR DDR2 DDR3 DDR4 GDDR3 GDDR5 GDDR5X
110 99 593 27 293 1679 46
#Kiểm tra PP CHuẩn#
qqnorm(non_dup_gpus$Memory_Speed)
qqline(non_dup_gpus$Memory_Speed)

#Kiểm tra tương đồng phuong sai#
bartlett.test(Memory_Speed~Memory_Type,data=data_filtered)
Bartlett test of homogeneity of variances
data: Memory_Speed by Memory_Type
Bartlett's K-squared = 833.85, df = 6, p-value < 2.2e-16
#Thực hiện anova#
anova_model1<-aov(Memory_Speed~Memory_Type,data=data_filtered)
summary(anova_model1)
Df Sum Sq Mean Sq F value Pr(>F)
Memory_Type 6 312350848 52058475 677.2 <2e-16 ***
Residuals 2840 218320676 76873
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#So sánh bội#
TukeyHSD(anova_model1)
Tukey multiple comparisons of means
95% family-wise confidence level
Fit: aov(formula = Memory_Speed ~ Memory_Type, data = data_filtered)
$Memory_Type
diff lwr upr p adj
DDR2-DDR 263.73535 150.40808 377.0626 0.0000000
DDR3-DDR 498.17271 413.24895 583.0965 0.0000000
DDR4-DDR 750.34478 574.65063 926.0389 0.0000000
GDDR3-DDR 470.51492 379.04094 561.9889 0.0000000
GDDR5-DDR 1074.24066 993.72901 1154.7523 0.0000000
GDDR5X-DDR 1022.96877 879.33311 1166.6044 0.0000000
DDR3-DDR2 234.43736 145.62297 323.2518 0.0000000
DDR4-DDR2 486.60943 309.00204 664.2168 0.0000000
GDDR3-DDR2 206.77957 111.68256 301.8766 0.0000000
GDDR5-DDR2 810.50531 725.89989 895.1107 0.0000000
GDDR5X-DDR2 759.23342 613.26372 905.2031 0.0000000
DDR4-DDR3 252.17207 91.19580 413.1483 0.0000811
GDDR3-DDR3 -27.65779 -86.07367 30.7581 0.8037118
GDDR5-DDR3 576.06795 536.99046 615.1454 0.0000000
GDDR5X-DDR3 524.79606 399.59171 650.0004 0.0000000
GDDR3-DDR4 -279.82986 -444.35586 -115.3039 0.0000115
GDDR5-DDR4 323.89588 165.20297 482.5888 0.0000000
GDDR5X-DDR4 272.62399 74.29972 470.9483 0.0010074
GDDR5-GDDR3 603.72574 551.93292 655.5186 0.0000000
GDDR5X-GDDR3 552.45385 422.71729 682.1904 0.0000000
GDDR5X-GDDR5 -51.27189 -173.52658 70.9828 0.8795677
################################2WAY ANOVA#########################
#XỬ lý và lọc dữ liệu
year_table<-table(data_filtered$Release_Year)
print(year_table)
1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012
2 7 5 10 28 28 36 36 76 101 130 107 232 291 478
2013 2014 2015 2016 2017
414 311 288 177 90
data_filtered2<-data_filtered[data_filtered$Release_Year %in% names(year_table[year_table > 10]), ]
table(data_filtered2$Release_Year)
2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
28 28 36 36 76 101 130 107 232 291 478 414 311 288 177
2017
90
#Kiểm tra sự tương đồng phương sai#
data_filtered2$Release_Year<-as.character(data_filtered2$Release_Year) #chuyển sang char
bartlett.test(Memory_Speed~Release_Year,data=data_filtered2)
Bartlett test of homogeneity of variances
data: Memory_Speed by Release_Year
Bartlett's K-squared = 227.11, df = 15, p-value < 2.2e-16
#Thực hiện anova 2 nhân tố#
anova_model2<-aov(Memory_Speed~Memory_Type*Release_Year,data=data_filtered2)
summary(anova_model2)
Df Sum Sq Mean Sq F value Pr(>F)
Memory_Type 6 293160338 48860056 1280.08 <2e-16 ***
Release_Year 15 95723756 6381584 167.19 <2e-16 ***
Memory_Type:Release_Year 37 14919360 403226 10.56 <2e-16 ***
Residuals 2764 105500720 38170
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
## Xay dung mo hinh hoi quy ##
model <- lm(Memory_Speed ~ Memory_Type + Release_Year,data=non_dup_gpus)
summary(model)
Call:
lm(formula = Memory_Speed ~ Memory_Type + Release_Year, data = non_dup_gpus)
Residuals:
Min 1Q Median 3Q Max
-1137.14 -152.60 -6.77 144.76 892.46
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.637e+05 4.160e+03 -39.351 < 2e-16 ***
Memory_TypeDDR2 -9.522e+01 3.213e+01 -2.963 0.00307 **
Memory_TypeDDR3 -2.519e+02 2.992e+01 -8.420 < 2e-16 ***
Memory_TypeDDR4 -2.646e+02 5.427e+01 -4.877 1.14e-06 ***
Memory_TypeeDRAM -4.236e+02 1.324e+02 -3.200 0.00139 **
Memory_TypeGDDR2 -2.215e+02 1.136e+02 -1.951 0.05117 .
Memory_TypeGDDR3 5.834e+01 2.698e+01 2.163 0.03066 *
Memory_TypeGDDR4 3.686e+02 8.196e+01 4.497 7.16e-06 ***
Memory_TypeGDDR5 2.328e+02 3.057e+01 7.613 3.61e-14 ***
Memory_TypeGDDR5X -1.164e+02 4.858e+01 -2.397 0.01661 *
Memory_TypeHBM-1 -8.361e+02 9.677e+01 -8.641 < 2e-16 ***
Memory_TypeHBM-2 -9.453e+02 9.754e+01 -9.692 < 2e-16 ***
Release_Year 8.190e+01 2.077e+00 39.427 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 222.4 on 2861 degrees of freedom
Multiple R-squared: 0.7368, Adjusted R-squared: 0.7357
F-statistic: 667.5 on 12 and 2861 DF, p-value: < 2.2e-16
filtered_non_dup_gpus <- non_dup_gpus[non_dup_gpus$Memory_Type != "GDDR3", ]
model <- lm(Memory_Speed ~ Memory_Type + Release_Year,data=filtered_non_dup_gpus)
summary(model)
Call:
lm(formula = Memory_Speed ~ Memory_Type + Release_Year, data = filtered_non_dup_gpus)
Residuals:
Min 1Q Median 3Q Max
-1149.97 -155.31 0.03 160.53 870.26
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.722e+05 4.363e+03 -39.477 < 2e-16 ***
Memory_TypeDDR2 -1.139e+02 3.250e+01 -3.505 0.000464 ***
Memory_TypeDDR3 -2.910e+02 3.066e+01 -9.491 < 2e-16 ***
Memory_TypeDDR4 -3.175e+02 5.521e+01 -5.751 9.94e-09 ***
Memory_TypeeDRAM -4.731e+02 1.336e+02 -3.541 0.000406 ***
Memory_TypeGDDR2 -2.398e+02 1.145e+02 -2.094 0.036339 *
Memory_TypeGDDR4 3.498e+02 8.267e+01 4.231 2.40e-05 ***
Memory_TypeGDDR5 1.889e+02 3.143e+01 6.010 2.11e-09 ***
Memory_TypeGDDR5X -1.758e+02 4.969e+01 -3.538 0.000411 ***
Memory_TypeHBM-1 -8.892e+02 9.783e+01 -9.089 < 2e-16 ***
Memory_TypeHBM-2 -1.004e+03 9.868e+01 -10.176 < 2e-16 ***
Release_Year 8.617e+01 2.179e+00 39.550 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 224.2 on 2569 degrees of freedom
Multiple R-squared: 0.7357, Adjusted R-squared: 0.7345
F-statistic: 649.9 on 11 and 2569 DF, p-value: < 2.2e-16
op <- par(mfrow=c(2,2))
plot(model)

LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCnNldHdkKCJEOi9CVEwvQlRMIFhTVEsvYXJjaGl2ZSIpDQoNCiNJbXBvcnQgZGF0YToNCmdwdXMgPSByZWFkLmNzdigiQWxsX0dQVXMuY3N2IiwgaGVhZGVyID0gVFJVRSkNCmdwdXMNCmBgYA0KDQpgYGB7cn0NCiMgS2jhu59pIHThuqFvIGRhbmggc8OhY2ggY8OhYyBj4buZdCBj4bqnbiB4w7NhDQpjb2x1bW5zX3RvX3JlbW92ZSA8LSBjKCkNCg0KIyBM4bq3cCBxdWEgdOG7q25nIGPhu5l0IHRyb25nIGRhdGFmcmFtZSAnZ3B1cycNCmZvciAoY29sdW1uIGluIG5hbWVzKGdwdXMpKSB7DQogIG51bUNlbGxOQW9yQmxhbmsgPC0gc3VtKGlzLm5hKGdwdXNbW2NvbHVtbl1dKSB8IGdwdXNbW2NvbHVtbl1dID09ICIiIHwgZ3B1c1tbY29sdW1uXV0gPT0gIlxuLSAiKQ0KICBudW1DZWxsIDwtIGxlbmd0aChncHVzW1tjb2x1bW5dXSkNCiAgbmFwZXJjZW50YWdlIDwtIG51bUNlbGxOQW9yQmxhbmsgLyBudW1DZWxsDQogIHByaW50KHBhc3RlKGNvbHVtbiwgbmFwZXJjZW50YWdlKSkNCiAgIyBO4bq/dSBwaOG6p24gdHLEg20gZ2nDoSB0cuG7iyBOQSBs4bubbiBoxqFuIGhv4bq3YyBi4bqxbmcgMC4yLCB0aMOqbSB0w6puIGPhu5l0IHbDoG8gZGFuaCBzw6FjaCBj4bqnbiB4w7NhDQogIGlmIChuYXBlcmNlbnRhZ2UgPj0gMC4yKSB7DQogICAgY29sdW1uc190b19yZW1vdmUgPC0gYyhjb2x1bW5zX3RvX3JlbW92ZSwgY29sdW1uKQ0KICB9DQp9DQpwcmludCgiQ8OhYyBj4buZdCBi4buLIHjDs2E6IikNCnByaW50KGNvbHVtbnNfdG9fcmVtb3ZlKQ0KIyBYw7NhIHThuqV0IGPhuqMgY8OhYyBj4buZdCB0cm9uZyBkYW5oIHPDoWNoIGPhuqduIHjDs2ENCmxlc3NOQV9ncHVzIDwtIGdwdXNbLCAhKG5hbWVzKGdwdXMpICVpbiUgY29sdW1uc190b19yZW1vdmUpXQ0KDQojIEluIHJhIHPhu5EgbMaw4bujbmcgY+G7mXQgY8OybiBs4bqhaQ0KcHJpbnQocGFzdGUoIlPhu5EgY+G7mXQgY8OybiBs4bqhaTogIiwgbGVuZ3RoKG5hbWVzKGxlc3NOQV9ncHVzKSkpKQ0KDQpgYGANCg0KYGBge3J9DQojQuG7jyBt4buZdCBz4buRIGPhu5l0IGtow7RuZyBj4bqnbiB0aGnhur90L2Lhu4sgbOG7l2kNCnJlbV9jb2xzID0gYygiUk9QcyIsICJMMl9DYWNoZSIsICJOYW1lIiwgIkludGVncmF0ZWQiLCAiUmVzb2x1dGlvbl9XeEgiLCAiQmVzdF9SZXNvbHV0aW9uIikNCmxlc3NOQV9ncHVzID0gbGVzc05BX2dwdXNbLCAhKG5hbWVzKGxlc3NOQV9ncHVzKSAlaW4lIHJlbV9jb2xzKV0NCm5hbWVzKGxlc3NOQV9ncHVzKQ0KYGBgDQoNCmBgYHtyfQ0KI0tp4buDbSB0cmEgdsOgIHjDs2EgaMOgbmcgdHLDuW5nDQpkdXBsaWNhdGVfcm93cyA9IGxlc3NOQV9ncHVzW2R1cGxpY2F0ZWQobGVzc05BX2dwdXMpLF0NCm5vbl9kdXBfZ3B1cyA9IHVuaXF1ZShsZXNzTkFfZ3B1cykNCmBgYA0KDQpgYGB7cn0NCiNDaHV54buDbiBjw6FjIGPhu5l0IGNhdGVnb3JpY2FsIHbhu4EgZOG6oW5nIHPhu5ENCmxpYnJhcnkoZHBseXIpDQojIEPDoGkgxJHhurd0IHbDoCB04bqjaSB0aMawIHZp4buHbiBmb3JjYXRzDQojIGluc3RhbGwucGFja2FnZXMoImZvcmNhdHMiKQ0KbGlicmFyeShmb3JjYXRzKQ0KDQpub25fZHVwX2dwdXMkRGVkaWNhdGVkIDwtIHJlY29kZShub25fZHVwX2dwdXMkRGVkaWNhdGVkLCAnWWVzJyA9IDEsICdObycgPSAwKQ0Kbm9uX2R1cF9ncHVzJERpcmVjdF9YIDwtIGZjdF9sdW1wKG5vbl9kdXBfZ3B1cyREaXJlY3RfWCwgbiA9IDUsIG90aGVyX2xldmVsID0gIk90aGVyIikNCm5vbl9kdXBfZ3B1cyROb3RlYm9va19HUFUgPC0gcmVjb2RlKG5vbl9kdXBfZ3B1cyROb3RlYm9va19HUFUsICdZZXMnID0gMSwgJ05vJyA9IDApDQpub25fZHVwX2dwdXMkU0xJX0Nyb3NzZmlyZSA8LSByZWNvZGUobm9uX2R1cF9ncHVzJFNMSV9Dcm9zc2ZpcmUsICdZZXMnID0gMSwgJ05vJyA9IDApDQoNCg0KYGBgDQoNCmBgYHtyfQ0KI1jhu60gbMO9IGPhu5l0IFJlbGVhc2VfRGF0ZSwgY2h1eeG7g24gdGjDoG5oIGPhu5l0IFJlbGVhc2VfWWVhcg0KIyBMb+G6oWkgYuG7jyBjw6FjIGtob+G6o25nIHRy4bqvbmcgdsOgIGThuqV1IHh14buRbmcgZMOybmcga2jDtG5nIGPhuqduIHRoaeG6v3QNCm5vbl9kdXBfZ3B1cyRSZWxlYXNlX0RhdGUgPC0gdHJpbXdzKG5vbl9kdXBfZ3B1cyRSZWxlYXNlX0RhdGUpDQoNCiMgQ2h1eeG7g24gxJHhu5VpIGPhu5l0IFJlbGVhc2VfRGF0ZSB0aMOgbmggxJHhu5FpIHTGsOG7o25nIG5nw6B5DQpkYXRlX2NvbnZlcnNpb24gPC0gYXMuRGF0ZShub25fZHVwX2dwdXMkUmVsZWFzZV9EYXRlLCBmb3JtYXQ9IiVkLSViLSVZIikNCg0KIyBUw6xtIGPDoWMgaMOgbmcgY8OzIGdpw6EgdHLhu4sgbmfDoHkgaOG7o3AgbOG7hw0KdmFsaWRfZGF0ZXMgPC0gIWlzLm5hKGRhdGVfY29udmVyc2lvbikNCg0KIyBHaeG7ryBs4bqhaSBjaOG7iSBjw6FjIGjDoG5nIGPDsyBnacOhIHRy4buLIG5nw6B5IGjhu6NwIGzhu4cNCm5vbl9kdXBfZ3B1cyA8LSBub25fZHVwX2dwdXNbdmFsaWRfZGF0ZXMsIF0NCg0KIyBU4bqhbyBj4buZdCBSZWxlYXNlX1llYXIgdsOgIGNodXnhu4NuIMSR4buVaSB0aMOgbmggc+G7kQ0Kbm9uX2R1cF9ncHVzJFJlbGVhc2VfWWVhciA8LSBhcy5udW1lcmljKGZvcm1hdChkYXRlX2NvbnZlcnNpb25bdmFsaWRfZGF0ZXNdLCAiJVkiKSkNCg0KIyBYw7NhIGPhu5l0IFJlbGVhc2VfRGF0ZQ0Kbm9uX2R1cF9ncHVzJFJlbGVhc2VfRGF0ZSA8LSBOVUxMDQoNCg0KIyBC4buPIMSRxqFuIHbhu4sgdsOgIGNodXnhu4NuIGPDoWMgY+G7mXQga2nhu4N1IGNoYXJhY3RlciB0aMOgbmgga2nhu4N1IHPhu5ENCm5vbl9kdXBfZ3B1cyRNYXhfUG93ZXIgPC0gYXMubnVtZXJpYyhnc3ViKCIgV2F0dHMiLCAiIiwgbm9uX2R1cF9ncHVzJE1heF9Qb3dlcikpDQpub25fZHVwX2dwdXMkTWVtb3J5IDwtIGFzLm51bWVyaWMoZ3N1YigiIE1CIiwgIiIsIG5vbl9kdXBfZ3B1cyRNZW1vcnkpKQ0Kbm9uX2R1cF9ncHVzJE1lbW9yeV9CYW5kd2lkdGggPC0gYXMubnVtZXJpYyhnc3ViKCJHQi9zZWMiLCAiIiwgbm9uX2R1cF9ncHVzJE1lbW9yeV9CYW5kd2lkdGgpKQ0Kbm9uX2R1cF9ncHVzJE1lbW9yeV9CdXMgPC0gYXMubnVtZXJpYyhnc3ViKCIgQml0IiwgIiIsIG5vbl9kdXBfZ3B1cyRNZW1vcnlfQnVzKSkNCm5vbl9kdXBfZ3B1cyRNZW1vcnlfU3BlZWQgPC0gYXMubnVtZXJpYyhnc3ViKCIgTUh6IiwgIiIsIG5vbl9kdXBfZ3B1cyRNZW1vcnlfU3BlZWQpKQ0Kbm9uX2R1cF9ncHVzJFBpeGVsX1JhdGUgPC0gYXMubnVtZXJpYyhnc3ViKCIgR1BpeGVsL3MiLCAiIiwgbm9uX2R1cF9ncHVzJFBpeGVsX1JhdGUpKQ0Kbm9uX2R1cF9ncHVzJFByb2Nlc3MgPC0gYXMubnVtZXJpYyhnc3ViKCJubSIsICIiLCBub25fZHVwX2dwdXMkUHJvY2VzcykpDQpub25fZHVwX2dwdXMkVE1VcyA8LSBhcy5udW1lcmljKG5vbl9kdXBfZ3B1cyRUTVVzKQ0Kbm9uX2R1cF9ncHVzJFRleHR1cmVfUmF0ZSA8LSBhcy5udW1lcmljKGdzdWIoIiBHVGV4ZWwvcyIsICIiLCBub25fZHVwX2dwdXMkVGV4dHVyZV9SYXRlKSkNCmBgYA0KDQpgYGB7cn0NCiMgQ8OgaSDEkeG6t3QgdsOgIHThuqNpIGPDoWMgdGjGsCB2aeG7h24gY+G6p24gdGhp4bq/dA0KIyBpbnN0YWxsLnBhY2thZ2VzKGModGlkeXZlcnNlIikpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KIyBJbiByYSBz4buRIGTDsm5nIGThu68gbGnhu4d1IGtodXnhur90IGPhu6dhIG3hu5dpIGPhu5l0DQpjb2xTdW1zKGlzLm5hKG5vbl9kdXBfZ3B1cykpDQoNCiMgWOG7rSBsw70gZOG7ryBsaeG7h3Uga2h1eeG6v3QgdHLDqm4gY8OhYyBj4buZdCBraeG7g3Ugc+G7kQ0KIyBU4bqhbyBEYXRhRnJhbWUgZ29tIG5ow7NtIHRoZW8gTWFudWZhY3R1cmVyDQpncm91cGVkX2RmIDwtIG5vbl9kdXBfZ3B1cyAlPiUgZ3JvdXBfYnkoTWFudWZhY3R1cmVyKQ0KDQojIFRoYXkgdGjhur8gTi9BIGLhurFuZyB0cnVuZyB24buLIGPhu6dhIG5ow7NtDQpub25fZHVwX2dwdXMgPC0gZ3JvdXBlZF9kZiAlPiUgbXV0YXRlX2lmKGlzLm51bWVyaWMsIGZ1bnMoaWZlbHNlKGlzLm5hKC4pIHwgLiA9PSAiIiwgbWVkaWFuKC4sIG5hLnJtID0gVFJVRSksIC4pKSkNCg0KIyBUaGF5IHRo4bq/IDAgYuG6sW5nIHRydW5nIHbhu4sgY+G7p2EgY+G7mXQNCm5vbl9kdXBfZ3B1cyA8LSBub25fZHVwX2dwdXMgJT4lIG11dGF0ZV9pZihpcy5udW1lcmljLCBmdW5zKGlmZWxzZSguID09IDAsIG1lZGlhbiguLCBuYS5ybSA9IFRSVUUpLCAuKSkpDQoNCiMgWOG7rSBsw70gZOG7ryBsaeG7h3Uga2h1eeG6v3QgdHLDqm4gY8OhYyBiaeG6v24gcGjDom4gbG/huqFpDQojIFRoYXkgdGjhur8gTi9BIGLhurFuZyBnacOhIHRy4buLIGPDsyB04bqnbiBzdeG6pXQgeHXhuqV0IGhp4buHbiBjYW8gbmjhuqV0DQpub25fZHVwX2dwdXMgPC0gbm9uX2R1cF9ncHVzICU+JSBtdXRhdGVfaWYoaXMuZmFjdG9yLCBmdW5zKGlmZWxzZShpcy5uYSguKSB8IC4gPT0gIiIsIG5hbWVzKHdoaWNoLm1heCh0YWJsZSguKSkpLCAuKSkpDQoNCiMgVGhheSB0aOG6vyBOL0EgaG/hurdjIHLhu5duZyBi4bqxbmcgZ2nDoSB0cuG7iyBjw7MgdOG6p24gc3XhuqV0IHh14bqldCBoaeG7h24gY2FvIG5o4bqldA0Kbm9uX2R1cF9ncHVzIDwtIG5vbl9kdXBfZ3B1cyAlPiUgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgZnVucyhpZmVsc2UoaXMubmEoLikgfCAuID09ICIiLCBuYW1lcyh3aGljaC5tYXgodGFibGUobmEub21pdCguWy4gIT0gIiIgJiAuICE9ICIgIl0pKSkpLCAuKSkpDQoNCg0KIyBC4buPIMSRaSBiaeG6v24gTWFudWZhY3R1cmVyDQpub25fZHVwX2dwdXMkTWFudWZhY3R1cmVyIDwtIE5VTEwNCg0KIyBLaeG7g20gdHJhIGzhuqFpIHPhu5EgZMOybmcgZOG7ryBsaeG7h3UgTi9BDQpjb2xTdW1zKGlzLm5hKG5vbl9kdXBfZ3B1cykgfCBub25fZHVwX2dwdXMgPT0gIiIpDQoNCmBgYA0KDQpgYGB7cn0NCm5ld19ncHVzID0gbm9uX2R1cF9ncHVzDQojIEPDoGkgxJHhurd0IHbDoCB04bqjaSBnw7NpIHdyaXRleGwNCmluc3RhbGwucGFja2FnZXMoJ3dyaXRleGwnKQ0KbGlicmFyeSh3cml0ZXhsKQ0KDQoNCiMgTMawdSBEYXRhRnJhbWUgdGjDoG5oIGZpbGUgRXhjZWwNCndyaXRlX3hsc3gobmV3X2dwdXMsICduZXdfR1BVcy54bHN4JykNCg0KYGBgDQoNCmBgYHtyfQ0KI1RI4buQTkcgS8OKIFThuqINCiNUw61uaCB0cnVuZyBiw6xuaCBt4bqrdQ0KbWVhbjwtYXBwbHkobm9uX2R1cF9ncHVzWyxjKCJNZW1vcnkiLCJNZW1vcnlfQmFuZHdpZHRoIiwiTWVtb3J5X0J1cyIsIk1lbW9yeV9TcGVlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9wZW5fR0wiLCAiUGl4ZWxfUmF0ZSIsIlNoYWRlciIsIlRNVXMiLCJUZXh0dXJlX1JhdGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWxlYXNlX1llYXIiLCJEaXJlY3RfWCIpXSwgMiwgbWVhbikNCiNUw61uaCDEkeG7mSBs4buHY2ggY2h14bqpbg0Kc2Q8LWFwcGx5KG5vbl9kdXBfZ3B1c1ssYygiTWVtb3J5IiwiTWVtb3J5X0JhbmR3aWR0aCIsIk1lbW9yeV9CdXMiLCJNZW1vcnlfU3BlZWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiT3Blbl9HTCIsICJQaXhlbF9SYXRlIiwiU2hhZGVyIiwiVE1VcyIsIlRleHR1cmVfUmF0ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJSZWxlYXNlX1llYXIiLCJEaXJlY3RfWCIpXSwgMiwgc2QpDQojVMOtbmggcGjDom4gduG7iyAxDQpRMTwtYXBwbHkobm9uX2R1cF9ncHVzWyxjKCJNZW1vcnkiLCJNZW1vcnlfQmFuZHdpZHRoIiwiTWVtb3J5X0J1cyIsIk1lbW9yeV9TcGVlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJPcGVuX0dMIiwgIlBpeGVsX1JhdGUiLCJTaGFkZXIiLCJUTVVzIiwiVGV4dHVyZV9SYXRlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlbGVhc2VfWWVhciIsIkRpcmVjdF9YIildLCAyLCBxdWFudGlsZSwgcHJvYnMgPSAwLjI1KQ0KI1TDrW5oIHRydW5nIHbhu4sNCm1lZDwtYXBwbHkobm9uX2R1cF9ncHVzWyxjKCJNZW1vcnkiLCJNZW1vcnlfQmFuZHdpZHRoIiwiTWVtb3J5X0J1cyIsIk1lbW9yeV9TcGVlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAiT3Blbl9HTCIsICJQaXhlbF9SYXRlIiwiU2hhZGVyIiwiVE1VcyIsIlRleHR1cmVfUmF0ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVsZWFzZV9ZZWFyIiwiRGlyZWN0X1giKV0sIDIsIG1lZGlhbikNCiNUw61uaCBwaMOibiB24buLIDMNClEzPC1hcHBseShub25fZHVwX2dwdXNbLGMoIk1lbW9yeSIsIk1lbW9yeV9CYW5kd2lkdGgiLCJNZW1vcnlfQnVzIiwiTWVtb3J5X1NwZWVkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIk9wZW5fR0wiLCAiUGl4ZWxfUmF0ZSIsIlNoYWRlciIsIlRNVXMiLCJUZXh0dXJlX1JhdGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVsZWFzZV9ZZWFyIiwiRGlyZWN0X1giKV0sIDIsIHF1YW50aWxlLCBwcm9icyA9IDAuNzUpDQojVMOtbmggZ2nDoSB0cuG7iyBs4bubbiBuaOG6pXQNCk1heDwtYXBwbHkobm9uX2R1cF9ncHVzWyxjKCJNZW1vcnkiLCJNZW1vcnlfQmFuZHdpZHRoIiwiTWVtb3J5X0J1cyIsIk1lbW9yeV9TcGVlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAiT3Blbl9HTCIsICJQaXhlbF9SYXRlIiwiU2hhZGVyIiwiVE1VcyIsIlRleHR1cmVfUmF0ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVsZWFzZV9ZZWFyIiwiRGlyZWN0X1giKV0sIDIsIG1heCkNCiNUw61uaCBnacOhIHRy4buLIG5o4buPIG5o4bqldA0KTWluPC1hcHBseShub25fZHVwX2dwdXNbLGMoIk1lbW9yeSIsIk1lbW9yeV9CYW5kd2lkdGgiLCJNZW1vcnlfQnVzIiwiTWVtb3J5X1NwZWVkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT3Blbl9HTCIsICJQaXhlbF9SYXRlIiwiU2hhZGVyIiwiVE1VcyIsIlRleHR1cmVfUmF0ZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlbGVhc2VfWWVhciIsIkRpcmVjdF9YIildLCAyLCBtaW4pDQpkYXRhLmZyYW1lKG1lYW4sIHNkLCBRMSwgbWVkLCBRMywgTWF4LCBNaW4pDQoNCiNW4bq8IMSQ4buSIFRISiBQSMOCTiBQSOG7kEkgQ+G7pkEgQknhur5OIE1lbW9yeV9TcGVlZA0KaGlzdChub25fZHVwX2dwdXMkTWVtb3J5X1NwZWVkLCBtYWluID0gIkhpc3RvZ3JhbSBvZiBNZW1vcnlfU3BlZWQiLCB4bGFiID0gIk1lbW9yeV9TcGVlZCIsDQogICAgIHhsaW0gPSBjKDAsMjUwMCksIHlsaW0gPSBjKDAsNjAwKSwgbGFiZWxzPVQsIGNvbCA9ICJsaWdodGJsdWUiLCBib3JkZXIgPSAiZGFya2JsdWUiLA0KICAgICBmcmVxID0gVFJVRQ0KKQ0KDQpgYGANCg0KDQpgYGB7cn0NCiNW4bq8IMSQ4buSIFRI4buKIFBIw4JOIFBI4buQSSBD4bumQSBCSeG6vk4gTWVtb3J5X1NwZWVkIFRIRU8gQknhur5OIE1lbW9yeQ0KcGxvdChub25fZHVwX2dwdXMkTWVtb3J5X1NwZWVkfm5vbl9kdXBfZ3B1cyRNZW1vcnksDQogICAgIG1haW4gPSAiTWVtb3J5X1NwZWVkIGJ5IE1lbW9yeSIsDQogICAgIHhsYWIgPSAiTWVtb3J5IiwNCiAgICAgeWxhYiA9ICJNZW1vcnlfU3BlZWQiLA0KICAgICBjb2wgPSAibmF2eSINCikNCmFibGluZShsbShNZW1vcnlfU3BlZWR+TWVtb3J5LGRhdGE9bm9uX2R1cF9ncHVzKSxjb2w9InJlZDMiKQ0KYGBgDQoNCg0KYGBge3J9DQojVuG6vCDEkOG7kiBUSOG7iiBQSMOCTiBQSOG7kEkgQ+G7pkEgQknhur5OIE1lbW9yeV9TcGVlZCBUSEVPIEJJ4bq+TiBNZW1vcnlfQmFuZHdpZHRoDQoNCnBsb3Qobm9uX2R1cF9ncHVzJE1lbW9yeV9TcGVlZH5ub25fZHVwX2dwdXMkTWVtb3J5X0JhbmR3aWR0aCwNCiAgICAgbWFpbiA9ICJNZW1vcnlfU3BlZWQgYnkgTWVtb3J5X0JhbmR3aWR0aCIsDQogICAgIHhsYWIgPSAiTWVtb3J5X0JhbmR3aWR0aCIsDQogICAgIHlsYWIgPSAiTWVtb3J5X1NwZWVkIiwNCiAgICAgY29sID0gImRhcmtibHVlIg0KKQ0KYWJsaW5lKGxtKE1lbW9yeV9TcGVlZH5NZW1vcnlfQmFuZHdpZHRoLGRhdGE9bm9uX2R1cF9ncHVzKSxjb2w9InJlZDMiKQ0KYGBgDQoNCg0KYGBge3J9DQojVuG6vCDEkOG7kiBUSOG7iiBQSMOCTiBQSOG7kEkgQ+G7pkEgQknhur5OIE1lbW9yeV9TcGVlZCBUSEVPIEJJ4bq+TiBNZW1vcnlfQnVzDQoNCnBsb3Qobm9uX2R1cF9ncHVzJE1lbW9yeV9TcGVlZH5ub25fZHVwX2dwdXMkTWVtb3J5X0J1cywNCiAgICAgbWFpbiA9ICJNZW1vcnlfU3BlZWQgYnkgTWVtb3J5X0J1cyIsDQogICAgIHhsYWIgPSAiTWVtb3J5X0J1cyIsDQogICAgIHlsYWIgPSAiTWVtb3J5X1NwZWVkIiwNCiAgICAgY29sID0gImRhcmtncmVlbiINCikNCmFibGluZShsbShNZW1vcnlfU3BlZWR+TWVtb3J5X0JhbmR3aWR0aCxkYXRhPW5vbl9kdXBfZ3B1cyksY29sPSJyZWQzIikNCg0KYGBgDQoNCg0KYGBge3J9DQpEI1bhurwgxJDhu5IgVEjhu4ogUEjDgk4gUEjhu5BJIEPhu6ZBIEJJ4bq+TiBNZW1vcnlfU3BlZWQgVEhFTyBCSeG6vk4gT3Blbl9HTA0KDQpwbG90KG5vbl9kdXBfZ3B1cyRNZW1vcnlfU3BlZWR+bm9uX2R1cF9ncHVzJE9wZW5fR0wsDQogICAgIG1haW4gPSAiTWVtb3J5X1NwZWVkIGJ5IE9wZW5fR0wiLA0KICAgICB4bGFiID0gIk9wZW5fR0wiLA0KICAgICB5bGFiID0gIk1lbW9yeV9TcGVlZCIsDQogICAgIGNvbCA9ICJyZWQ0Ig0KKQ0KYWJsaW5lKGxtKE1lbW9yeV9TcGVlZH5PcGVuX0dMLGRhdGE9bm9uX2R1cF9ncHVzKSxjb2w9InJlZDMiKQ0KYGBgDQoNCg0KYGBge3J9DQojVuG6vCDEkOG7kiBUSOG7iiBQSMOCTiBQSOG7kEkgQ+G7pkEgQknhur5OIE1lbW9yeV9TcGVlZCBUSEVPIEJJ4bq+TiBEaXJlY3RfWA0KDQpwbG90KG5vbl9kdXBfZ3B1cyRNZW1vcnlfU3BlZWR+bm9uX2R1cF9ncHVzJERpcmVjdF9YLA0KICAgICBtYWluID0gIk1lbW9yeV9TcGVlZCBieSBEaXJlY3RfWCIsDQogICAgIHhsYWIgPSAiRGlyZWN0X1giLA0KICAgICB5bGFiID0gIk1lbW9yeV9TcGVlZCIsDQogICAgIGNvbCA9ICJzZWFncmVlbiINCikNCmFibGluZShsbShNZW1vcnlfU3BlZWR+RGlyZWN0X1gsZGF0YT1ub25fZHVwX2dwdXMpLGNvbD0icmVkMyIpDQpgYGANCg0KDQpgYGB7cn0NCiNW4bq8IMSQ4buSIFRI4buKIFBIw4JOIFBI4buQSSBD4bumQSBCSeG6vk4gTWVtb3J5X1NwZWVkIFRIRU8gQknhur5OIFJlbGVhc2VfWWVhcg0KDQpwbG90KG5vbl9kdXBfZ3B1cyRNZW1vcnlfU3BlZWR+bm9uX2R1cF9ncHVzJFJlbGVhc2VfWWVhciwNCiAgICAgbWFpbiA9ICJNZW1vcnlfU3BlZWQgYnkgUmVsZWFzZV9ZZWFyIiwNCiAgICAgeGxhYiA9ICJSZWxlYXNlX1llYXIiLA0KICAgICB5bGFiID0gIk1lbW9yeV9TcGVlZCIsDQogICAgIGNvbCA9ICJuYXZ5Ig0KKQ0KYWJsaW5lKGxtKE1lbW9yeV9TcGVlZH5SZWxlYXNlX1llYXIsZGF0YT1ub25fZHVwX2dwdXMpLGNvbD0icmVkMyIpDQpgYGANCg0KDQoNCmBgYHtyfQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjMVdheS1BTk9WQSMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KI1jhu60gbMOtIHbDoCBs4buNYyBk4buvIGxp4buHdSMNCnR5cGVfdGFibGU8LXRhYmxlKG5vbl9kdXBfZ3B1cyRNZW1vcnlfVHlwZSkNCnByaW50KHR5cGVfdGFibGUpDQpkYXRhX2ZpbHRlcmVkIDwtIG5vbl9kdXBfZ3B1c1tub25fZHVwX2dwdXMkTWVtb3J5X1R5cGUgJWluJSBuYW1lcyh0eXBlX3RhYmxlW3R5cGVfdGFibGUgPiAxMF0pLCBdDQp0YWJsZShkYXRhX2ZpbHRlcmVkJE1lbW9yeV9UeXBlKQ0KI0tp4buDbSB0cmEgUFAgQ0h14bqpbiMNCnFxbm9ybShub25fZHVwX2dwdXMkTWVtb3J5X1NwZWVkKQ0KcXFsaW5lKG5vbl9kdXBfZ3B1cyRNZW1vcnlfU3BlZWQpDQojS2nhu4NtIHRyYSB0xrDGoW5nIMSR4buTbmcgcGh1b25nIHNhaSMNCmJhcnRsZXR0LnRlc3QoTWVtb3J5X1NwZWVkfk1lbW9yeV9UeXBlLGRhdGE9ZGF0YV9maWx0ZXJlZCkNCiNUaOG7sWMgaGnhu4duIGFub3ZhIw0KYW5vdmFfbW9kZWwxPC1hb3YoTWVtb3J5X1NwZWVkfk1lbW9yeV9UeXBlLGRhdGE9ZGF0YV9maWx0ZXJlZCkNCnN1bW1hcnkoYW5vdmFfbW9kZWwxKQ0KI1NvIHPDoW5oIGLhu5lpIw0KVHVrZXlIU0QoYW5vdmFfbW9kZWwxKQ0KDQpgYGANCg0KYGBge3J9DQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIzJXQVkgQU5PVkEjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojWOG7rCBsw70gdsOgIGzhu41jIGThu68gbGnhu4d1DQp5ZWFyX3RhYmxlPC10YWJsZShkYXRhX2ZpbHRlcmVkJFJlbGVhc2VfWWVhcikNCnByaW50KHllYXJfdGFibGUpDQpkYXRhX2ZpbHRlcmVkMjwtZGF0YV9maWx0ZXJlZFtkYXRhX2ZpbHRlcmVkJFJlbGVhc2VfWWVhciAlaW4lIG5hbWVzKHllYXJfdGFibGVbeWVhcl90YWJsZSA+IDEwXSksIF0NCnRhYmxlKGRhdGFfZmlsdGVyZWQyJFJlbGVhc2VfWWVhcikNCiNLaeG7g20gdHJhIHPhu7EgdMawxqFuZyDEkeG7k25nIHBoxrDGoW5nIHNhaSMNCmRhdGFfZmlsdGVyZWQyJFJlbGVhc2VfWWVhcjwtYXMuY2hhcmFjdGVyKGRhdGFfZmlsdGVyZWQyJFJlbGVhc2VfWWVhcikgI2NodXnhu4NuIHNhbmcgY2hhcg0KYmFydGxldHQudGVzdChNZW1vcnlfU3BlZWR+UmVsZWFzZV9ZZWFyLGRhdGE9ZGF0YV9maWx0ZXJlZDIpDQojVGjhu7FjIGhp4buHbiBhbm92YSAyIG5ow6JuIHThu5EjDQphbm92YV9tb2RlbDI8LWFvdihNZW1vcnlfU3BlZWR+TWVtb3J5X1R5cGUqUmVsZWFzZV9ZZWFyLGRhdGE9ZGF0YV9maWx0ZXJlZDIpDQpzdW1tYXJ5KGFub3ZhX21vZGVsMikNCmBgYA0KDQpgYGB7cn0NCiMjIFhheSBkdW5nIG1vIGhpbmggaG9pIHF1eSAjIw0KbW9kZWwgPC0gbG0oTWVtb3J5X1NwZWVkIH4gTWVtb3J5X1R5cGUgKyBSZWxlYXNlX1llYXIsZGF0YT1ub25fZHVwX2dwdXMpDQpzdW1tYXJ5KG1vZGVsKQ0KDQpmaWx0ZXJlZF9ub25fZHVwX2dwdXMgPC0gbm9uX2R1cF9ncHVzW25vbl9kdXBfZ3B1cyRNZW1vcnlfVHlwZSAhPSAiR0REUjMiLCBdDQoNCm1vZGVsIDwtIGxtKE1lbW9yeV9TcGVlZCB+IE1lbW9yeV9UeXBlICsgUmVsZWFzZV9ZZWFyLGRhdGE9ZmlsdGVyZWRfbm9uX2R1cF9ncHVzKQ0KDQpzdW1tYXJ5KG1vZGVsKQ0KDQpvcCA8LSBwYXIobWZyb3c9YygyLDIpKSANCnBsb3QobW9kZWwpIA0KYGBgDQo=