# HW02 參考答案
## 2.1 Subtitle Player
Credit: 41147016S 陳品翰
滿分程式碼,會拿出來主要是因為我覺得 function 分的很好。
1. 但要注意因為是先讀完檔再輸出字幕,所以大的字幕檔時間會有偏差。
2. 時間的 `usleep` 最好直接算出一次要多久。
:::spoiler hw0201.c
```c=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// Structure to store subtitle information
typedef struct {
double start_time; // Start time in milliseconds
double end_time; // End time in milliseconds
char text[1000]; // Subtitle text
} Subtitle;
int r = 0;
int g = 0;
int b = 0;
//write a function to change 16 to 10
int hex_to_dec(char hex[]){
int i = 0;
int dec = 0;
while(hex[i]){
if(hex[i] >= '0' && hex[i] <= '9'){
dec = dec * 16 + hex[i] - '0';
}
else if(hex[i] >= 'A' && hex[i] <= 'F'){
dec = dec * 16 + hex[i] - 'A' + 10;
}
else if(hex[i] >= 'a' && hex[i] <= 'f'){
dec = dec * 16 + hex[i] - 'a' + 10;
}
i++;
}
return dec;
}
int find_color(char* line){
int i = 0;
char *temp = calloc(sizeof(char),1000);
const char s[2] = ",";
char *token;
token = strtok(line, s);
while( token != NULL ) {
if (i == 3){
strcpy(temp, token);
}
token = strtok(NULL, s);
i ++;
}
if(temp[0] == '&'){
temp[0] = temp[strlen(temp)-6];
temp[1] = temp[strlen(temp)-5];
temp[2] = temp[strlen(temp)-4];
temp[3] = temp[strlen(temp)-3];
temp[4] = temp[strlen(temp)-2];
temp[5] = temp[strlen(temp)-1];
char save[2];
strncpy(save, temp, 2);
b = hex_to_dec(save);
strncpy(save, temp+2, 2);
g = hex_to_dec(save);
strncpy(save, temp+4, 2);
r = hex_to_dec(save);
}
else{
int long color = strtol(temp, &temp, 10);
//change the color to 16進位
//r is the first two digits, g is the next two digits, b is the last two digits
b = (color & 0xFF0000) >> 16;
g = (color & 0x00FF00) >> 8;
r = (color & 0x0000FF);
}
return 0;
}
// Function to parse subtitle file and store subtitles
int parse_subtitles(const char* filename, Subtitle** subtitles) {
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("Failed to open file: %s\n", filename);
return -1;
}
char line[1000];
int num_subtitles = 0;
while (fgets(line, sizeof(line), file)) {
if (strncmp(line, "Style", 5) == 0){
find_color(line);
}
if (strncmp(line, "Dialogue:", 9) == 0) {
num_subtitles++;
}
}
*subtitles = calloc(num_subtitles * sizeof(Subtitle),1);
if (*subtitles == NULL) {
printf("Failed to allocate memory for subtitles\n");
fclose(file);
return -1;
}
rewind(file);
int current_subtitle = 0;
while (fgets(line, sizeof(line), file)) {
if (strncmp(line, "Dialogue:", 9) == 0) {
int start_hours, start_minutes, start_seconds, start_milliseconds;
int end_hours, end_minutes, end_seconds, end_milliseconds;
sscanf(line, "Dialogue: %*d,%d:%d:%d.%d,%d:%d:%d.%d,Default,,0,0,0,,%[^\n]",
//Dialogue: 0,0:00:25.06,0:00:28.86,Default,,0,0,0,,... Three minutes.
&start_hours, &start_minutes, &start_seconds, &start_milliseconds,
&end_hours, &end_minutes, &end_seconds, &end_milliseconds,
(*subtitles)[current_subtitle].text);
(*subtitles)[current_subtitle].start_time = start_hours * 3600 + start_minutes * 60 + start_seconds + start_milliseconds / 1000.0;
(*subtitles)[current_subtitle].end_time = end_hours * 3600 + end_minutes * 60 + end_seconds + end_milliseconds / 1000.0;
current_subtitle++;
}
}
fclose(file);
return num_subtitles;
}
// Function to print colored subtitle text
void print_subtitle(const char* text) {
//printf("\x1b[48;2;%d;%d;%dm ", r, g, b);
printf("\x1b[38;2;%d;%d;%dm %s \n", r,g,b, text);
}
// Function to clear the screen
void clear_screen() {
printf("\033[H\033[J");
}
int main() {
char filename[100];
printf("Please enter the file name: ");
scanf("%s", filename);
Subtitle* subtitles;
int num_subtitles = parse_subtitles(filename, &subtitles);
if (num_subtitles == -1) {
return 1;
}
int time_shift = 0;
printf("Time Shift (-10 ~ 10): ");
scanf("%d", &time_shift);
if (time_shift > 10 || time_shift < -10){
printf("wrong input\n");
return -1;
}
float speed = 0;
printf("Speed (0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2): ");
scanf("%f", &speed);
if (!((speed == 0.25) || (speed == 0.5) || (speed == 0.75) || (speed == 1) || (speed == 1.25) || (speed == 1.5) || (speed == 1.75) || (speed == 2))){
printf("wrong input\n");
return -1;
}
int current_subtitle = 0;
double elapsed_time = 0;
while (current_subtitle < num_subtitles) {
double start_time =( (subtitles[current_subtitle].start_time + time_shift) / speed);
double end_time =( (subtitles[current_subtitle].end_time + time_shift) / speed);
if (start_time < 0){
start_time = 0;
}
if (end_time < 0){
end_time = 0;
}
//printf("elapsed_time: %f",elapsed_time);
// Wait for elapsed time to reach start time
while (elapsed_time <= start_time) {
usleep(10000); // Sleep for 1000 microseconds
elapsed_time += 0.01;
}
//printf("%f",elapsed_time);
// Clear
clear_screen();
/*printf("fuck");
clear_screen();*/
// Print
print_subtitle(subtitles[current_subtitle].text);
/*printf("start_time: %f\n", subtitles[current_subtitle].start_time);
printf("startome %f\n",start_time);
printf("end_time: %f\n", subtitles[current_subtitle].end_time);
printf("startome %f\n",end_time);*/
//printf("elapsed_time: %f\n", elapsed_time);
// Wait for elapsed time to reach end time
while (elapsed_time <= end_time) {
usleep(10000); // Sleep for 10 milliseconds
elapsed_time += 0.01;
}
system("clear");
current_subtitle++;
}
//where is errno
free(subtitles);
return 0;
}
```
:::
## 2.2 Premier League
內含測試資料、輸出資料及程式碼:
https://drive.google.com/file/d/1amkjVM_hCP5R1PGREt-x-iVQI2aVJDmx/view?usp=sharing
> 部分結構及程式參考以下同學之程式碼並經過改寫:
> 41247001S 盧昱安
> 41247050S 郝東彥
:::spoiler `hw0202.c`
```clike=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TEAM_NAME 100
#define MAX_TEAMS 100
#define MAX_LINE_LENGTH 1024
typedef struct {
char name[MAX_TEAM_NAME];
int wins;
int draws;
int losses;
int goalsFor;
int goalsAgainst;
int goalDifference;
int points;
} Team;
void processMatchResults(const char* filename, Team teams[], int* teamCount);
void computeTeamStatistics(Team teams[], int teamCount);
void sortByTeamPerformance(Team teams[], int teamCount);
void displayTeamRankings(const Team teams[], int teamCount);
int getTeamIndex(Team teams[], int *teamCount, char *teamName);
int main() {
Team teams[MAX_TEAMS];
int teamCount = 0;
char filename[256];
printf("Please enter the data file name: ");
scanf("%s", filename);
processMatchResults(filename, teams, &teamCount);
computeTeamStatistics(teams, teamCount);
sortByTeamPerformance(teams, teamCount);
displayTeamRankings(teams, teamCount);
return 0;
}
int compareTeams(const void* a, const void* b) {
const Team *teamA = (const Team*)a;
const Team *teamB = (const Team*)b;
if (teamA->points != teamB->points) return teamB->points - teamA->points;
if (teamA->goalDifference != teamB->goalDifference) return teamB->goalDifference - teamA->goalDifference;
return teamB->goalsFor - teamA->goalsFor;
}
void sortByTeamPerformance(Team teams[], int teamCount) {
qsort(teams, teamCount, sizeof(Team), compareTeams);
}
void displayTeamRankings(const Team teams[], int teamCount) {
printf(" Team W D L GF GA GD Pts\n");
for (int i = 0; i < teamCount; ++i) {
printf("%02d) %-17s %-2d %-2d %-2d %-3d %-3d %-+4d %-4d\n",
i + 1, teams[i].name, teams[i].wins, teams[i].draws, teams[i].losses,
teams[i].goalsFor, teams[i].goalsAgainst, teams[i].goalDifference, teams[i].points);
}
}
int getTeamIndex(Team teams[], int *teamCount, char *teamName) {
for (int i = 0; i < *teamCount; i++) {
if (strcmp(teams[i].name, teamName) == 0) {
return i;
}
}
int index = *teamCount;
strcpy(teams[index].name, teamName);
memset(&teams[index], 0, sizeof(Team));
strcpy(teams[index].name, teamName);
(*teamCount)++;
return index;
}
void processMatchResults(const char* filename, Team teams[], int* teamCount) {
FILE* file = fopen(filename, "r");
if (!file) {
printf("Can not open file.\n");
return;
}
char line[MAX_LINE_LENGTH];
fgets(line, sizeof(line), file);
while (fgets(line, sizeof(line), file)) {
char homeTeam[MAX_TEAM_NAME], awayTeam[MAX_TEAM_NAME], matchResult;
int homeGoals, awayGoals;
sscanf(line, "%*[^,],%[^,],%[^,],%d,%d,%c", homeTeam, awayTeam, &homeGoals, &awayGoals, &matchResult);
int homeIndex = getTeamIndex(teams, teamCount, homeTeam);
int awayIndex = getTeamIndex(teams, teamCount, awayTeam);
teams[homeIndex].goalsFor += homeGoals;
teams[homeIndex].goalsAgainst += awayGoals;
teams[awayIndex].goalsFor += awayGoals;
teams[awayIndex].goalsAgainst += homeGoals;
if (matchResult == 'H') {
teams[homeIndex].wins++;
teams[awayIndex].losses++;
} else if (matchResult == 'A') {
teams[awayIndex].wins++;
teams[homeIndex].losses++;
} else {
teams[homeIndex].draws++;
teams[awayIndex].draws++;
}
}
fclose(file);
}
void computeTeamStatistics(Team teams[], int teamCount) {
for (int i = 0; i < teamCount; ++i) {
teams[i].points = teams[i].wins * 3 + teams[i].draws * 1;
teams[i].goalDifference = teams[i].goalsFor - teams[i].goalsAgainst;
}
}
```
:::
## 2.3 Wordle Solver
Credit: 41247034S 伍駿宇
:::spoiler hw0203.c
```c
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
typedef struct _sWord{
char word[6];
double freq;
} sWord;
int32_t alphabet_sheet[26][5] = {0};
double calc_freq(char *input);
void updateWords(sWord *pool, int32_t *word_count, char *advice, char *feedback);
int main() {
//load dic
FILE *pDict;
pDict = fopen("en_US.dic", "r");
if(pDict == NULL){
printf("Error opening en_US.dic.\n");
return 1;
}
//create pool
sWord pool[5000]={0};
int32_t word_count=0;
//header and number
char line[32];
for(int32_t i=0; i<24; i++){
fgets(line, sizeof(line), pDict);
}
//collect words from dict
while(fgets(line, sizeof(line), pDict) != NULL){
line[strlen(line)-1] = 0;
sscanf(line,"%[^/]",line);
if(strlen(line)==5){
sscanf(line,"%[^\']",line);
if(strlen(line)==5){
for(int32_t i=0;i<5;i++){line[i]=toupper(line[i]);}
strcpy(pool[word_count].word, line);
pool[word_count].freq = calc_freq(line);
word_count++;
}
}
}
fclose(pDict);
//main loop
char advice[6]={0};
char feedback[6]={0};
do{
double max_freq = -1;
for(int32_t i=0; i<word_count; i++){
if(calc_freq(pool[i].word) > max_freq){
max_freq = calc_freq(pool[i].word);
strcpy(advice, pool[i].word);
}
}
printf("Advice: %s\n", advice);
//get feedback
printf("Feedback: ");
scanf("%s", feedback);
if (sscanf(feedback, "%5[YGB]", feedback) != 1 || strlen(feedback)!=5) {
printf("Wrong Input\n");
return 1;
}
updateWords(pool, &word_count, advice, feedback);
if(word_count==0){
printf("No Advice\n");
return 0;
}
} while (strcmp(feedback,"GGGGG"));
printf("Congratulations!!\n");
return 0;
}
double calc_freq(char *input){
double freq_table[26]= {8.200, 1.500, 2.800, 4.300,12.700, 2.200, 2.000, 6.100, 7.000, 0.150, 0.770, 4.000, 2.400,
6.700, 7.500, 1.900, 0.095, 6.000, 6.300, 9.100, 2.800, 0.980, 2.400, 0.150, 2.000, 0.074};
double sum = 0;
for(int32_t i=0; i<5; i++){
sum += freq_table[input[i] - 'A'];
}
return round(sum*1000.0)/1000.0;
}
void updateWords(sWord *pool, int32_t *word_count, char *advice, char *feedback){
char match[6]={0};
for(int32_t i=0;i<*word_count;i++){
char target[6]={0};
strcpy(target,pool[i].word);
for(int32_t j=0;j<5;j++){
if(target[j] == advice[j]){
match[j]='G';
target[j]='0';
}
}
for(int32_t j=0;j<5;j++){
if(target[j]=='0'){
continue;
}else if(strchr(target, advice[j]) != NULL){
match[j]='Y';
int32_t idx = strchr(target, advice[j])-target;
target[idx]='1';
}else{
match[j]='B';
}
}
//printf("%s %s %s\n",target,pool[i].word,match);
if(strcmp(feedback,match)!=0){
strcpy(pool[i].word,"");
}
}
int32_t new_word_count=0;
for(int32_t i = 0; i < *word_count; i++){
if(strcmp(pool[i].word, "") != 0){
pool[new_word_count] = pool[i];
new_word_count++;
}
}
*word_count = new_word_count;
}
```
:::
## 2.4 BMP
Credit by: 41247001S 盧O安
:::spoiler hw0204.c
```c=
#include "AndyLuBMP.h"
void Transfer(BMP * a,BMP * b);
BMP * bmp;
static double Change_ANGEL = 0;
void GETINPUT();
int main(){
GETINPUT();
setupBMP(&bmp[1] , &bmp[0]);
//showBMPInfo(&bmp[0]);
bmp[1].info->width = round(bmp[0].info->width + bmp[0].info->height* tan(Change_ANGEL));
bmp[1].file->size = (4-(bmp[1].info->width* 3%4)+bmp[1].info->width* 3)* bmp[1].info->height + bmp[1].file->offbit;
bmp[1].info->BMPsize = bmp[1].file->size - bmp[1].file->offbit;
//printf("%zu %d %ld",bmp[1]->file->size,bmp[1]->info->size,bmp[1]->info->width);
//printf("\n%zu %d %ld",bmp[0]->file->size,bmp[0]->info->size,bmp[0]->info->width);
//showBMPInfo(&bmp[0]);
//showBMPInfo(&bmp[1]);
writeInHeader(&bmp[1]);
Transfer(&bmp[0],&bmp[1]);
fclose(bmp[0].source);
fclose(bmp[1].source);
BMPFree(&bmp[0]);
BMPFree(&bmp[1]);
free(bmp);
}
void Transfer(BMP * a,BMP * b){
//b->info->height = 100;
for(int i=0;i<b->info->height;i++){
//int n = 0,ss = 0;
int lWhite = b->info->direction == 1 ? round((b->info->width - a->info->width)*(i+1)/b->info->height) :
round((b->info->width - a->info->width)*(b->info->height-i-1)/b->info->height);
int white = 255;
for(int j=0;j<lWhite;j++){
for(int k=0;k<b->info->bitcount/8;k++){
fwrite(&white,1,1,b->source);
//n++;
}
}
for(int j=0;j<a->info->width;j++){
uint8_t readIn[b->info->bitcount/8];
fread(readIn,b->info->bitcount/8,1,a->source);
fwrite(readIn,b->info->bitcount/8,1,b->source);
for(int k=0;k<(4 - (a->info->width*b->info->bitcount/8)%4)%4;k++)fread(readIn,1,1,a->source);
//n+=b->info->bitcount/8;
}
for(int j=0;j<b->info->width - a->info->width - lWhite;j++){
for(int k=0;k<b->info->bitcount/8;k++){
fwrite(&white,1,1,b->source);
//n++;
}
}
for(int k=0;k<(4 - (b->info->width*b->info->bitcount/8)%4)%4;k++){
fwrite("00",1,1,b->source);
//n++;
}
}
//printf("%d",b->info->width*3);
}
void GETINPUT(){
printf("Please input a BMP file: ");
bmp = calloc(2,sizeof(BMP));
CallocBMP(&bmp[0]);
CallocBMP(&bmp[1]);
fgets(bmp[0].path,1025,stdin);
if(bmp[0].path[strlen(bmp[0].path)-1]==10)bmp[0].path[strlen(bmp[0].path)-1] = 0;
if(!( bmp[0].source = fopen(bmp[0].path,"rb"))){
printf("File Not Exist!\n");
exit(0);
}
if(!READBMP(&bmp[0]) || !dotBMPcheck(bmp[0].path)){
printf("Read file failed, it is not a BMP file\n");
exit(0);
}
printf("Please input the output BMP file name: ");
fgets(bmp[1].path,1025,stdin);
if(bmp[1].path[strlen(bmp[1].path)-1]==10)bmp[1].path[strlen(bmp[1].path)-1] = 0;
if(!strcmp(bmp[0].path,bmp[1].path)){
printf("Input file cannot be same as output file!\n");
exit(0);
}
if(!dotBMPcheck(bmp[1].path)){
printf("Read file failed, it is not a BMP file\n");
exit(0);
}
bmp[1].source = fopen(bmp[1].path,"wb");
printf("Angle (0-90): ");
scanf("%lf",&Change_ANGEL);
if(Change_ANGEL >= 90 || Change_ANGEL < 0){
printf("Wrong Angle ! (0<=angle<90)\n");
exit(0);
}
Change_ANGEL = Change_ANGEL *3.1415926/180;
}
```
:::
:::spoiler AndyLuBMP.c
```c=
#include "AndyLuBMP.h"
int dotBMPcheck(char * target){
int q = strlen(target);
if(strcmp(target+q-3,"bmp")){
if(strcmp(target+q-3,"BMP"))return 0;
}
return 1;
}
void CallocBMP(BMP * target){
target->file = calloc(1,sizeof(BMPFile));
target->info = calloc(1,sizeof(BMPInfo));
}
void BMPFree(BMP * target){
free(target->file);
free(target->info);
//free(target->path);
//free(target->source);
}
void writeInHeader(BMP * target){
fwrite(target->file->type,sizeof(target->file->type),1,target->source);
fwrite(&(target->file->size),sizeof(target->file->size),1,target->source);
fwrite(&(target->file->reverse1),sizeof(target->file->reverse1),1,target->source);
fwrite(&(target->file->reverse2),sizeof(target->file->reverse2),1,target->source);
fwrite(&(target->file->offbit),sizeof(target->file->offbit),1,target->source);
fwrite(&(target->info->size),sizeof(target->info->size),1,target->source);
fwrite(&(target->info->width),sizeof(target->info->width),1,target->source);
fwrite(&(target->info->height),sizeof(target->info->height),1,target->source);
fwrite(&(target->info->planes),sizeof(target->info->planes),1,target->source);
fwrite(&(target->info->bitcount),sizeof(target->info->bitcount),1,target->source);
fwrite(&(target->info->compress),sizeof(target->info->compress),1,target->source);
fwrite(&(target->info->BMPsize),sizeof(target->info->BMPsize),1,target->source);
fwrite(&(target->info->xpixel),sizeof(target->info->xpixel),1,target->source);
fwrite(&(target->info->ypixel),sizeof(target->info->ypixel),1,target->source);
fwrite(&(target->info->coloruse),sizeof(target->info->coloruse),1,target->source);
fwrite(&(target->info->colorImportance),sizeof(target->info->colorImportance),1,target->source);
}
void setupBMP(BMP * target , BMP * from){
target->file->type[0] = 'B';
target->file->type[1] = 'M';
target->file->size = from->info->width * from->info->height * 3 + from->file->offbit;
target->file->reverse1 = from->file->reverse1;
target->file->reverse2 = from->file->reverse1;
target->file->offbit = from->file->offbit;
target->info->size = from->info->size;
target->info->width = from->info->width;
target->info->height = from->info->height;
target->info->direction = from->info->direction;
target->info->planes = from->info->planes;
target->info->bitcount = from->info->bitcount;
target->info->compress = from->info->compress;
target->info->BMPsize = from->info->width * from->info->height * from->info->bitcount/8;
target->info->xpixel = from->info->xpixel;
target->info->ypixel = from->info->ypixel;
target->info->width = from->info->width;
target->info->coloruse = from->info->coloruse;
target->info->colorImportance = from->info->colorImportance;
}
int READBMP(BMP * target){
fread(target->file->type,2,1,target->source);
if(strcmp(target->file->type,"BM")){
if(strcmp(target->file->type,"BA")){
if(strcmp(target->file->type,"CI")){
if(strcmp(target->file->type,"CP")){
if(strcmp(target->file->type,"IC")){
if(strcmp(target->file->type,"PT")) return 0;
}
}
}
}
}
fread(&(target->file->size),4,1,target->source);
fread(&(target->file->reverse1),2,1,target->source);
fread(&(target->file->reverse2),2,1,target->source);
fread(&(target->file->offbit),4,1,target->source);
fread(&(target->info->size),4,1,target->source);
fread(&(target->info->width),4,1,target->source);
fread(&(target->info->height),4,1,target->source);
fread(&(target->info->planes),2,1,target->source);
if(target->info->planes != 1)return 0;
fread(&(target->info->bitcount),2,1,target->source);
fread(&(target->info->compress),4,1,target->source);
fread(&(target->info->BMPsize),4,1,target->source);
fread(&(target->info->xpixel),4,1,target->source);
fread(&(target->info->ypixel),4,1,target->source);
fread(&(target->info->coloruse),4,1,target->source);
fread(&(target->info->colorImportance),4,1,target->source);
if(target->info->height < 0) target->info->direction = 0;
else target->info->direction = 1;
char temp[200];
fread(temp,target->info->size - 40,1,target->source);
//showBMPInfo(target);
return 1;
}
void showBMPInfo(BMP * target){
printf("File ID : %c%c\n",target->file->type[0],target->file->type[1]);
printf("File Size : %ld\n",(int64_t)target->file->size);
printf("File reserve1 : %ld\n",(int64_t)target->file->reverse1);
printf("File reserve2 : %ld\n",(int64_t)target->file->reverse2);
printf("File offbit : %ld\n",(int64_t)target->file->offbit);
printf("Info Header Size : %ld\n",(int64_t)target->info->size);
printf("Width : %ld\n",(int64_t)target->info->width);
printf("Height : %ld\n",(int64_t)target->info->height);
printf("Planes : %ld\n",(int64_t)target->info->planes);
printf("Bit Per Pixel : %ld\n",(int64_t)target->info->bitcount);
printf("Compress : %ld\n",(int64_t)target->info->compress);
printf("BMPSize : %ld\n",(int64_t)target->info->BMPsize);
printf("X_Pixel : %ld\n",(int64_t)target->info->xpixel);
printf("Y_Pixel : %ld\n",(int64_t)target->info->ypixel);
printf("Used Color : %ld\n",(int64_t)target->info->coloruse);
printf("Important Color : %ld\n",(int64_t)target->info->colorImportance);
}
```
:::
:::spoiler AndyLuBMP.h
```c=
#ifndef _ANDYLUBMP
#define _ANDYLUBMP
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
typedef struct _BMPFile{
uint8_t type[2]; //BM
uint32_t size;
uint16_t reverse1;
uint16_t reverse2;
uint32_t offbit;
} BMPFile;
typedef struct _BMPInfo{
uint32_t size;
int32_t width;
int32_t height;
int32_t direction;
uint16_t planes;
uint16_t bitcount;
uint32_t compress;
uint32_t BMPsize;
int32_t xpixel;
int32_t ypixel;
uint32_t coloruse;
uint32_t colorImportance;
} BMPInfo;
typedef struct _BMP{
BMPInfo *info;
BMPFile *file;
char path[1025];
FILE * source;
}BMP;
int READBMP(BMP * target);
void showBMPInfo(BMP * target);
void setupBMP(BMP * target, BMP * from);
void writeInHeader(BMP *target);
void BMPFree(BMP * target);
void CallocBMP(BMP * target);
int dotBMPcheck(char * target);
#endif
```
:::
## 2.5 Large Language Model
:::spoiler `hw0205.c` Credit: 41247022S 林O恩
```c=
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
// #include "gguf.h"
#define DEBUG 0
#define fptf fprintf
enum gguf_metadata_value_type // uin32_t
{
// The value is a 8-bit unsigned integer.
GGUF_METADATA_VALUE_TYPE_UINT8 = 0,
// The value is a 8-bit signed integer.
GGUF_METADATA_VALUE_TYPE_INT8 = 1,
// The value is a 16-bit unsigned little -endian integer.
GGUF_METADATA_VALUE_TYPE_UINT16 = 2,
// The value is a 16-bit signed little -endian integer.
GGUF_METADATA_VALUE_TYPE_INT16 = 3,
// The value is a 32-bit unsigned little -endian integer.
GGUF_METADATA_VALUE_TYPE_UINT32 = 4,
// The value is a 32-bit signed little -endian integer.
GGUF_METADATA_VALUE_TYPE_INT32 = 5,
// The value is a 32-bit IEEE754 floating point number.
GGUF_METADATA_VALUE_TYPE_FLOAT32 = 6,
// The value is a boolean.
// 1-byte value where 0 is false and 1 is true.
// Anything else is invalid , and should be treated as either the model being invalid or the reader being buggy.
GGUF_METADATA_VALUE_TYPE_BOOL = 7,
// The value is a UTF -8 non-null -terminated string , with length prepended.
GGUF_METADATA_VALUE_TYPE_STRING = 8,
// The value is an array of other values , with the length and type prepended.
///
// Arrays can be nested , and the length of the array is the number of elements in the array , not the number of bytes.
GGUF_METADATA_VALUE_TYPE_ARRAY = 9,
// The value is a 64-bit unsigned little -endian integer.
GGUF_METADATA_VALUE_TYPE_UINT64 = 10,
// The value is a 64-bit signed little -endian integer.
GGUF_METADATA_VALUE_TYPE_INT64 = 11,
// The value is a 64-bit IEEE754 floating point number.
GGUF_METADATA_VALUE_TYPE_FLOAT64 = 12,
};
enum ggml_type
{
GGML_TYPE_F32 = 0,
GGML_TYPE_F16 = 1,
GGML_TYPE_Q4_0 = 2,
GGML_TYPE_Q4_1 = 3,
// GGML_TYPE_Q4_2 = 4, support has been removed
// GGML_TYPE_Q4_3 (5) support has been removed
GGML_TYPE_Q5_0 = 6,
GGML_TYPE_Q5_1 = 7,
GGML_TYPE_Q8_0 = 8,
GGML_TYPE_Q8_1 = 9,
// k-quantizations
GGML_TYPE_Q2_K = 10,
GGML_TYPE_Q3_K = 11,
GGML_TYPE_Q4_K = 12,
GGML_TYPE_Q5_K = 13,
GGML_TYPE_Q6_K = 14,
GGML_TYPE_Q8_K = 15,
GGML_TYPE_I8,
GGML_TYPE_I16,
GGML_TYPE_I32,
GGML_TYPE_COUNT,
};
typedef struct _Sgguf_header
{
uint32_t magic_number;
uint32_t version;
uint64_t tenson_count;
uint64_t metadata_kv_count;
} __attribute__((__packed__)) Sgguf_header;
static int8_t get_string(FILE *file, char str[]);
static uint8_t get_value(FILE *file, uint32_t type, int8_t print);
static int8_t count_parameters(FILE *file, Sgguf_header gguf_header);
static int8_t sort_tensor();
static int32_t mylog10(int32_t x);
uint64_t parameter = 0;
int main()
{
fprintf(stdout, "GGUF: ");
FILE *gguf_read = fopen("model.gguf", "rb");
if (gguf_read == NULL)
{
fprintf(stdout, "false\n");
return -1;
}
Sgguf_header gguf_header;
uint32_t type = 0;
fread(&gguf_header, sizeof(Sgguf_header), 1, gguf_read);
if (gguf_header.magic_number == 0x46554747)
fprintf(stdout, "true\n");
else
{
fprintf(stdout, "false\n");
fclose(gguf_read);
return -1;
}
count_parameters(gguf_read, gguf_header);
fprintf(stdout, "Parameters: ");
char num[100] = {0};
sprintf(num, "%lu", parameter);
int64_t len = strlen(num);
for (int64_t i = 0; i < len; i++)
{
fprintf(stdout, "%c", num[i]);
if ((len - i - 1) % 3 == 0 && i != len - 1)
{
fprintf(stdout, ",");
}
}
fprintf(stdout, "\n");
fseek(gguf_read, 0, SEEK_SET);
fread(&gguf_header, sizeof(Sgguf_header), 1, gguf_read);
fprintf(stdout, "\n");
fprintf(stdout, "Metadata Value\n");
fprintf(stdout, "Version: %u\n", gguf_header.version);
fprintf(stdout, "tensor_count: %lu\n", gguf_header.tenson_count);
fprintf(stdout, "kv_count: %lu\n", gguf_header.metadata_kv_count);
for (uint64_t i = 0; i < gguf_header.metadata_kv_count; i++)
{
char title[100] = {0};
get_string(gguf_read, title);
fprintf(stdout, "%s:", title);
for (size_t i = 0; i < 39 - strlen(title); i++)
{
fprintf(stdout, " ");
}
fread(&type, sizeof(uint32_t), 1, gguf_read);
get_value(gguf_read, type, 1);
fprintf(stdout, "\n");
}
fprintf(stdout, "\n");
fprintf(stdout, "Tensors Shape Precision\n");
FILE *tensor = fopen("tensor.txt", "w");
for (uint64_t i = 0; i < gguf_header.tenson_count; i++)
{
char name[200] = {0};
get_string(gguf_read, name);
fprintf(tensor, "%s:", name);
for (size_t i = 0; i < 39 - strlen(name); i++)
{
fprintf(tensor, " ");
}
uint32_t n_dim = 0;
fread(&n_dim, sizeof(uint32_t), 1, gguf_read);
fprintf(tensor, "[");
int64_t strlen_count = 0;
strlen_count++;
uint64_t count = 1;
for (uint32_t j = 0; j < n_dim; j++)
{
uint64_t dimensions = 0;
fread(&dimensions, sizeof(uint64_t), 1, gguf_read);
fprintf(tensor, "%lu", dimensions);
char len_ct[100] = {0};
sprintf(len_ct, "%lu", dimensions);
count *= dimensions;
strlen_count += strlen(len_ct);
if (j != n_dim - 1)
{
fprintf(tensor, ",");
strlen_count++;
}
}
parameter += count;
fprintf(tensor, "]");
strlen_count++;
for (int64_t i = 0; i < 17 - strlen_count; i++)
{
fprintf(tensor, " ");
}
uint32_t precision = 0;
fread(&precision, sizeof(uint32_t), 1, gguf_read);
switch (precision)
{
case GGML_TYPE_F32:
fprintf(tensor, "F32");
break;
case GGML_TYPE_F16:
fprintf(tensor, "F16");
break;
case GGML_TYPE_Q4_0:
fprintf(tensor, "Q4_0");
break;
case GGML_TYPE_Q4_1:
fprintf(tensor, "Q4_1");
break;
case GGML_TYPE_Q5_0:
fprintf(tensor, "Q5_0");
break;
case GGML_TYPE_Q5_1:
fprintf(tensor, "Q5_1");
break;
case GGML_TYPE_Q8_0:
fprintf(tensor, "Q8_0");
break;
case GGML_TYPE_Q8_1:
fprintf(tensor, "Q8_1");
break;
case GGML_TYPE_Q2_K:
fprintf(tensor, "Q2_K");
break;
case GGML_TYPE_Q3_K:
fprintf(tensor, "Q3_K");
break;
case GGML_TYPE_Q4_K:
fprintf(tensor, "Q4_K");
break;
case GGML_TYPE_Q5_K:
fprintf(tensor, "Q5_K");
break;
case GGML_TYPE_Q6_K:
fprintf(tensor, "Q6_K");
break;
case GGML_TYPE_Q8_K:
fprintf(tensor, "Q8_K");
break;
case GGML_TYPE_I8:
fprintf(tensor, "I8");
break;
case GGML_TYPE_I16:
fprintf(tensor, "I16");
break;
case GGML_TYPE_I32:
fprintf(tensor, "I32");
break;
default:
break;
}
uint64_t offset = 0;
fread(&offset, sizeof(uint64_t), 1, gguf_read);
// don't know what to do with offset
fprintf(tensor, "\n");
}
fclose(tensor);
sort_tensor();
fclose(gguf_read);
return 0;
}
static int8_t get_string(FILE *file, char str[])
{
uint64_t string_len = 0;
fread(&string_len, sizeof(uint64_t), 1, file);
if (string_len == 0)
{
str[0] = '\0';
return 0;
}
if (DEBUG)
{
fptf(stderr, "%ld\n", string_len);
}
uint64_t max_len = 50;
if (string_len > max_len)
{
for (uint64_t i = 0; i < max_len; i++)
{
char char_read = 0;
fread(&char_read, sizeof(char), 1, file);
str[i] = char_read;
}
str[max_len] = '.';
str[max_len + 1] = '.';
str[max_len + 2] = '.';
str[max_len + 3] = '\0';
for (uint64_t i = max_len; i < string_len; i++)
{
char char_read = 0;
fread(&char_read, sizeof(char), 1, file);
}
}
else
{
fread(str, sizeof(char), string_len, file);
}
str[strlen(str)] = '\0';
return -1;
}
static uint8_t get_value(FILE *file, uint32_t type, int8_t print)
{
switch (type)
{
case GGUF_METADATA_VALUE_TYPE_UINT8:
uint8_t value = 0;
fread(&value, sizeof(uint8_t), 1, file);
if (print)
fprintf(stdout, "%d", value);
break;
case GGUF_METADATA_VALUE_TYPE_INT8:
int8_t value1 = 0;
fread(&value1, sizeof(int8_t), 1, file);
if (print)
fprintf(stdout, "%d", value1);
break;
case GGUF_METADATA_VALUE_TYPE_UINT16:
uint16_t value2 = 0;
fread(&value2, sizeof(uint16_t), 1, file);
if (print)
fprintf(stdout, "%d", value2);
break;
case GGUF_METADATA_VALUE_TYPE_INT16:
int16_t value3 = 0;
fread(&value3, sizeof(int16_t), 1, file);
if (print)
fprintf(stdout, "%d", value3);
break;
case GGUF_METADATA_VALUE_TYPE_UINT32:
uint32_t value4 = 0;
fread(&value4, sizeof(uint32_t), 1, file);
if (print)
fprintf(stdout, "%d", value4);
break;
case GGUF_METADATA_VALUE_TYPE_INT32:
int32_t value5 = 0;
fread(&value5, sizeof(int32_t), 1, file);
if (print)
fprintf(stdout, "%d", value5);
break;
case GGUF_METADATA_VALUE_TYPE_FLOAT32:
float value6 = 0;
fread(&value6, sizeof(float), 1, file);
if (print)
fprintf(stdout, "%f", value6);
break;
case GGUF_METADATA_VALUE_TYPE_BOOL:
uint8_t value7 = 0;
fread(&value7, sizeof(uint8_t), 1, file);
if (print)
{
if (value7 == 0)
fprintf(stdout, "false");
else if (value7 == 1)
fprintf(stdout, "true");
else
fprintf(stdout, "invalid");
}
break;
case GGUF_METADATA_VALUE_TYPE_STRING:
char value8[100] = {0};
get_string(file, value8);
if (print)
{
fprintf(stdout, "%s", value8);
}
break;
case GGUF_METADATA_VALUE_TYPE_ARRAY:
uint32_t array_type = 0;
fread(&array_type, sizeof(uint32_t), 1, file);
uint64_t array_len = 0;
fread(&array_len, sizeof(uint64_t), 1, file);
if (print)
fprintf(stdout, "[");
for (uint64_t i = 0; i < array_len; i++)
{
if (array_len > 3 && i >= 3)
{
if (i == array_len - 1)
{
if (print)
fprintf(stdout, "...(%lu)", array_len - 3);
}
get_value(file, array_type, 0);
}
else
{
get_value(file, array_type, print);
if (print)
{
if (i != array_len - 1)
fprintf(stdout, ", ");
}
}
}
if (print)
fprintf(stdout, "]");
break;
case GGUF_METADATA_VALUE_TYPE_UINT64:
uint64_t value9 = 0;
fread(&value9, sizeof(uint64_t), 1, file);
if (print)
fprintf(stdout, "%lu", value9);
break;
case GGUF_METADATA_VALUE_TYPE_INT64:
int64_t value10 = 0;
fread(&value10, sizeof(int64_t), 1, file);
if (print)
fprintf(stdout, "%ld", value10);
break;
case GGUF_METADATA_VALUE_TYPE_FLOAT64:
double value11 = 0;
fread(&value11, sizeof(double), 1, file);
if (print)
fprintf(stdout, "%f", value11);
break;
default:
break;
}
return 0;
}
static int8_t count_parameters(FILE *file, Sgguf_header gguf_header)
{
uint32_t type = 0;
for (uint64_t i = 0; i < gguf_header.metadata_kv_count; i++)
{
char title[100] = {0};
get_string(file, title);
fread(&type, sizeof(uint32_t), 1, file);
get_value(file, type, 0);
}
for (uint64_t i = 0; i < gguf_header.tenson_count; i++)
{
char name[200] = {0};
get_string(file, name);
uint32_t n_dim = 0;
fread(&n_dim, sizeof(uint32_t), 1, file);
uint64_t count = 1;
for (uint32_t j = 0; j < n_dim; j++)
{
uint64_t dimensions = 0;
fread(&dimensions, sizeof(uint64_t), 1, file);
count *= dimensions;
}
parameter += count;
uint32_t precision = 0;
fread(&precision, sizeof(uint32_t), 1, file);
uint64_t offset = 0;
fread(&offset, sizeof(uint64_t), 1, file);
// don't know what to do with offset
}
return 0;
}
static int8_t sort_tensor()
{
FILE *fTensors = fopen("tensor.txt", "r");
if (fTensors == NULL)
{
return -1;
}
FILE *f_blk_sort = fopen("blk_sort.txt", "w");
FILE *fOther_sort = fopen("other_sort.txt", "w");
int32_t number_max = 0;
while (!feof(fTensors))
{
char tensor[200] = {0};
fgets(tensor, 200, fTensors);
if (strstr(tensor, "blk") != NULL) // sort by number
{
fprintf(f_blk_sort, "%s", tensor);
int32_t number = 0;
number = strtol(strchr(tensor, '.') + 1, NULL, 10);
if (number > number_max)
{
number_max = number;
}
}
else
{
fprintf(fOther_sort, "%s", tensor);
}
}
fclose(fTensors);
remove("tensor.txt");
fclose(f_blk_sort);
fclose(fOther_sort);
FILE *f_blk_sort_read = fopen("blk_sort.txt", "r");
// FILE *temp = fopen("temp.txt", "w");
for (int32_t i = 0; i <= number_max; i++)
{
fprintf(stdout, "blk.%d\n", i);
while (!feof(f_blk_sort_read))
{
char tensor[200] = {0};
fgets(tensor, 200, f_blk_sort_read);
if (strstr(tensor, ".") != NULL) // sort by number
{
int32_t number = 0;
number = strtol(strchr(tensor, '.') + 1, NULL, 10);
if (number == i)
{
// add 2 spaces before [
char print_tensor[200] = {0};
strcpy(print_tensor, strchr(strchr(tensor, '.') + 1, '.'));
strtok(print_tensor, "[");
fprintf(stdout, " %s", strtok(print_tensor, "["));
for (int32_t j = 0; j < mylog10(i); j++)
{
fprintf(stdout, " ");
}
fprintf(stdout, "%s", strchr(tensor, '['));
}
}
}
fseek(f_blk_sort_read, 0, SEEK_SET);
}
fclose(f_blk_sort_read);
remove("blk_sort.txt");
// sort by alphabet
FILE *fOther_sort_read = fopen("other_sort.txt", "r");
char words[100][200];
while (!feof(fOther_sort_read))
{
int32_t count = 0;
while (!feof(fOther_sort_read))
{
char line[200] = {0};
fgets(line, 200, fOther_sort_read);
if (line[0] == '\0')
break;
strcpy(words[count], line);
count++;
}
for (int32_t i = 0; i < count; i++)
{
for (int32_t j = i + 1; j < count; j++)
{
int32_t len1 = strlen(words[i]);
int32_t len2 = strlen(words[j]);
int32_t len = len1 > len2 ? len2 : len1;
for (int32_t k = 0; k < len; k++)
{
if (words[i][k] > words[j][k])
{
char temp[200] = {0};
strcpy(temp, words[i]);
strcpy(words[i], words[j]);
strcpy(words[j], temp);
break;
}
else if (words[i][k] < words[j][k])
{
break;
}
}
}
}
for (int32_t i = 0; i < count; i++)
{
fprintf(stdout, "%s", words[i]);
}
}
fclose(fOther_sort_read);
remove("other_sort.txt");
return 0;
}
static int32_t mylog10(int32_t x)
{
int32_t count = 0;
if (x == 0)
{
return 1;
}
while (x > 0)
{
x /= 10;
count++;
}
return count;
}
```
:::
:::spoiler Output
```
GGUF: true
Parameters: 2,779,683,840
Metadata Value
Version: 3
tensor_count: 325
kv_count: 20
general.architecture: phi2
general.name: Phi2
phi2.context_length: 2048
phi2.embedding_length: 2560
phi2.feed_forward_length: 10240
phi2.block_count: 32
phi2.attention.head_count: 32
phi2.attention.head_count_kv: 32
phi2.attention.layer_norm_epsilon: 0.000010
phi2.rope.dimension_count: 32
general.file_type: 10
tokenizer.ggml.add_bos_token: false
tokenizer.ggml.model: gpt2
tokenizer.ggml.tokens: [!, ", #, ...(51197)]
tokenizer.ggml.token_type: [1, 1, 1, ...(51197)]
tokenizer.ggml.merges: [Ġ t, Ġ a, h e, ...(49997)]
tokenizer.ggml.bos_token_id: 50256
tokenizer.ggml.eos_token_id: 50256
tokenizer.ggml.unknown_token_id: 50256
general.quantization_version: 2
Tensors Shape Precision
blk.0
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.1
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.2
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.3
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.4
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.5
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.6
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.7
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.8
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.9
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.10
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.11
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.12
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.13
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.14
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.15
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.16
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.17
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.18
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.19
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.20
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.21
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.22
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.23
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.24
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.25
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.26
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.27
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.28
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.29
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.30
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
blk.31
.attn_norm.bias: [2560] F32
.attn_norm.weight: [2560] F32
.attn_qkv.bias: [7680] F32
.attn_qkv.weight: [2560,7680] Q2_K
.attn_output.bias: [2560] F32
.attn_output.weight: [2560,2560] Q3_K
.ffn_up.bias: [10240] F32
.ffn_up.weight: [2560,10240] Q3_K
.ffn_down.bias: [2560] F32
.ffn_down.weight: [10240,2560] Q3_K
output.bias: [51200] F32
output.weight: [2560,51200] Q6_K
output_norm.bias: [2560] F32
output_norm.weight: [2560] F32
token_embd.weight: [2560,51200] Q2_K
```
:::
## 2.6 Bonus: Where is errno
Credit by: 40541105S 王O堯
1. Where is errno?
- errno is defined in /usr/include/error.h
2. Please find all known error numbers. Do not search them from Google but find them from codes.
- use a for loop in main() to print out all errno.
3. Please define a new error number and use perror to show it.
- in the end of this .c, it define a new errno as NEWERROR.
:::spoiler hw0206.c
```c=
#include <stdio.h>
#include <string.h>
#include <errno.h>
// defined in /usr/include/error.h
int main()
{
for (int i = 1; i < 1000; i++) {
const char * error = strerror(i);
if (!error || strncmp(error, "Unknown error", 12) == 0) {
continue;
}
printf("error num %d: %s\n", i, error);
}
// define new error num
errno = 999;
if (errno == 999) {
fprintf(stderr, "new error occurred\n");
} else {
perror("error occurred");
}
return 0;
}
```
:::