centralized performance resources
This commit is contained in:
commit
50b15a1522
63 changed files with 328466 additions and 0 deletions
BIN
ocw/1/assignment.pdf
Normal file
BIN
ocw/1/assignment.pdf
Normal file
Binary file not shown.
31
ocw/1/c-primer/Makefile
Normal file
31
ocw/1/c-primer/Makefile
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
CC := clang
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
CFLAGS := -Wall -O0 -g
|
||||
else
|
||||
CFLAGS := -Wall -O1 -DNDEBUG
|
||||
endif
|
||||
|
||||
LDFLAGS := -lrt -flto -fuse-ld=gold
|
||||
|
||||
all: sizes pointer swap
|
||||
|
||||
sizes.o: sizes.c
|
||||
$(CC) $(CFLAGS) -c sizes.c
|
||||
|
||||
sizes: sizes.o
|
||||
$(CC) -o sizes sizes.o $(LDFLAGS)
|
||||
|
||||
pointer.o: pointer.c
|
||||
$(CC) $(CFLAGS) -c pointer.c
|
||||
|
||||
pointer: pointer.o
|
||||
$(CC) -o pointer pointer.o $(LDFLAGS)
|
||||
|
||||
swap.o: swap.c
|
||||
$(CC) $(CFLAGS) -c swap.c
|
||||
|
||||
swap: swap.o
|
||||
$(CC) -o swap swap.o $(LDFLAGS)
|
||||
clean:
|
||||
rm -f sizes pointer swap *.o *.gcda *.gcno *.gcov perf.data */perf.data cachegrind.out.*
|
||||
47
ocw/1/c-primer/pointer.c
Normal file
47
ocw/1/c-primer/pointer.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2012 MIT License by 6.172 Staff
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int main(int argc, char * argv[]) { // What is the type of argv?
|
||||
int i = 5;
|
||||
// The & operator here gets the address of i and stores it into pi
|
||||
int * pi = &i;
|
||||
// The * operator here dereferences pi and stores the value -- 5 --
|
||||
// into j.
|
||||
int j = *pi;
|
||||
|
||||
char c[] = "6.172";
|
||||
char * pc = c; // Valid assignment: c acts like a pointer to c[0] here.
|
||||
char d = *pc;
|
||||
printf("char d = %c\n", d); // What does this print?
|
||||
|
||||
// compound types are read right to left in C.
|
||||
// pcp is a pointer to a pointer to a char, meaning that
|
||||
// pcp stores the address of a char pointer.
|
||||
char ** pcp;
|
||||
pcp = argv; // Why is this assignment valid?
|
||||
|
||||
const char * pcc = c; // pcc is a pointer to char constant
|
||||
char const * pcc2 = c; // What is the type of pcc2?
|
||||
|
||||
// For each of the following, why is the assignment:
|
||||
*pcc = '7'; // invalid?
|
||||
pcc = *pcp; // valid?
|
||||
pcc = argv[0]; // valid?
|
||||
|
||||
char * const cp = c; // cp is a const pointer to char
|
||||
// For each of the following, why is the assignment:
|
||||
cp = *pcp; // invalid?
|
||||
cp = *argv; // invalid?
|
||||
*cp = '!'; // valid?
|
||||
|
||||
const char * const cpc = c; // cpc is a const pointer to char const
|
||||
// For each of the following, why is the assignment:
|
||||
cpc = *pcp; // invalid?
|
||||
cpc = argv[0]; // invalid?
|
||||
*cpc = '@'; // invalid?
|
||||
|
||||
return 0;
|
||||
}
|
||||
21
ocw/1/c-primer/preprocess.c
Normal file
21
ocw/1/c-primer/preprocess.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2012 MIT License by 6.172 Staff
|
||||
|
||||
// All occurences of ONE will be replaced by 1.
|
||||
#define ONE 1
|
||||
|
||||
// Macros can also behave similar to inline functions.
|
||||
// Note that parentheses around arguments are required to preserve order of
|
||||
// operations. Otherwise, you can introduce bugs when substitution happens
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
int c = ONE, d = ONE + 5;
|
||||
int e = MIN(c, d);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// This code will be compiled only when
|
||||
// the macro NDEBUG is not defined.
|
||||
// Recall that if clang is passed -DNDEBUG on the command line,
|
||||
// then NDEBUG will be defined.
|
||||
if (something) {}
|
||||
#endif
|
||||
14
ocw/1/c-primer/sizes.c
Normal file
14
ocw/1/c-primer/sizes.c
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2012 MIT License by 6.172 Staff
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void subprocedure(int x, int y) {
|
||||
int z = x + y;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int x = 3, y = 5;
|
||||
subprocedure(x, y);
|
||||
}
|
||||
476
ocw/1/c-primer/sizes.s
Normal file
476
ocw/1/c-primer/sizes.s
Normal file
|
|
@ -0,0 +1,476 @@
|
|||
.file "sizes.c"
|
||||
.text
|
||||
.Ltext0:
|
||||
.file 0 "/home/frozen/dev/performance-engineering-ocw/1/c-primer" "sizes.c"
|
||||
.section .rodata
|
||||
.LC0:
|
||||
.string "size of int : %zu bytes \n"
|
||||
.LC1:
|
||||
.string "size of you : %zu bytes \n"
|
||||
.text
|
||||
.globl main
|
||||
.type main, @function
|
||||
main:
|
||||
.LFB6:
|
||||
.file 1 "sizes.c"
|
||||
.loc 1 9 12
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register 6
|
||||
subq $48, %rsp
|
||||
.loc 1 9 12
|
||||
movq %fs:40, %rax
|
||||
movq %rax, -8(%rbp)
|
||||
xorl %eax, %eax
|
||||
.loc 1 18 3
|
||||
leaq .LC0(%rip), %rax
|
||||
movl $4, %esi
|
||||
movq %rax, %rdi
|
||||
movl $0, %eax
|
||||
call printf@PLT
|
||||
.loc 1 35 10
|
||||
movl $12345, -40(%rbp)
|
||||
.loc 1 36 12
|
||||
movl $4, -36(%rbp)
|
||||
.loc 1 43 3
|
||||
leaq .LC1(%rip), %rax
|
||||
movl $8, %esi
|
||||
movq %rax, %rdi
|
||||
movl $0, %eax
|
||||
call printf@PLT
|
||||
.loc 1 45 10
|
||||
movl $0, %eax
|
||||
.loc 1 46 1
|
||||
movq -8(%rbp), %rdx
|
||||
subq %fs:40, %rdx
|
||||
je .L3
|
||||
call __stack_chk_fail@PLT
|
||||
.L3:
|
||||
leave
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE6:
|
||||
.size main, .-main
|
||||
.Letext0:
|
||||
.file 2 "/usr/include/stdio.h"
|
||||
.section .debug_info,"",@progbits
|
||||
.Ldebug_info0:
|
||||
.long 0x118
|
||||
.value 0x5
|
||||
.byte 0x1
|
||||
.byte 0x8
|
||||
.long .Ldebug_abbrev0
|
||||
.uleb128 0x3
|
||||
.long .LASF13
|
||||
.byte 0x1d
|
||||
.byte 0x3
|
||||
.long 0x31647
|
||||
.long .LASF0
|
||||
.long .LASF1
|
||||
.quad .Ltext0
|
||||
.quad .Letext0-.Ltext0
|
||||
.long .Ldebug_line0
|
||||
.uleb128 0x1
|
||||
.byte 0x8
|
||||
.byte 0x7
|
||||
.long .LASF2
|
||||
.uleb128 0x1
|
||||
.byte 0x4
|
||||
.byte 0x7
|
||||
.long .LASF3
|
||||
.uleb128 0x1
|
||||
.byte 0x1
|
||||
.byte 0x8
|
||||
.long .LASF4
|
||||
.uleb128 0x1
|
||||
.byte 0x2
|
||||
.byte 0x7
|
||||
.long .LASF5
|
||||
.uleb128 0x1
|
||||
.byte 0x1
|
||||
.byte 0x6
|
||||
.long .LASF6
|
||||
.uleb128 0x1
|
||||
.byte 0x2
|
||||
.byte 0x5
|
||||
.long .LASF7
|
||||
.uleb128 0x4
|
||||
.byte 0x4
|
||||
.byte 0x5
|
||||
.string "int"
|
||||
.uleb128 0x1
|
||||
.byte 0x8
|
||||
.byte 0x5
|
||||
.long .LASF8
|
||||
.uleb128 0x1
|
||||
.byte 0x1
|
||||
.byte 0x6
|
||||
.long .LASF9
|
||||
.uleb128 0x5
|
||||
.long 0x6b
|
||||
.uleb128 0x6
|
||||
.byte 0x8
|
||||
.long 0x72
|
||||
.uleb128 0x1
|
||||
.byte 0x8
|
||||
.byte 0x5
|
||||
.long .LASF10
|
||||
.uleb128 0x1
|
||||
.byte 0x8
|
||||
.byte 0x7
|
||||
.long .LASF11
|
||||
.uleb128 0x7
|
||||
.long .LASF14
|
||||
.byte 0x2
|
||||
.value 0x16b
|
||||
.byte 0xc
|
||||
.long 0x5d
|
||||
.long 0xa3
|
||||
.uleb128 0x8
|
||||
.long 0x77
|
||||
.uleb128 0x9
|
||||
.byte 0
|
||||
.uleb128 0xa
|
||||
.long .LASF15
|
||||
.byte 0x1
|
||||
.byte 0x9
|
||||
.byte 0x5
|
||||
.long 0x5d
|
||||
.quad .LFB6
|
||||
.quad .LFE6-.LFB6
|
||||
.uleb128 0x1
|
||||
.byte 0x9c
|
||||
.long 0x10f
|
||||
.uleb128 0xb
|
||||
.byte 0x8
|
||||
.byte 0x1
|
||||
.byte 0x1d
|
||||
.byte 0xb
|
||||
.long 0xe8
|
||||
.uleb128 0xc
|
||||
.string "id"
|
||||
.byte 0x1
|
||||
.byte 0x1e
|
||||
.byte 0x9
|
||||
.long 0x5d
|
||||
.byte 0
|
||||
.uleb128 0xd
|
||||
.long .LASF12
|
||||
.byte 0x1
|
||||
.byte 0x1f
|
||||
.byte 0x9
|
||||
.long 0x5d
|
||||
.byte 0x4
|
||||
.byte 0
|
||||
.uleb128 0xe
|
||||
.long .LASF16
|
||||
.byte 0x1
|
||||
.byte 0x20
|
||||
.byte 0x5
|
||||
.long 0xc5
|
||||
.uleb128 0x2
|
||||
.string "you"
|
||||
.byte 0x22
|
||||
.byte 0xb
|
||||
.long 0xe8
|
||||
.uleb128 0x2
|
||||
.byte 0x91
|
||||
.sleb128 -56
|
||||
.uleb128 0x2
|
||||
.string "x"
|
||||
.byte 0x28
|
||||
.byte 0x7
|
||||
.long 0x10f
|
||||
.uleb128 0x2
|
||||
.byte 0x91
|
||||
.sleb128 -48
|
||||
.byte 0
|
||||
.uleb128 0xf
|
||||
.long 0x5d
|
||||
.uleb128 0x10
|
||||
.long 0x33
|
||||
.byte 0x4
|
||||
.byte 0
|
||||
.byte 0
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.Ldebug_abbrev0:
|
||||
.uleb128 0x1
|
||||
.uleb128 0x24
|
||||
.byte 0
|
||||
.uleb128 0xb
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3e
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3
|
||||
.uleb128 0xe
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0x2
|
||||
.uleb128 0x34
|
||||
.byte 0
|
||||
.uleb128 0x3
|
||||
.uleb128 0x8
|
||||
.uleb128 0x3a
|
||||
.uleb128 0x21
|
||||
.sleb128 1
|
||||
.uleb128 0x3b
|
||||
.uleb128 0xb
|
||||
.uleb128 0x39
|
||||
.uleb128 0xb
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.uleb128 0x2
|
||||
.uleb128 0x18
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0x3
|
||||
.uleb128 0x11
|
||||
.byte 0x1
|
||||
.uleb128 0x25
|
||||
.uleb128 0xe
|
||||
.uleb128 0x13
|
||||
.uleb128 0xb
|
||||
.uleb128 0x90
|
||||
.uleb128 0xb
|
||||
.uleb128 0x91
|
||||
.uleb128 0x6
|
||||
.uleb128 0x3
|
||||
.uleb128 0x1f
|
||||
.uleb128 0x1b
|
||||
.uleb128 0x1f
|
||||
.uleb128 0x11
|
||||
.uleb128 0x1
|
||||
.uleb128 0x12
|
||||
.uleb128 0x7
|
||||
.uleb128 0x10
|
||||
.uleb128 0x17
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0x4
|
||||
.uleb128 0x24
|
||||
.byte 0
|
||||
.uleb128 0xb
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3e
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3
|
||||
.uleb128 0x8
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0x5
|
||||
.uleb128 0x26
|
||||
.byte 0
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0x6
|
||||
.uleb128 0xf
|
||||
.byte 0
|
||||
.uleb128 0xb
|
||||
.uleb128 0xb
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0x7
|
||||
.uleb128 0x2e
|
||||
.byte 0x1
|
||||
.uleb128 0x3f
|
||||
.uleb128 0x19
|
||||
.uleb128 0x3
|
||||
.uleb128 0xe
|
||||
.uleb128 0x3a
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3b
|
||||
.uleb128 0x5
|
||||
.uleb128 0x39
|
||||
.uleb128 0xb
|
||||
.uleb128 0x27
|
||||
.uleb128 0x19
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.uleb128 0x3c
|
||||
.uleb128 0x19
|
||||
.uleb128 0x1
|
||||
.uleb128 0x13
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0x8
|
||||
.uleb128 0x5
|
||||
.byte 0
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0x9
|
||||
.uleb128 0x18
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0xa
|
||||
.uleb128 0x2e
|
||||
.byte 0x1
|
||||
.uleb128 0x3f
|
||||
.uleb128 0x19
|
||||
.uleb128 0x3
|
||||
.uleb128 0xe
|
||||
.uleb128 0x3a
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3b
|
||||
.uleb128 0xb
|
||||
.uleb128 0x39
|
||||
.uleb128 0xb
|
||||
.uleb128 0x27
|
||||
.uleb128 0x19
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.uleb128 0x11
|
||||
.uleb128 0x1
|
||||
.uleb128 0x12
|
||||
.uleb128 0x7
|
||||
.uleb128 0x40
|
||||
.uleb128 0x18
|
||||
.uleb128 0x7c
|
||||
.uleb128 0x19
|
||||
.uleb128 0x1
|
||||
.uleb128 0x13
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0xb
|
||||
.uleb128 0x13
|
||||
.byte 0x1
|
||||
.uleb128 0xb
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3a
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3b
|
||||
.uleb128 0xb
|
||||
.uleb128 0x39
|
||||
.uleb128 0xb
|
||||
.uleb128 0x1
|
||||
.uleb128 0x13
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0xc
|
||||
.uleb128 0xd
|
||||
.byte 0
|
||||
.uleb128 0x3
|
||||
.uleb128 0x8
|
||||
.uleb128 0x3a
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3b
|
||||
.uleb128 0xb
|
||||
.uleb128 0x39
|
||||
.uleb128 0xb
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.uleb128 0x38
|
||||
.uleb128 0xb
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0xd
|
||||
.uleb128 0xd
|
||||
.byte 0
|
||||
.uleb128 0x3
|
||||
.uleb128 0xe
|
||||
.uleb128 0x3a
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3b
|
||||
.uleb128 0xb
|
||||
.uleb128 0x39
|
||||
.uleb128 0xb
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.uleb128 0x38
|
||||
.uleb128 0xb
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0xe
|
||||
.uleb128 0x16
|
||||
.byte 0
|
||||
.uleb128 0x3
|
||||
.uleb128 0xe
|
||||
.uleb128 0x3a
|
||||
.uleb128 0xb
|
||||
.uleb128 0x3b
|
||||
.uleb128 0xb
|
||||
.uleb128 0x39
|
||||
.uleb128 0xb
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0xf
|
||||
.uleb128 0x1
|
||||
.byte 0x1
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.byte 0
|
||||
.byte 0
|
||||
.uleb128 0x10
|
||||
.uleb128 0x21
|
||||
.byte 0
|
||||
.uleb128 0x49
|
||||
.uleb128 0x13
|
||||
.uleb128 0x2f
|
||||
.uleb128 0xb
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.section .debug_aranges,"",@progbits
|
||||
.long 0x2c
|
||||
.value 0x2
|
||||
.long .Ldebug_info0
|
||||
.byte 0x8
|
||||
.byte 0
|
||||
.value 0
|
||||
.value 0
|
||||
.quad .Ltext0
|
||||
.quad .Letext0-.Ltext0
|
||||
.quad 0
|
||||
.quad 0
|
||||
.section .debug_line,"",@progbits
|
||||
.Ldebug_line0:
|
||||
.section .debug_str,"MS",@progbits,1
|
||||
.LASF10:
|
||||
.string "long long int"
|
||||
.LASF3:
|
||||
.string "unsigned int"
|
||||
.LASF15:
|
||||
.string "main"
|
||||
.LASF13:
|
||||
.string "GNU C23 15.1.1 20250425 -mtune=generic -march=x86-64 -g -O0"
|
||||
.LASF2:
|
||||
.string "long unsigned int"
|
||||
.LASF11:
|
||||
.string "long long unsigned int"
|
||||
.LASF4:
|
||||
.string "unsigned char"
|
||||
.LASF9:
|
||||
.string "char"
|
||||
.LASF8:
|
||||
.string "long int"
|
||||
.LASF16:
|
||||
.string "student"
|
||||
.LASF12:
|
||||
.string "year"
|
||||
.LASF5:
|
||||
.string "short unsigned int"
|
||||
.LASF14:
|
||||
.string "printf"
|
||||
.LASF7:
|
||||
.string "short int"
|
||||
.LASF6:
|
||||
.string "signed char"
|
||||
.section .debug_line_str,"MS",@progbits,1
|
||||
.LASF0:
|
||||
.string "sizes.c"
|
||||
.LASF1:
|
||||
.string "/home/frozen/dev/performance-engineering-ocw/1/c-primer"
|
||||
.ident "GCC: (GNU) 15.1.1 20250425"
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
21
ocw/1/c-primer/swap.c
Normal file
21
ocw/1/c-primer/swap.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2012 MIT License by 6.172 Staff
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void swap(int i, int j) {
|
||||
int temp = i;
|
||||
i = j;
|
||||
j = temp;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int k = 1;
|
||||
int m = 2;
|
||||
swap(k, m);
|
||||
// What does this print?
|
||||
printf("k = %d, m = %d\n", k, m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
111
ocw/1/c-primer/verifier.py
Normal file
111
ocw/1/c-primer/verifier.py
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/python
|
||||
import subprocess, os, sys, re
|
||||
|
||||
def exitWithError(error):
|
||||
print error
|
||||
sys.exit(1)
|
||||
|
||||
def runAndReadOutput(args):
|
||||
if args is str:
|
||||
args = [args]
|
||||
try:
|
||||
return subprocess.check_output(args)
|
||||
except subprocess.CalledProcessError as e:
|
||||
exitWithError("ERROR: runtime error with %s" % str(args))
|
||||
|
||||
def run(path): runAndReadOutput(path)
|
||||
|
||||
def runAndCheckSizes():
|
||||
output = runAndReadOutput("./sizes")
|
||||
expected_output_format = "size of %s : %d bytes"
|
||||
|
||||
lines = set([x.replace(" ", "") for x in output.strip().lower().split('\n')])
|
||||
types = [
|
||||
( "int", 4 ),
|
||||
( "short", 2 ),
|
||||
( "long", 8 ),
|
||||
( "char", 1 ),
|
||||
( "float", 4 ),
|
||||
( "double", 8 ),
|
||||
( "unsigned int", 4 ),
|
||||
( "long long", 8 ),
|
||||
( "uint8_t", 1 ),
|
||||
( "uint16_t", 2 ),
|
||||
( "uint32_t", 4 ),
|
||||
( "uint64_t", 8 ),
|
||||
( "uint_fast8_t", 1 ),
|
||||
( "uint_fast16_t", 8 ),
|
||||
( "uintmax_t", 8 ),
|
||||
( "intmax_t", 8 ),
|
||||
( "__int128", 16 ),
|
||||
( "uint32_t", 4 ),
|
||||
( "uint64_t", 8 ),
|
||||
( "student", 8 ),
|
||||
( "x", 20),
|
||||
( "int*", 8 ),
|
||||
( "short*", 8 ),
|
||||
( "long*", 8 ),
|
||||
( "char*", 8 ),
|
||||
( "float*", 8 ),
|
||||
( "double*", 8 ),
|
||||
( "unsigned int*", 8 ),
|
||||
( "long long*", 8 ),
|
||||
( "uint8_t*", 8 ),
|
||||
( "uint16_t*", 8 ),
|
||||
( "uint32_t*", 8 ),
|
||||
( "uint64_t*", 8 ),
|
||||
( "uint_fast8_t*", 8 ),
|
||||
( "uint_fast16_t*", 8 ),
|
||||
( "uintmax_t*", 8 ),
|
||||
( "intmax_t*", 8 ),
|
||||
( "__int128*", 8 ),
|
||||
( "uint32_t*", 8 ),
|
||||
( "uint64_t*", 8 ),
|
||||
( "student*", 8 ),
|
||||
( "&x", 8)
|
||||
]
|
||||
|
||||
for typ in types:
|
||||
print (expected_output_format % typ)
|
||||
if (expected_output_format % typ).replace(" ", "") not in lines:
|
||||
exitWithError("ERROR: couldn't find type %s (or it has the incorrect value) in sizes output" % typ[0])
|
||||
|
||||
def runAndCheckSwap():
|
||||
expected_output = "k = 2, m = 1\n"
|
||||
output = runAndReadOutput("./swap")
|
||||
|
||||
if output != expected_output:
|
||||
exitWithError('ERROR: actual output: "%s", expected "%s"' % (output, expected_output))
|
||||
|
||||
def build(make_arg, filename):
|
||||
print "\nRunning make %s ... " % make_arg
|
||||
run(["make", filename])
|
||||
print "Ok!"
|
||||
|
||||
print "\nChecking that %s was built ... " % filename
|
||||
if not os.path.isfile(filename):
|
||||
exitWithError("ERROR: %s binary missing, did you rename it?" % filename)
|
||||
print "Ok!"
|
||||
|
||||
|
||||
print "Running verifying script ... "
|
||||
|
||||
print "\nChecking that the Makefile exists ... "
|
||||
if not os.path.isfile('Makefile'):
|
||||
exitWithError('ERROR: Makefile does not exist.')
|
||||
print "Good!"
|
||||
|
||||
build("sizes", "sizes")
|
||||
print "Checking output of sizes ... "
|
||||
runAndCheckSizes()
|
||||
print "Ok!"
|
||||
|
||||
build("pointer", "pointer")
|
||||
run("./pointer") # Run pointer as a sanity check, but there's no output to check
|
||||
|
||||
build("swap", "swap")
|
||||
print "Checking output of swap ... "
|
||||
runAndCheckSwap()
|
||||
print "Ok!"
|
||||
|
||||
print "LGTM"
|
||||
105
ocw/1/matrix-multiply/Makefile
Normal file
105
ocw/1/matrix-multiply/Makefile
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# Copyright (c) 2012 MIT License by 6.172 Staff
|
||||
|
||||
# List all of your source files here (but not your headers), separated by
|
||||
# spaces. You'll have to add to this list every time you create a new
|
||||
# source file.
|
||||
SRC := testbed.c matrix_multiply.c
|
||||
|
||||
# Set the name of your binary. Change it if you like.
|
||||
PRODUCT := matrix_multiply
|
||||
|
||||
################################################################################
|
||||
# These configuration options change how your code (listed above) is compiled
|
||||
# every time you type "make". You may have to change these values to complete
|
||||
# some assignments; you should also feel free to experiment with them.
|
||||
################################################################################
|
||||
|
||||
# This option sets which compiler your code will be compiled with. Likely
|
||||
# choices are icc, icpc, gcc, g++, clang
|
||||
CC := clang
|
||||
|
||||
# These flags will be applied to your code any time it is built.
|
||||
CFLAGS := -Wall -std=c99 -D_POSIX_C_SOURCE=200809L -O3
|
||||
|
||||
# These flags are applied only if you build your code with "make DEBUG=1". -g
|
||||
# generates debugging symbols, -DDEBUG defines the preprocessor symbol "DEBUG"
|
||||
# (so that you can use "#ifdef DEBUG" in your code), and -O0 disables compiler
|
||||
# optimizations, so that the binary generated more directly corresponds to your
|
||||
# source code.
|
||||
CFLAGS_DEBUG := -g -DDEBUG -O0
|
||||
|
||||
# In the release version, we ask for many optimizations; -O3 sets the
|
||||
# optimization level to three. -DNDEBUG defines the NDEBUG macro,
|
||||
# which disables assertion checks.
|
||||
CFLAGS_RELEASE := -O1 -DNDEBUG
|
||||
|
||||
# These flags are used to invoke Clang's address sanitizer.
|
||||
CFLAGS_ASAN := -O1 -g -fsanitize=address
|
||||
|
||||
# These flags are applied when linking object files together into your binary.
|
||||
# If you need to link against libraries, add the appropriate flags here. By
|
||||
# default, your code is linked against the "rt" library with the flag -lrt;
|
||||
# this library is used by the timing code in the testbed.
|
||||
LDFLAGS := -lrt -flto -fuse-ld=gold
|
||||
|
||||
################################################################################
|
||||
# You probably won't need to change anything below this line, but if you're
|
||||
# curious about how makefiles work, or if you'd like to customize the behavior
|
||||
# of your makefile, go ahead and take a peek.
|
||||
################################################################################
|
||||
|
||||
# You shouldn't need to touch this. This keeps track of whether you are
|
||||
# building in a release or debug configuration, and sets CFLAGS appropriately.
|
||||
# (This mechanism is based on one from the original materials for 6.197 by
|
||||
# Ceryen Tan and Marek Olszewski.)
|
||||
OLDMODE=$(shell cat .buildmode 2> /dev/null)
|
||||
ifeq ($(DEBUG),1)
|
||||
CFLAGS := $(CFLAGS_DEBUG) $(CFLAGS)
|
||||
ifneq ($(OLDMODE),debug)
|
||||
$(shell echo debug > .buildmode)
|
||||
endif
|
||||
else ifeq ($(ASAN),1)
|
||||
CFLAGS := $(CFLAGS_ASAN) $(CFLAGS)
|
||||
LDFLAGS := $(LDFLAGS) -fsanitize=address
|
||||
ifneq ($(OLDMODE),asan)
|
||||
$(shell echo asan > .buildmode)
|
||||
endif
|
||||
else
|
||||
CFLAGS := $(CFLAGS_RELEASE) $(CFLAGS)
|
||||
ifneq ($(OLDMODE),nodebug)
|
||||
$(shell echo nodebug > .buildmode)
|
||||
endif
|
||||
endif
|
||||
|
||||
# When you invoke make without an argument, make behaves as though you had
|
||||
# typed "make all", and builds whatever you have listed here. (It knows to
|
||||
# pick "make all" because "all" is the first rule listed.)
|
||||
all: $(PRODUCT)
|
||||
|
||||
# This special "target" will remove the binary and all intermediate files.
|
||||
clean::
|
||||
rm -f $(OBJ) $(PRODUCT) .buildmode \
|
||||
$(addsuffix .gcda, $(basename $(SRC))) \
|
||||
$(addsuffix .gcno, $(basename $(SRC))) \
|
||||
$(addsuffix .gcov, $(SRC) fasttime.h)
|
||||
|
||||
# This rule generates a list of object names. Each of your source files (but
|
||||
# not your header files) produces a single object file when it's compiled. In
|
||||
# a later step, all of those object files are linked together to produce the
|
||||
# binary that you run.
|
||||
OBJ = $(addsuffix .o, $(basename $(SRC)))
|
||||
|
||||
# These rules tell make how to automatically generate rules that build the
|
||||
# appropriate object-file from each of the source files listed in SRC (above).
|
||||
%.o : %.c .buildmode
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
%.o : %.cc .buildmode
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
%.o : %.cpp .buildmode
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
# This rule tells make that it can produce your binary by linking together all
|
||||
# of the object files produced from your source files and any necessary
|
||||
# libraries.
|
||||
$(PRODUCT): $(OBJ) .buildmode
|
||||
$(CC) -o $@ $(OBJ) $(LDFLAGS)
|
||||
95
ocw/1/matrix-multiply/fasttime.h
Normal file
95
ocw/1/matrix-multiply/fasttime.h
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* Copyright (c) 2014 MIT License by 6.172 Staff
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
**/
|
||||
|
||||
#ifndef INCLUDED_FASTTIME_DOT_H
|
||||
#define INCLUDED_FASTTIME_DOT_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __MACH__
|
||||
#include <mach/mach_time.h> // mach_absolute_time
|
||||
|
||||
typedef uint64_t fasttime_t;
|
||||
|
||||
|
||||
// Return the current time.
|
||||
static inline fasttime_t gettime(void) {
|
||||
return mach_absolute_time();
|
||||
}
|
||||
|
||||
// Return the time different between the start and the end, as a float
|
||||
// in units of seconds. This function does not need to be fast.
|
||||
// Implementation notes: See
|
||||
// https://developer.apple.com/library/mac/qa/qa1398/_index.html
|
||||
static inline double tdiff(fasttime_t start, fasttime_t end) {
|
||||
static mach_timebase_info_data_t timebase;
|
||||
int r = mach_timebase_info(&timebase);
|
||||
assert(r == 0);
|
||||
fasttime_t elapsed = end-start;
|
||||
double ns = (double)elapsed * timebase.numer / timebase.denom;
|
||||
return ns*1e-9;
|
||||
}
|
||||
|
||||
static inline unsigned int random_seed_from_clock(void) {
|
||||
fasttime_t now = gettime();
|
||||
return (now & 0xFFFFFFFF) + (now>>32);
|
||||
}
|
||||
|
||||
#else // LINUX
|
||||
|
||||
// We need _POSIX_C_SOURCE to pick up 'struct timespec' and clock_gettime.
|
||||
// #define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include <time.h>
|
||||
|
||||
typedef struct timespec fasttime_t;
|
||||
|
||||
// Return the current time.
|
||||
static inline fasttime_t gettime(void) {
|
||||
struct timespec s;
|
||||
#ifdef NDEBUG
|
||||
clock_gettime(CLOCK_MONOTONIC, &s);
|
||||
#else
|
||||
int r = clock_gettime(CLOCK_MONOTONIC, &s);
|
||||
assert(r == 0);
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
||||
// Return the time different between the start and the end, as a float
|
||||
// in units of seconds. This function does not need to be fast.
|
||||
static inline double tdiff(fasttime_t start, fasttime_t end) {
|
||||
return end.tv_sec - start.tv_sec + 1e-9*(end.tv_nsec - start.tv_nsec);
|
||||
}
|
||||
|
||||
static inline unsigned int random_seed_from_clock(void) {
|
||||
fasttime_t now = gettime();
|
||||
return now.tv_sec + now.tv_nsec;
|
||||
}
|
||||
|
||||
// Poison these symbols to help find portability problems.
|
||||
int clock_gettime(clockid_t, struct timespec *) __attribute__((deprecated));
|
||||
time_t time(time_t *) __attribute__((deprecated));
|
||||
|
||||
#endif // LINUX
|
||||
|
||||
#endif // INCLUDED_FASTTIME_DOT_H
|
||||
96
ocw/1/matrix-multiply/matrix_multiply.c
Normal file
96
ocw/1/matrix-multiply/matrix_multiply.c
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* Copyright (c) 2012 MIT License by 6.172 Staff
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
**/
|
||||
|
||||
#include "./matrix_multiply.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
// #include "./tbassert.h"
|
||||
|
||||
// Allocates a row-by-cols matrix and returns it
|
||||
matrix* make_matrix(int rows, int cols) {
|
||||
matrix* new_matrix = malloc(sizeof(matrix));
|
||||
|
||||
// Set the number of rows and columns
|
||||
new_matrix->rows = rows;
|
||||
new_matrix->cols = cols;
|
||||
|
||||
// Allocate a buffer big enough to hold the matrix.
|
||||
new_matrix->values = (int**)malloc(sizeof(int*) * rows);
|
||||
for (int i = 0; i < rows; i++) {
|
||||
new_matrix->values[i] = (int*)malloc(sizeof(int) * cols);
|
||||
}
|
||||
|
||||
return new_matrix;
|
||||
}
|
||||
|
||||
// Frees an allocated matrix
|
||||
void free_matrix(matrix* m) {
|
||||
for (int i = 0; i < m->rows; i++) {
|
||||
free(m->values[i]);
|
||||
}
|
||||
free(m->values);
|
||||
free(m);
|
||||
}
|
||||
|
||||
// Print matrix
|
||||
void print_matrix(const matrix* m) {
|
||||
printf("------------\n");
|
||||
for (int i = 0; i < m->rows; i++) {
|
||||
for (int j = 0; j < m->cols; j++) {
|
||||
printf(" %3d ", m->values[i][j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("------------\n");
|
||||
}
|
||||
|
||||
|
||||
// Multiply matrix A*B, store result in C.
|
||||
int matrix_multiply_run(const matrix* A, const matrix* B, matrix* C) {
|
||||
/*
|
||||
tbassert(A->cols == B->rows,
|
||||
"A->cols = %d, B->rows = %d\n", A->cols, B->rows);
|
||||
tbassert(A->rows == C->rows,
|
||||
"A->rows = %d, C->rows = %d\n", A->rows, C->rows);
|
||||
tbassert(B->cols == C->cols,
|
||||
"B->cols = %d, C->cols = %d\n", B->cols, C->cols);
|
||||
*/
|
||||
|
||||
for (int i = 0; i < A->rows; i++) {
|
||||
for (int j = 0; j < B->cols; j++) {
|
||||
for (int k = 0; k < A->cols; k++) {
|
||||
C->values[i][j] += A->values[i][k] * B->values[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
58
ocw/1/matrix-multiply/matrix_multiply.h
Normal file
58
ocw/1/matrix-multiply/matrix_multiply.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright (c) 2012 MIT License by 6.172 Staff
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* Matrix Multiply
|
||||
*
|
||||
*
|
||||
* Declarations here are your API specification -- we expect that your
|
||||
* code defines and correctly implements these functions and does not modify
|
||||
* the way the reference implementation uses variables mentioned here,
|
||||
* so that we may call them from testbed.c and any other testing software
|
||||
* that we write!
|
||||
*
|
||||
* Deviating from this API may cause your program to fail all of our tests.
|
||||
**/
|
||||
|
||||
#ifndef MATRIX_MULTIPLY_H_INCLUDED
|
||||
|
||||
#define MATRIX_MULTIPLY_H_INCLUDED
|
||||
|
||||
typedef struct {
|
||||
int rows;
|
||||
int cols;
|
||||
int** values;
|
||||
} matrix;
|
||||
|
||||
// Multiply matrix A*B, store result in C.
|
||||
int matrix_multiply_run(const matrix* A, const matrix* B, matrix* C);
|
||||
|
||||
// Allocates a row-by-cols matrix and returns it
|
||||
matrix* make_matrix(int rows, int cols);
|
||||
|
||||
// Frees an allocated matrix
|
||||
void free_matrix(matrix* m);
|
||||
|
||||
// Print matrix
|
||||
void print_matrix(const matrix* m);
|
||||
#endif // MATRIX_MULTIPLY_H_INCLUDED
|
||||
73
ocw/1/matrix-multiply/tbassert.h
Normal file
73
ocw/1/matrix-multiply/tbassert.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* Copyright (c) 2014 MIT License by Tao B. Schardl
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
**/
|
||||
|
||||
#ifndef _TBASSERT_H_
|
||||
#define _TBASSERT_H_ 1
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
/**************************************************************************
|
||||
* Library of debugging macros.
|
||||
*************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Print a message to STREAM when DEBUG = 1. This macro takes the
|
||||
// same arguments as FPRINTF().
|
||||
#define DEBUG_FPRINTF(STREAM, ...) \
|
||||
do { \
|
||||
fprintf(STREAM, "%s:%d (%s) ", \
|
||||
__FILE__, __LINE__, __PRETTY_FUNCTION__); \
|
||||
fprintf(STREAM, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
// Print a message to STDERR when DEBUG = 1. This macro takes the
|
||||
// same arguments as PRINTF().
|
||||
#define DEBUG_EPRINTF(...) DEBUG_FPRINTF(stderr, __VA_ARGS__);
|
||||
|
||||
// If PREDICATE is true, do nothing. Otherwise, print an error with
|
||||
// the specified message to STDERR. This macro only operates when
|
||||
// DEBUG = 1. This macro takes a PREDICATE to evaluate followed by
|
||||
// the standard arguments to PRINTF().
|
||||
#define DEBUG_ASSERT(PREDICATE, ...) \
|
||||
do { \
|
||||
if (!(PREDICATE)) { \
|
||||
fprintf(stderr, "%s:%d (%s) Assertion " #PREDICATE " failed: ", \
|
||||
__FILE__, __LINE__, __PRETTY_FUNCTION__); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define tbassert DEBUG_ASSERT
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG_PRINTF(...) // Nothing.
|
||||
#define DEBUG_EPRINTF(...) // Nothing.
|
||||
#define DEBUG_ASSERT(...) // Nothing.
|
||||
#define tbassert(...) // Nothing.
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _TBASSERT_H_
|
||||
154
ocw/1/matrix-multiply/testbed.c
Normal file
154
ocw/1/matrix-multiply/testbed.c
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/**
|
||||
* Copyright (c) 2012 MIT License by 6.172 Staff
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* testbed.c:
|
||||
*
|
||||
* This file runs your code, timing its execution and printing out the result.
|
||||
**/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "./fasttime.h"
|
||||
#include "./matrix_multiply.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int optchar = 0;
|
||||
int show_usec = 0;
|
||||
int should_print = 0;
|
||||
int use_zero_matrix = 0;
|
||||
|
||||
// Always use the same seed, so that our tests are repeatable.
|
||||
unsigned int randomSeed = 1;
|
||||
|
||||
matrix* A;
|
||||
matrix* B;
|
||||
matrix* C;
|
||||
|
||||
const int kMatrixSize = 4;
|
||||
|
||||
|
||||
// Parse command line arguments
|
||||
while ((optchar = getopt(argc, argv, "upz")) != -1) {
|
||||
switch (optchar) {
|
||||
case 'u':
|
||||
show_usec = 1;
|
||||
break;
|
||||
case 'p':
|
||||
should_print = 1;
|
||||
break;
|
||||
case 'z':
|
||||
use_zero_matrix = 1;
|
||||
break;
|
||||
default:
|
||||
printf("Ignoring unrecognized option: %c\n", optchar);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a trick to make the memory bug leads to a wrong output.
|
||||
int size = sizeof(int) * 4;
|
||||
int* temp[20];
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
temp[i] = (int*)malloc(size);
|
||||
memset(temp[i], 1, size);
|
||||
}
|
||||
int total = 0;
|
||||
for (int i = 0; i < 20; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
total += temp[i][j];
|
||||
}
|
||||
}
|
||||
if (!total) printf("Trick to stop mallocs from being optimized out.");
|
||||
for (int i = 0; i < 20; i++) {
|
||||
free(temp[i]);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Setup\n");
|
||||
|
||||
A = make_matrix(kMatrixSize, kMatrixSize+1);
|
||||
B = make_matrix(kMatrixSize, kMatrixSize);
|
||||
C = make_matrix(kMatrixSize, kMatrixSize);
|
||||
|
||||
if (use_zero_matrix) {
|
||||
for (int i = 0; i < A->rows; i++) {
|
||||
for (int j = 0; j < A->cols; j++) {
|
||||
A->values[i][j] = 0;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < B->rows; i++) {
|
||||
for (int j = 0; j < B->cols; j++) {
|
||||
B->values[i][j] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < A->rows; i++) {
|
||||
for (int j = 0; j < A->cols; j++) {
|
||||
A->values[i][j] = rand_r(&randomSeed) % 10;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < B->rows; i++) {
|
||||
for (int j = 0; j < B->cols; j++) {
|
||||
B->values[i][j] = rand_r(&randomSeed) % 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (should_print) {
|
||||
printf("Matrix A: \n");
|
||||
print_matrix(A);
|
||||
|
||||
printf("Matrix B: \n");
|
||||
print_matrix(B);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Running matrix_multiply_run()...\n");
|
||||
|
||||
fasttime_t time1 = gettime();
|
||||
matrix_multiply_run(A, B, C);
|
||||
fasttime_t time2 = gettime();
|
||||
|
||||
if (should_print) {
|
||||
printf("---- RESULTS ----\n");
|
||||
printf("Result: \n");
|
||||
print_matrix(C);
|
||||
printf("---- END RESULTS ----\n");
|
||||
}
|
||||
|
||||
if (show_usec) {
|
||||
double elapsed = tdiff(time1, time2);
|
||||
printf("Elapsed execution time: %f usec\n",
|
||||
elapsed * (1000.0 * 1000.0));
|
||||
} else {
|
||||
double elapsed = tdiff(time1, time2);
|
||||
printf("Elapsed execution time: %f sec\n", elapsed);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
52
ocw/1/sizes.s
Normal file
52
ocw/1/sizes.s
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
.file "sizes.c"
|
||||
.text
|
||||
.globl subprocedure
|
||||
.type subprocedure, @function
|
||||
subprocedure:
|
||||
.LFB6:
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register 6
|
||||
movl %edi, -20(%rbp)
|
||||
movl %esi, -24(%rbp)
|
||||
movl -20(%rbp), %edx
|
||||
movl -24(%rbp), %eax
|
||||
addl %edx, %eax
|
||||
movl %eax, -4(%rbp)
|
||||
nop
|
||||
popq %rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE6:
|
||||
.size subprocedure, .-subprocedure
|
||||
.globl main
|
||||
.type main, @function
|
||||
main:
|
||||
.LFB7:
|
||||
.cfi_startproc
|
||||
pushq %rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
movq %rsp, %rbp
|
||||
.cfi_def_cfa_register 6
|
||||
subq $16, %rsp
|
||||
movl $3, -8(%rbp)
|
||||
movl $5, -4(%rbp)
|
||||
movl -4(%rbp), %edx
|
||||
movl -8(%rbp), %eax
|
||||
movl %edx, %esi
|
||||
movl %eax, %edi
|
||||
call subprocedure
|
||||
movl $0, %eax
|
||||
leave
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE7:
|
||||
.size main, .-main
|
||||
.ident "GCC: (GNU) 15.1.1 20250425"
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
BIN
ocw/bit-hacks/a.out
Executable file
BIN
ocw/bit-hacks/a.out
Executable file
Binary file not shown.
2
ocw/bit-hacks/a.py
Normal file
2
ocw/bit-hacks/a.py
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
class S:
|
||||
def __init__(self)
|
||||
2
ocw/bit-hacks/compile_flags.txt
Normal file
2
ocw/bit-hacks/compile_flags.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
-O2
|
||||
-masm=intel
|
||||
12
ocw/bit-hacks/hacks.cc
Normal file
12
ocw/bit-hacks/hacks.cc
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
int x = 123;
|
||||
int y = 123123;
|
||||
|
||||
std::cout << x;
|
||||
std::swap(x, y);
|
||||
std::cout << y;
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
ocw/bit-hacks/structop
Executable file
BIN
ocw/bit-hacks/structop
Executable file
Binary file not shown.
15
ocw/bit-hacks/structop.cc
Normal file
15
ocw/bit-hacks/structop.cc
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#include <cstddef>
|
||||
#include <iostream>
|
||||
|
||||
struct S {
|
||||
char b;
|
||||
int i;
|
||||
};
|
||||
|
||||
int main() {
|
||||
S s;
|
||||
|
||||
std::cout << offsetof(S, i) << '\n';
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
ocw/profiling/a.out
Executable file
BIN
ocw/profiling/a.out
Executable file
Binary file not shown.
6165
ocw/profiling/cachegrind.out.1193934
Normal file
6165
ocw/profiling/cachegrind.out.1193934
Normal file
File diff suppressed because it is too large
Load diff
89225
ocw/profiling/demangled.s
Normal file
89225
ocw/profiling/demangled.s
Normal file
File diff suppressed because it is too large
Load diff
39
ocw/profiling/notes.md
Normal file
39
ocw/profiling/notes.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# profiling
|
||||
|
||||
## intro
|
||||
|
||||
### instrumentation: overall timing (usual idea)
|
||||
|
||||
- while timing a clock with `time_the_clock.cc`, i erroneously initialized a
|
||||
`chrono::microseconds` default. this can be seen in the STL source: the default constructor
|
||||
initializes the `Rep` (repeated value, the unit for the duration) by
|
||||
default. A `microsecond` is a long here - this became garbage.
|
||||
- NOTE: timing the clock (with 0 optimization) took ~0ns and is not of significance for my profiling. I concluded this by compiling with `-O0` and de-mangling with c++filt we can see this is the case: we can see this is the case and nothing is being optimized out:
|
||||
|
||||
```asm
|
||||
.L585:
|
||||
call std::chrono::_V2::system_clock::now()@PLT
|
||||
movq %rax, -64(%rbp)
|
||||
call std::chrono::_V2::system_clock::now()@PLT
|
||||
```
|
||||
However, I acknowledge that this code is not run one-for-one. I don't have the
|
||||
knowledge to assess caching done by the actual CPU itself, or even other side
|
||||
effects like inlining.
|
||||
|
||||
So far, though, one lesson of profiling is:
|
||||
|
||||
> Only profile the code *actually* being profiled
|
||||
|
||||
### statistical profiling
|
||||
|
||||
- more accurate by *experimental* virtue - probabilistic look
|
||||
- imagine the execution of the program as a "strip" of time
|
||||
- system-specific, but so was before
|
||||
|
||||
- statistical: stats
|
||||
- program simulation: ll
|
||||
|
||||
## exercise 1
|
||||
- use cachegrind/valgrind/asan on cf problem
|
||||
- apply bentley's rules to some code
|
||||
- begin developing a strategy for how to profile things
|
||||
26698
ocw/profiling/output.svg
Normal file
26698
ocw/profiling/output.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 1.2 MiB |
BIN
ocw/profiling/perf-tester
Executable file
BIN
ocw/profiling/perf-tester
Executable file
Binary file not shown.
19
ocw/profiling/perf-tester.cc
Normal file
19
ocw/profiling/perf-tester.cc
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include <iostream>
|
||||
|
||||
void complex_method() {
|
||||
int i = 0x12323333- 1230*123213;
|
||||
long x = -23;
|
||||
std::cout << "x: " << x << '\n';
|
||||
while (--i) {
|
||||
x ^= (x - 1);
|
||||
for (int j = 0; j < 50; ++j) {
|
||||
x = x * x * x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
complex_method();
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
ocw/profiling/perf.data
Normal file
BIN
ocw/profiling/perf.data
Normal file
Binary file not shown.
BIN
ocw/profiling/perf.data.old
Normal file
BIN
ocw/profiling/perf.data.old
Normal file
Binary file not shown.
114179
ocw/profiling/perf.script
Normal file
114179
ocw/profiling/perf.script
Normal file
File diff suppressed because it is too large
Load diff
24
ocw/profiling/time_the_clock.cc
Normal file
24
ocw/profiling/time_the_clock.cc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <print>
|
||||
|
||||
using namespace std;
|
||||
|
||||
constexpr static size_t TRIALS = 100000;
|
||||
|
||||
|
||||
int main() {
|
||||
chrono::microseconds diffs_ms{0};
|
||||
for (size_t loop_var = 1; loop_var <= TRIALS; ++loop_var) {
|
||||
auto t1 = chrono::high_resolution_clock::now();
|
||||
auto t2 = chrono::high_resolution_clock::now();
|
||||
diffs_ms += chrono::duration_cast<chrono::microseconds>(t2 - t1);
|
||||
}
|
||||
|
||||
print("measuring the clock in c++ 23 {} trials had an average time duration "
|
||||
"of: {} microseconds, or {} milliseconds",
|
||||
TRIALS, diffs_ms / TRIALS,
|
||||
chrono::duration_cast<chrono::milliseconds>(diffs_ms / TRIALS));
|
||||
|
||||
return 0;
|
||||
}
|
||||
89225
ocw/profiling/time_the_clock.s
Normal file
89225
ocw/profiling/time_the_clock.s
Normal file
File diff suppressed because it is too large
Load diff
5
perf-cpp/analysis-and-tuning.md
Normal file
5
perf-cpp/analysis-and-tuning.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# performance
|
||||
|
||||
## [profiling - algorithmica](https://en.algorithmica.org/hpc/profiling/)
|
||||
|
||||
## [performance analysis and tuning](https://en.algorithmica.org/hpc/profiling/)
|
||||
816
perf-cpp/cpp.md
Normal file
816
perf-cpp/cpp.md
Normal file
|
|
@ -0,0 +1,816 @@
|
|||
# CPP
|
||||
|
||||
## [learncpp](https://www.learncpp.com/)
|
||||
|
||||
- compilation process: preprocess -> compilation -> assembly -> linking
|
||||
- lexing for grammar validity -> ast type checking
|
||||
- files are compiled top to bottom, & individually (must include libraries
|
||||
multiple times)
|
||||
|
||||
- e.g. below, type checker evaluates, sees f returns `void` -> pairs with
|
||||
`std::cout` operator `<<` -> this is invalid -> *compile-time* caught
|
||||
```cpp
|
||||
#include <iostream>
|
||||
|
||||
void printA()
|
||||
{
|
||||
std::cout << "A\n";
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << printA() << '\n';
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
- initialization
|
||||
- why list initialization -> narrowing conversions disallowed
|
||||
|
||||
- [operator precendece](https://en.cppreference.com/w/cpp/language/operator_precedence.html)
|
||||
|
||||
- nested functions disallowed
|
||||
- many features of cpp don't nec. have rhyme or reason; it is a language
|
||||
[with history](https://www.reddit.com/r/cpp/comments/199ho2b/why_doesnt_standard_c_support_nested_functions/) for good or bad
|
||||
|
||||
- cpp compiles sequentially (i.e. top to bottom)
|
||||
- <u>One Definition Rule</u>: per file, per scope, one definition only; per
|
||||
program too; types/templates/inline functions can have other definitions
|
||||
- ? why are header files usually omitted in c++ compilation processes?
|
||||
- ? why does the cpp - include header structure in projects work, espec. wrt
|
||||
ODR?
|
||||
- NOTE: *compiling* does not need impls (just needs ) -> *linking* does
|
||||
- NOTE: research about linking later, but just know linking has a symbol
|
||||
table to map symbols to literaly code locations
|
||||
|
||||
### namespaces
|
||||
|
||||
- *simple* -> wrap simple name
|
||||
- "name mangling" includes the namespace prefix in compilation -> easy to
|
||||
identify
|
||||
|
||||
|
||||
## preprocessing
|
||||
|
||||
- when is it done?
|
||||
- for each cpp file, copy-paste in the includes & compile into translation
|
||||
units separately
|
||||
- what's the output of pre-processsed files called?
|
||||
|
||||
- Lesson: use macros sparingly besides eliminating code compilation (i.e. in
|
||||
libraries) and compilation-specific processes
|
||||
|
||||
- `""` vs. `<>` in includes: look locally relative to the path, then
|
||||
system/*only* look in the system
|
||||
|
||||
- Why not use relative includes (~~configure the compile-time include path instead~~)
|
||||
- Why even use header guards? What's the common pattern that necessitates them?
|
||||
- 1 file including 2 files that each include another file -> duplicate
|
||||
definition
|
||||
- ? why do header guards resolve this problem? ~~because each translation unit
|
||||
is treated separately by the pre-processor. files are compiled separately but
|
||||
a file compiling joint ones doesn't duplicate includes via the guard.~~
|
||||
- long story short, every file must have one of all each included file ->
|
||||
prevent ODR violations
|
||||
- ? why don't define methods in header files? ~~multiple cpp can include
|
||||
headers, leading to ODR violations~~
|
||||
- only have ONE function implementation in source files -> compilation
|
||||
resolves with declarations & implementations linked easily
|
||||
|
||||
## type conversion
|
||||
|
||||
- <u>implicit conversions</u> convert types when acceptable
|
||||
- pre-defined set of compiler rules
|
||||
- why is using const in value parameters useless?
|
||||
|
||||
## optimization
|
||||
|
||||
- what's the official rule for how c++ compilres can change code? ~~when the
|
||||
"observable behavior" is identical - i.e. cahnge anything if output is the
|
||||
same~~
|
||||
- methods:
|
||||
1. constant folding
|
||||
2. dead code elimination
|
||||
|
||||
## constants
|
||||
|
||||
- "by default, expressions are evaluated at \_"?
|
||||
- it's up to the *compiler* as to whether *anything* is evaluated at compile
|
||||
time
|
||||
- <u>constexpr</u>: declares value as a compile-time available constant - all args *must* be
|
||||
evaluatable at compile time (i.e. be constant expressoions) - BUT... this is optional!
|
||||
- values must be KNOWN -> not nec. imply compilation
|
||||
- "constexprness" implies constness
|
||||
- `std::string_view` is a fragile container
|
||||
|
||||
## [order of operations](https://en.cppreference.com/w/cpp/language/operator_precedence.html)
|
||||
|
||||
- why is this bad? ~~according to c++ spec, order of function evaluation is not
|
||||
specified - generally speaking, args should not have side effects~~
|
||||
|
||||
```cpp
|
||||
auto x = 5;
|
||||
|
||||
f(x++, ++x);
|
||||
```
|
||||
|
||||
- what does this return, and why? what does it teach us abou tthe ternary
|
||||
operations?
|
||||
- ~~due to operator precedence, 0 is first printed; then the returned
|
||||
std::cout& is implicitly cast to a boolean and the result of the terary is
|
||||
discarded~~
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
int x { 2 };
|
||||
std::cout << (x < 0) ? "negative" : "non-negative";
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
- NOTE: `<=>`, bitwise operators, and more have lower priority than `<<`
|
||||
|
||||
- I allocate N bits into a `std::bitset`. How many bits of memory are allocated
|
||||
and why?
|
||||
~~ceil(N / bits per machine word) * number bits per word (rounded up) -
|
||||
bitsets are fixed size, contiguous arrays of machine words for convenient
|
||||
accessing~~
|
||||
|
||||
## scopes
|
||||
|
||||
- explain lifetime management in c++
|
||||
- an identifier can have multiple scopes - T/F
|
||||
- how does the compiler search for scope resolution?
|
||||
||it works from the inside out resolving symbols||
|
||||
|
||||
- how can i refer to x in the outer example? ||use the scope resolution
|
||||
operator: `f::x`||
|
||||
|
||||
```cpp
|
||||
void f() {
|
||||
int x;
|
||||
{
|
||||
int x;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## linkage
|
||||
|
||||
- what is linkage? ||linkage determines visibility & to the linker||
|
||||
- can the linker see variables with internal linkage? ||intuitively no - they'll
|
||||
never need to be linked because they are not accessible from other translation
|
||||
units||
|
||||
- functions default to {external, internal} linkage ||external||
|
||||
- non-constant global variables? ||external||
|
||||
- how to declare constant global to have external linkage? ||add the [storage class specifier](https://en.cppreference.com/w/cpp/language/storage_duration.html) `extern`||
|
||||
- why can `extern` variables not be `constexpr`? ||value must be evaluatable at
|
||||
compile-time - if another file sets the value, the compiler isn't
|
||||
sophisticated to know (it compiles files in isolation)||
|
||||
|
||||
- What’s the difference between a variable’s scope, duration, and linkage? What kind of scope, duration, and linkage do global variables have?
|
||||
- ||scope -> where defined/accessible in the code; duration ->
|
||||
creation/destruction bounds (can be different in more complex areas? give an
|
||||
example), linkage -> visibility beyond translation unit||
|
||||
|
||||
## [inlining](https://en.cppreference.com/w/cpp/language/inline.html)
|
||||
|
||||
- centrally concerned with *linkage*
|
||||
- external linkage can cause ODR violations -> resolve with `inline`
|
||||
- when to not inline? ||size of the inlined function outweighs the overhead of
|
||||
inlining itself||
|
||||
- why can you not force the compiler to inline?
|
||||
- why is `inline` not to be used for inlining?
|
||||
- ||inlining is a per-function call concept, but the keyword makes it apply to
|
||||
all scenarios||
|
||||
|
||||
- `inline` is about removing ODR violations across *multiple* different files.
|
||||
- how does this vary from header guards?
|
||||
- when should you use inline?
|
||||
- `inline` really means ||multiple definitions are permitted|| instead of inline the call
|
||||
|
||||
- NOTE: this still honestly doesn't make much sense to me
|
||||
- Review linkage, compilation process, ODR, and inlining
|
||||
|
||||
- We usually just want ONE definition - so we keep implementations in ||source||
|
||||
files so that on compilation the ||linker|| can easily find the function
|
||||
definition (which it can do because it has ||external|| linkage by default)
|
||||
- When defining something like a function ||implementation|| in a ||header||
|
||||
file, this pattern is broken. why? ||multiple function impls with external
|
||||
linkage will exist||
|
||||
- inline then allows separate ||translation units||, indeed compiled separately, to resolve the symbol fine
|
||||
|
||||
- marking something as `inline` does/does not ||does not|| change the storage class specifier. the linker ||merges|| multiple definitions of variables marked inline
|
||||
- `inline` variables have ||external|| linkage by default - why? ||duh - so
|
||||
linker can resolve between TUs||
|
||||
|
||||
## static
|
||||
|
||||
- has so many different meaning
|
||||
|
||||
- What does `static` refer to inside/outside a function? ||static *storage
|
||||
duration*/*internal linkage*||
|
||||
variable to start/end at the time of the program
|
||||
|
||||
- how do I give a function internal linkage? ||mark as `static`||
|
||||
|
||||
## scoping and brackets
|
||||
|
||||
- which does the else bind to? ||closest/nearest unmatched if -> the if (y)
|
||||
block||
|
||||
|
||||
- explain loops without brackets in terms of grammar
|
||||
- ||basically, grammatically an if/for/etc. cover ones statement. an enclosing body with brackets is a <u>compound statement</u>. no
|
||||
brackets -> the first statement in the tree is grabbed||
|
||||
- why does this then work with chained elses and else ifs? note that else ifs are
|
||||
parsed as ifs inside of else blocks
|
||||
```cpp
|
||||
if (x)
|
||||
if (y)
|
||||
a();
|
||||
else
|
||||
b();
|
||||
```
|
||||
|
||||
|
||||
## switch statements
|
||||
|
||||
- compilers are smart, and may do the following for switch statements:
|
||||
|
||||
1. direct access jump tables
|
||||
2. binary search when too big
|
||||
3. re-indexing (i.e. values start at large n)
|
||||
|
||||
## loops
|
||||
|
||||
- mostly get compiled to the same thing
|
||||
|
||||
## function overloading implicit type conversion
|
||||
|
||||
- why is it needed? ||internal representation of different types differs||
|
||||
|
||||
- `using` keyword does a variety of things
|
||||
- what happens when multiple function candidates are available?
|
||||
- overload resolution -> choose ONE best candidate (if multiple, error)
|
||||
|
||||
- What's the output (and why?)
|
||||
- ||double because there's a promotion to float||
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
|
||||
void f(int) { std::cout << "f(int)\n"; }
|
||||
void f(double) { std::cout << "f(double)\n"; }
|
||||
|
||||
int main() {
|
||||
f(3.14f);
|
||||
int x = 3.14f; // also conversion
|
||||
}
|
||||
```
|
||||
|
||||
- in <u>function overloading</u>, acc. to C++ spec resolve function choices:
|
||||
1. exact match
|
||||
2. promote *arguments*
|
||||
3. user defined conversions
|
||||
4. ellipses
|
||||
5. give up
|
||||
|
||||
- ? what's the difference between compiler vs. linker resolving functions?
|
||||
- ~~compiler resolves function calls via OVERLOADING - indeed, the compiler
|
||||
must know all function signatures. subsequently, each
|
||||
function is then mapped to in the linker phase.~~
|
||||
|
||||
- What's the output (and why?)
|
||||
- ||compilation error -> CONVERSION of the same rank||
|
||||
```cpp
|
||||
void f(long) { std::cout << "f(long)\n"; }
|
||||
void f(unsigned long) { std::cout << "f(unsigned long)\n"; }
|
||||
|
||||
int main() {
|
||||
f(3.14f);
|
||||
return 0;
|
||||
```
|
||||
|
||||
- NOTE: conversion is complex
|
||||
- promotion -> special, correct promotion -> prioritized (prioritized first)
|
||||
- only includes small types, not like `long`
|
||||
- conversion -> otherwise
|
||||
- compilers do the five following conversions, and in which order?
|
||||
|
||||
||
|
||||
1. exact (including qualifiers such as cv, array-to-pointer, etc.)
|
||||
2. promotion
|
||||
3. conversion (and any path, promotion + conversion, etc)
|
||||
4. user-defined
|
||||
5. variadic (i.e. smash into an ellipses)
|
||||
||
|
||||
|
||||
- valid or not, and why?
|
||||
- ||invalid - return types not used in function overloading for a)
|
||||
compatibility reasons with C and b) trouble distinguishing between desired
|
||||
return type (how can you indicate which function you want when there isn't
|
||||
always a straightforward way to do such?). e.g. `auto X = x(); f(());`,
|
||||
etc. Generally, it's convenient to just look at call context & know return
|
||||
value after deducing the right function call.||
|
||||
- || in other words, a function's type signature is everything but the
|
||||
return type.||
|
||||
|
||||
```cpp
|
||||
int x();
|
||||
double x();
|
||||
```
|
||||
|
||||
- exactly what does this do?
|
||||
- || *halt* compilation if the function is called. code is still compiled,
|
||||
but `delete` forbids the call||
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
void printInt(T x) = delete;
|
||||
```
|
||||
|
||||
### default arguments
|
||||
|
||||
- are default args part of function signature ||no||
|
||||
- how are default args instantiated
|
||||
- what's the output of the following code, and why?
|
||||
- ||behaves as expected. compile substitutes in the default args at the call
|
||||
site, so the calls become `g(int x=foo())`||.
|
||||
|
||||
```cpp
|
||||
int foo() {
|
||||
static int s = 0;
|
||||
return ++s;
|
||||
}
|
||||
|
||||
void g(int x = foo()) {
|
||||
// ...
|
||||
}
|
||||
|
||||
int main() {
|
||||
g();
|
||||
g();
|
||||
}
|
||||
```
|
||||
|
||||
- does this compile? y or no? ||no - default args not considered in function
|
||||
signature in overload resolution process - call is ambiguous||
|
||||
|
||||
```cpp
|
||||
void print()
|
||||
{
|
||||
std::cout << "void\n";
|
||||
}
|
||||
|
||||
void print(int x=0)
|
||||
{
|
||||
std::cout << "int " << x << '\n';
|
||||
}
|
||||
|
||||
int main() { print(); }
|
||||
```
|
||||
|
||||
### templates
|
||||
|
||||
- how do templates work in the compiler?
|
||||
- ||an internal symbol table - one template blueprint itself does not generate
|
||||
machine code (instantiations do)||
|
||||
- say i have two functions - one regular, one templated. how can i prefer the
|
||||
templated function? do i even need to?
|
||||
- ||if you want to target the templated function, which is more generic and
|
||||
thus not prioritized by the compiler, wrap it in `<>`||
|
||||
|
||||
```cpp
|
||||
template<typename T>
|
||||
void print();
|
||||
void f(bool);
|
||||
|
||||
// ??
|
||||
f(true);
|
||||
f<(bool)>(); // NOTE: bool is optional
|
||||
```
|
||||
|
||||
- what's the output? || 1) 2) 1) - consider the instantiated code per the
|
||||
compiler - one static local variable per template specialization ||
|
||||
|
||||
- what about here? ||second function called. template can create an exact match
|
||||
which is preferred over promotion||.
|
||||
|
||||
```cpp
|
||||
void f(int x) { ... }
|
||||
void f(auto x) { ... }
|
||||
|
||||
// ??
|
||||
f(short{3});
|
||||
```
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
|
||||
template <typename T>
|
||||
void printIDAndValue(T value)
|
||||
{
|
||||
static int id{ 0 };
|
||||
std::cout << ++id << ") " << value << '\n';
|
||||
}
|
||||
|
||||
int main() {
|
||||
printIDAndValue(12);
|
||||
printIDAndValue(13);
|
||||
|
||||
printIDAndValue(14.5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
- ? concepts and generics, best ways to link together?
|
||||
- what's partial ordering of templates?
|
||||
- ? what's the *entire* way compilers resolve function calls?
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
auto add(T x, T y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
auto add(T x, U y) {
|
||||
return x + y;
|
||||
}
|
||||
```
|
||||
|
||||
- what's wrong with this? how do i fix it?
|
||||
- ||add specializations or an else clause with `constexpr`. picture the compiler - it needs to
|
||||
instantiate all proper templates on compilation. in some sense, the
|
||||
compiler is literally executing the code.
|
||||
```cpp
|
||||
template <int N>
|
||||
constexpr long long fibonacci() {
|
||||
static_assert(N >= 0);
|
||||
if (N <= 1) { return N; }
|
||||
return fibonacci<N - 1>() + fibonacci<N - 2>();
|
||||
}
|
||||
```
|
||||
|
||||
- NOTE: this is a sharp edge. skip it, honestly
|
||||
|
||||
- functions instantiated from templates are implicitly ||`inline`||. Why? ||must
|
||||
be so that different, identical specializations in files do not violate the
|
||||
ODR.||
|
||||
- the odr is a compile and/xor link time concept ||and||
|
||||
|
||||
## pointers and references
|
||||
|
||||
- how do references work under the hood?
|
||||
- alias to variable only known to compiler - implicitly dereffed
|
||||
- NEVER reassignable
|
||||
- output?
|
||||
|
||||
```cpp
|
||||
int x = 5;
|
||||
int y = 4;
|
||||
int& z = x;
|
||||
z = y; // x holds value of 4 -> can never reassign alias
|
||||
(*x) = y;
|
||||
```
|
||||
|
||||
- what's the output?
|
||||
- ||A 5 A; reference calls always implicitly resolve to (\*ref) by the compiler - "syntactic sugar". In other words, it's impossible to actually inspect the reference pointer itself.||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
|
||||
void printAddresses(int val, int& ref)
|
||||
{
|
||||
std::cout << val << '\n';
|
||||
std::cout << &ref << '\n';
|
||||
}
|
||||
|
||||
int main() {
|
||||
int x { 5 };
|
||||
std::cout << "The address of x is: " << &x << '\n';
|
||||
printAddresses(x, x);
|
||||
}
|
||||
```
|
||||
|
||||
- will this compile? ||it has a memory leak - that doesn't mean it won't compile
|
||||
(it is valid c++, sigh)||
|
||||
|
||||
```cpp
|
||||
const std::string& getProgramName() {
|
||||
const std::string programName { "Calculator" };
|
||||
|
||||
return programName;
|
||||
}
|
||||
// automatic storage duration of `programName` - destroyed
|
||||
```
|
||||
|
||||
- auto and what not - name the types, assuming `getRef()` returns `T`:
|
||||
|
||||
- `auto x = getRef()` -> ||T (reference discarded)||
|
||||
- `auto& x = getRef()` -> ||T&. This is known as "reapplying the reference and
|
||||
can also be done with `const`"||
|
||||
- `auto x = getConstRef()` -> ||T (const discarded)||
|
||||
- `auto x = getPointer()` -> ||T\* (pointer kept - notion of
|
||||
converting/dropping is incorrect, its sort of its own type)||
|
||||
- `auto* x = getPointer()` -> ||T\* (pointer kept)||
|
||||
|
||||
- low-level vs. top level const?
|
||||
- ||A top-level const applies to the object itself (e.g. const int x or int* const ptr)||
|
||||
- ||A low-level const applies to the object accessed through a reference or pointer (e.g. const int& ref, const int* ptr).||
|
||||
|
||||
## enums
|
||||
|
||||
- by default, `enum`s are ||unscoped|| which means they ||leak into the
|
||||
scope they're defined in||. For this reason default
|
||||
to `enum`s keyed with the word ||`class`||, or "||scoped||" enums. We just
|
||||
need to access them with the ||scope resolution|| operator.
|
||||
not leak.
|
||||
|
||||
|
||||
- ||bad, good - unscoped do not implicitly convert||
|
||||
```cpp
|
||||
enum class X { A };
|
||||
enum Y { A };
|
||||
|
||||
X::A == 0;
|
||||
Y::A == 0;
|
||||
```
|
||||
|
||||
- ||NO but yes if unscoped, NEVER||
|
||||
|
||||
```cpp
|
||||
void f() {
|
||||
// NOTE: even enum does not work here (both scoped inside)
|
||||
enum class A { B };
|
||||
|
||||
// does this compile?
|
||||
A::B;
|
||||
}
|
||||
|
||||
// this?
|
||||
A::B;
|
||||
```
|
||||
|
||||
## structs/classes
|
||||
|
||||
- `static` in structs means one variable for the lifetime
|
||||
- where do static class/struct vars live in memory? ||not in struct, prob in
|
||||
the data segment||
|
||||
|
||||
- any function implementation in a `struct` is implicitly marked ||`inline`|| - why?
|
||||
- why declare a static struct variable `inline`? ||so you can declare it once inside the struct (C++17+)||
|
||||
- NOTE: only ever makes sense to declare variables as `inline` when done
|
||||
static inside a class - shared, program-living variables. i.e. marking
|
||||
object-local variable as `inline` is nonsensical - it's "already `inline`"
|
||||
- static-static interaction only
|
||||
- no `this` pointer -> must access via `ClassName::{}`
|
||||
|
||||
- structs are like/not like member functions in the sense that they can/cannot
|
||||
be declared in any order
|
||||
- specification default vs. class
|
||||
|
||||
- valid? & why? ||yes, const is part of signature. useful for things like
|
||||
operator overload, const & non-const versions||
|
||||
|
||||
- what is `const` mem func -> ||cannot modift class internals||
|
||||
- When can you not call non-`const` member functions? ||from const objects ->
|
||||
may mutate state||
|
||||
- pretty straightforward, which is why you can/cannot call non-const MF from
|
||||
non-const objects (||can||)
|
||||
|
||||
```cpp
|
||||
// ??
|
||||
class A{
|
||||
void f() const;
|
||||
void f();
|
||||
}
|
||||
```
|
||||
|
||||
### access specification
|
||||
|
||||
- private/public/protected
|
||||
- given your definitions, why is the code below valid or invalid? ||valid -
|
||||
`private` -> *any* object & friend of class (inheritor or not) can touch its members||
|
||||
|
||||
```cpp
|
||||
class A{
|
||||
int x;
|
||||
void f(A a) {
|
||||
// ??
|
||||
a.x;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- structs/class differ in that struct/class AS is ||public/private||
|
||||
- access specification is a ||compile||-time construct and occurs before/after
|
||||
(||after||) method resolution in the compilation process
|
||||
|
||||
- good or bad (||bad - best match, then resolve specification||)
|
||||
|
||||
```cpp
|
||||
struct Gate {
|
||||
private:
|
||||
void calibrate(int);
|
||||
public:
|
||||
void calibrate(double);
|
||||
};
|
||||
|
||||
void run(Gate& g) {
|
||||
// ??
|
||||
g.calibrate(7);
|
||||
}
|
||||
```
|
||||
|
||||
### struct/class memory management
|
||||
|
||||
- struct members can/cannot be reordered and can/cannot have padding inserted
|
||||
- in terms of the following memory model:
|
||||
- <u>code</u>: code itself
|
||||
- <u>data</u>: globals, statics, string literals
|
||||
- <u>stack</u>: stack frames, local vars, etc
|
||||
- <u>heap</u>: heap-allocated things
|
||||
|
||||
```cpp
|
||||
struct Widget {
|
||||
int id; // per-object data
|
||||
std::string name; // per-object data
|
||||
static int total_count; // one global variable
|
||||
static constexpr double pi = 3.14159; // goes in rodata
|
||||
void ping(); // function
|
||||
virtual void vfunc(); // function pointer in vtable
|
||||
};
|
||||
```
|
||||
|
||||
- ... member functions are in (||code, so you don't have multiple
|
||||
per-instantiation||), regular variables in ||stack||, static in ||data||,
|
||||
virtual stuff ||also somewhere in code - like having one virtual pointer||
|
||||
- WHY does this memory management make sense?
|
||||
|
||||
### construction
|
||||
|
||||
- do constructors create objects || no they initialize ||
|
||||
- why not `const`?
|
||||
- follow normal conversion rules
|
||||
|
||||
- ouptput: ||member initializer list always takes precedence||
|
||||
- NOTE: member IL != IL
|
||||
```cpp
|
||||
class A {
|
||||
public:
|
||||
A(int x) : x(x) {}
|
||||
int x{2};
|
||||
};
|
||||
|
||||
// ??
|
||||
A{}.x;
|
||||
```
|
||||
|
||||
- members are initialized in order of declaration in initialize list (why? no
|
||||
idea)
|
||||
|
||||
```cpp
|
||||
class Foo {
|
||||
private:
|
||||
int m_x{};
|
||||
int m_y{};
|
||||
|
||||
public:
|
||||
Foo(int x, int y)
|
||||
// m_x is ALWAYS garbage
|
||||
: m_y { std::max(x, y) }, m_x { m_y }
|
||||
{}
|
||||
};
|
||||
```
|
||||
|
||||
- delegating and chaining constructors can be usefukl for off-loading logic
|
||||
- CALLING CTORS of *other* classes and *our own* in CTORS IS PERFECTLY FINE!
|
||||
|
||||
- more rules:
|
||||
- T/F: if I have constructors but no default, c++ creates an implicit one for
|
||||
me ||F||
|
||||
- T/F: if I have no default constructors, c++ makes ||T||
|
||||
- Say you want to disable copying/default construction. I claim you can just
|
||||
make the methods private. Does this work? ||Yes - but members of the
|
||||
class/inheritors/etc. can still call it -> defeating the purpose - just use
|
||||
`= delete`||
|
||||
|
||||
- anything wrong? ||incompete type - infinite recursion||
|
||||
```cpp
|
||||
class A {
|
||||
A(A a) {}
|
||||
};
|
||||
```
|
||||
|
||||
- why should copy constructors not have side effects? ||if copy elision occurs,
|
||||
the side effects will not. copy elision is immune to the ["as-if" rule](https://en.cppreference.com/w/cpp/language/as_if.html)||
|
||||
|
||||
- what is [(N)RVO](https://en.cppreference.com/w/cpp/language/copy_elision.html) and which c++ concept is behind it? ||copy elision & copy
|
||||
constructors||
|
||||
|
||||
- does this compile? || no - only one user-defined constructor can be applied
|
||||
(trying to go from `std::string` -> `std::string_view` -> `std::string`)||
|
||||
- [user-defined types](https://www.learncpp.com/cpp-tutorial/introduction-to-program-defined-user-defined-types/) are also for STL
|
||||
|
||||
```cpp
|
||||
class Employee {
|
||||
private:
|
||||
std::string m_name{};
|
||||
public:
|
||||
Employee(std::string_view name)
|
||||
: m_name{ name } { }
|
||||
const std::string& getName() const { return m_name; }
|
||||
};
|
||||
|
||||
void printEmployee(Employee e) {
|
||||
std::cout << e.getName();
|
||||
}
|
||||
|
||||
int main() {
|
||||
printEmployee("Joe");
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
- ? know each constructor syntax - which does this call?
|
||||
|
||||
```cpp
|
||||
Y y = Y(5); // cpp isn't stupid -> calls Y::Y(const& y), the copy constructor - not default + assigned
|
||||
Y y = Y(); // default & copy, but copy elided (c++17+) -> just default
|
||||
Y o;
|
||||
Y y(o); // textbook copy
|
||||
Y y = Y(Y()); // one defeault - BOTH elided
|
||||
```
|
||||
|
||||
- `explicit` - only accept exact value type (no implicit conversions)
|
||||
- why use `explicit` -> implicit conversions
|
||||
|
||||
```cpp
|
||||
class A {
|
||||
public:
|
||||
int a;
|
||||
A(int a) : a(a) {}
|
||||
void meth(A a) {}
|
||||
};
|
||||
|
||||
A a = A(true); // this is valid when A::A(int) is not explicit
|
||||
a.meth(A(false)); // so i can do this too
|
||||
```
|
||||
- called by `static_cast` just fine, too
|
||||
|
||||
### this pointer
|
||||
|
||||
- "Every non-static member function has an implicit parameter called this."
|
||||
- how does `this` and implicit `this` work?
|
||||
- inserted implicitly
|
||||
- what's the type of `this` in non-const/const member functions? ||
|
||||
`TheClass\* const` (const pointer - you can still change underlying object)/const TheClass\* const (you cannot change underlying object, so pointer to
|
||||
const)||
|
||||
- NOTE: references didn't exist when c++ was made, so even tho it should be a
|
||||
reference it's not
|
||||
|
||||
```cpp
|
||||
class MethodChain {
|
||||
MethodChain& mc() {
|
||||
// deref -> automatically aliased in return type
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
- ODR again - why does defining classes in headers "just work?" - because class
|
||||
member functions defined ||& implemented fully in the header|| are ||implicitly marked as `inline`||
|
||||
- I could just define an entire class in a header - why not? ||organization +
|
||||
increased compile time -> recompile header + all deps on change, rather than
|
||||
just cpp source file)
|
||||
- why do class variables and other things not need to be marked `inline`
|
||||
||***member functions have external linkage by default***. other stuff does
|
||||
not and is a per-object local storage - is has NO linkage||
|
||||
|
||||
### more `static`
|
||||
|
||||
- static vars are/are not associated with the lifetime of a class ||are not -
|
||||
start & end of program - can access w/ 0 instances||
|
||||
|
||||
```cpp
|
||||
class A {
|
||||
static x;
|
||||
};
|
||||
|
||||
A::x; // valid
|
||||
```
|
||||
|
||||
- say you want to shield static class vars - how? ||make private - access
|
||||
specifiers trump||
|
||||
|
||||
- static *member functions* have/don't have a `this` pointer ||don't||
|
||||
- therefore, they can/cannot call non-static functions - why? ||cannot -
|
||||
non-static member functions need an implicit this object point to operate
|
||||
on, and statics do not have this||
|
||||
|
||||
# [beginning c++ 23: beginner to pro](https://www.amazon.com/Beginning-C-23-Beginner-Pro/dp/1484293428)
|
||||
3
perf-cpp/readme.md
Normal file
3
perf-cpp/readme.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# performance
|
||||
|
||||
c++ and performance notes and resources
|
||||
9
perf-cpp/scripts/.clang-format
Normal file
9
perf-cpp/scripts/.clang-format
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
BasedOnStyle: Google
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
35
perf-cpp/scripts/.clangd
Normal file
35
perf-cpp/scripts/.clangd
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
CompileFlags:
|
||||
Add:
|
||||
-O2
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wpedantic
|
||||
-Wshadow
|
||||
-Wformat=2
|
||||
-Wfloat-equal
|
||||
-Wlogical-op
|
||||
-Wshift-overflow=2
|
||||
-Wnon-virtual-dtor
|
||||
-Wold-style-cast
|
||||
-Wcast-qual
|
||||
-Wuseless-cast
|
||||
-Wno-sign-promotion
|
||||
-Wcast-align
|
||||
-Wunused
|
||||
-Woverloaded-virtual
|
||||
-Wconversion
|
||||
-Wsign-conversion
|
||||
-Wmisleading-indentation
|
||||
-Wduplicated-cond
|
||||
-Wduplicated-branches
|
||||
-Wlogical-op
|
||||
-Wnull-dereference
|
||||
-Wformat=2
|
||||
-Wformat-overflow
|
||||
-Wformat-truncation
|
||||
-Wdouble-promotion
|
||||
-Wundef
|
||||
-DLOCAL
|
||||
-Wno-unknown-pragmas
|
||||
-e -std=c++23
|
||||
-e -std=c++23
|
||||
9
perf-cpp/scripts/a.cc
Normal file
9
perf-cpp/scripts/a.cc
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#include <iostream>
|
||||
|
||||
#include "a.hh"
|
||||
|
||||
int main() {
|
||||
std::cout << add();
|
||||
|
||||
return 0;
|
||||
}
|
||||
3
perf-cpp/scripts/a.hh
Normal file
3
perf-cpp/scripts/a.hh
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
int add() {return 1;}
|
||||
29
perf-cpp/scripts/bitset.cc
Normal file
29
perf-cpp/scripts/bitset.cc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include <iostream>
|
||||
#include <bitset>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <bitset>
|
||||
#include <iostream>
|
||||
|
||||
std::bitset<4> rotl(std::bitset<4> bits) {
|
||||
return (bits << 1) | (bits >> 3);
|
||||
}
|
||||
|
||||
void william() {
|
||||
int will;
|
||||
|
||||
if (69)
|
||||
int will;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::bitset<4> bits1{ 0b0001 };
|
||||
std::cout << rotl(bits1) << '\n';
|
||||
|
||||
std::bitset<4> bits2{ 0b1001 };
|
||||
std::cout << rotl(bits2) << '\n';
|
||||
|
||||
return 0;
|
||||
}
|
||||
48
perf-cpp/scripts/ch11.cc
Normal file
48
perf-cpp/scripts/ch11.cc
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
Write a constexpr function template with a non-type template parameter that
|
||||
returns the factorial of the template argument. The following program should
|
||||
fail to compile when it reaches factorial<-3>().
|
||||
|
||||
*/
|
||||
|
||||
template <int N>
|
||||
constexpr long long fibonacci() {
|
||||
static_assert(N >= 0);
|
||||
if constexpr (N <= 1) {
|
||||
return N;
|
||||
} else {
|
||||
return fibonacci<N - 1>() + fibonacci<N - 2>();
|
||||
}
|
||||
}
|
||||
|
||||
// int main() {
|
||||
// static_assert(fibonacci<1LL>() == 1);
|
||||
// // static_assert(factorial<3>() == 6);
|
||||
// // static_assert(factorial<5>() == 120);
|
||||
//
|
||||
// // fibonacci<-3>();
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <typename T>
|
||||
T add(T x, T y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T mult(T t, int N) {
|
||||
return t * N;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << add(2, 3) << '\n';
|
||||
std::cout << add(1.2, 3.4) << '\n';
|
||||
|
||||
std::cout << mult(2, 3) << '\n';
|
||||
std::cout << mult(1.2, 3) << '\n';
|
||||
|
||||
return 0;
|
||||
}
|
||||
50
perf-cpp/scripts/ch15.cc
Normal file
50
perf-cpp/scripts/ch15.cc
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Question #1
|
||||
|
||||
Write a class template named Triad that has 3 private data members with
|
||||
independent type template parameters. The class should have a constructor,
|
||||
access functions, and a print() member function that is defined outside the
|
||||
class.
|
||||
|
||||
The following program should compile and run:
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
class Triad {
|
||||
private:
|
||||
T1 t1;
|
||||
T2 t2;
|
||||
T3 t3;
|
||||
|
||||
public:
|
||||
explicit Triad() {
|
||||
}
|
||||
explicit Triad(T1 t1, T2 t2, T3 t3) : t1(t1), t2(t2), t3(t3) {
|
||||
}
|
||||
T1 first() { return t1; }
|
||||
void print() ;
|
||||
~Triad() {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
void Triad<T1, T2, T3>::print() {
|
||||
std::cout << '[' << t1 << ", " << t2 << ", " << t3 << "]\n";
|
||||
}
|
||||
|
||||
int main() {
|
||||
Triad t1{1, 2, 3};
|
||||
t1.print();
|
||||
std::cout << '\n';
|
||||
std::cout << t1.first() << '\n';
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
const Triad t2{1, 2.3, "Hello"s};
|
||||
t2.print();
|
||||
std::cout << '\n';
|
||||
|
||||
return 0;
|
||||
}
|
||||
38
perf-cpp/scripts/ch4.cc
Normal file
38
perf-cpp/scripts/ch4.cc
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Write the following program: The user is asked to enter 2 floating point numbers (use doubles). The user is then asked to enter one of the following mathematical symbols: +, -, *, or /. The program computes the answer on the two numbers the user entered and prints the results. If the user enters an invalid symbol, the program should print nothing.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
double x, y;
|
||||
std::cout << "enter x: "<<'\n';
|
||||
std::cin >> x;
|
||||
std::cout << "enter x: "<<'\n';
|
||||
std::cin >> y;
|
||||
std::cout << "enter symbol " << '\n';;
|
||||
char symbol;
|
||||
std::cin >> symbol;
|
||||
|
||||
double ans;
|
||||
switch (symbol) {
|
||||
case '+':
|
||||
ans = x + y;
|
||||
break;
|
||||
case '-':
|
||||
ans = x - y;
|
||||
break;
|
||||
case '*':
|
||||
ans = x * y;
|
||||
break;
|
||||
case '/':
|
||||
ans = x / y;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::cout << "answer: " << ans << '\n';
|
||||
return 0;
|
||||
}
|
||||
51
perf-cpp/scripts/ch5.cc
Normal file
51
perf-cpp/scripts/ch5.cc
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <concepts>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
template <std::integral T>
|
||||
T binexp(T base, T exponent, T mod) {
|
||||
assert(mod > 0 && exponent > 0);
|
||||
|
||||
T product{1};
|
||||
T multiplier{base % mod};
|
||||
|
||||
while (exponent > 0) {
|
||||
if ((exponent & 1) != 0) {
|
||||
product = (multiplier * product) % mod;
|
||||
}
|
||||
multiplier = (multiplier * multiplier) % mod;
|
||||
exponent >>= 1;
|
||||
}
|
||||
|
||||
return product;
|
||||
}
|
||||
|
||||
int main() {
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
std::string S{"hello"};
|
||||
std::string_view s{S};
|
||||
S.~basic_string();
|
||||
|
||||
// double ub - free + string view dereferencing destroyed object
|
||||
// std::cout << s << '\n' ;
|
||||
|
||||
std::cout << -5 / 2 << '\n';
|
||||
|
||||
using namespace std;
|
||||
long double ld = pow((long double)10, 18); // computed in floating point
|
||||
long long ll = (long long)ld; // cast back to integer
|
||||
|
||||
cout << fixed << setprecision(0);
|
||||
cout << "pow(10,18) as long double: " << ld << "\n";
|
||||
cout << "cast to long long: " << ll << "\n";
|
||||
cout << "Should be exactly: " << 1000000000000000000LL << "\n";
|
||||
|
||||
std::cout << binexp(2, 5, 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
20
perf-cpp/scripts/ch6.cc
Normal file
20
perf-cpp/scripts/ch6.cc
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#include <iostream>
|
||||
#include <cstdint>
|
||||
|
||||
/*
|
||||
Write a program that asks the user to input an integer, and tells the user whether the number is even or odd. Write a constexpr function called isEven() that returns true if an integer passed to it is even, and false otherwise. Use the remainder operator to test whether the integer parameter is even. Make sure isEven() works with both positive and negative numbers
|
||||
.*/
|
||||
|
||||
constexpr bool isEven(std::int32_t number) {
|
||||
return number % 2 == 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "input an integer: \n";
|
||||
std::int32_t x{};
|
||||
std::cin >> x;
|
||||
|
||||
std::cout << std::boolalpha << isEven(x);
|
||||
|
||||
return 0;
|
||||
}
|
||||
18
perf-cpp/scripts/chapter-1.cc
Normal file
18
perf-cpp/scripts/chapter-1.cc
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
std::cout << "Enter a number: \n";
|
||||
|
||||
int n;
|
||||
std::cin >> n;
|
||||
|
||||
int m;
|
||||
|
||||
std::cout << "Enter another number: \n";
|
||||
|
||||
std::cin >> m;
|
||||
|
||||
std::cout << "Diff: " << n - m << "; Sum: " << n + m << '\n';
|
||||
|
||||
return 0;
|
||||
}
|
||||
2
perf-cpp/scripts/compile_flags.txt
Normal file
2
perf-cpp/scripts/compile_flags.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
-O0
|
||||
-std=c++20
|
||||
14
perf-cpp/scripts/consteval.cc
Normal file
14
perf-cpp/scripts/consteval.cc
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include <iostream>
|
||||
|
||||
consteval int foo(int x) {
|
||||
if (x <= 1) return x;
|
||||
return foo(x - 1) + foo(x - 2);
|
||||
}
|
||||
|
||||
int main() {
|
||||
constexpr int x = foo(3);
|
||||
|
||||
static_assert(x != foo(4));
|
||||
|
||||
return 0;
|
||||
}
|
||||
10
perf-cpp/scripts/conversion.cc
Normal file
10
perf-cpp/scripts/conversion.cc
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#include <iostream>
|
||||
|
||||
void f(double) { std::cout << "double\n"; }
|
||||
void f(int) { std::cout << "long\n"; }
|
||||
|
||||
int main() {
|
||||
short x = 5;
|
||||
f(x); // Which one?
|
||||
}
|
||||
|
||||
14
perf-cpp/scripts/debug_flags.txt
Normal file
14
perf-cpp/scripts/debug_flags.txt
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
-g3
|
||||
-fsanitize=address,undefined
|
||||
-fsanitize=float-divide-by-zero
|
||||
-fsanitize=float-cast-overflow
|
||||
-fno-sanitize-recover=all
|
||||
-fstack-protector-all
|
||||
-fstack-usage
|
||||
-fno-omit-frame-pointer
|
||||
-fno-inline
|
||||
-ffunction-sections
|
||||
-D_GLIBCXX_DEBUG
|
||||
-D_GLIBCXX_DEBUG_PEDANTIC
|
||||
-DLOCAL
|
||||
-std=c++23
|
||||
50
perf-cpp/scripts/enum-class-quiz.cc
Normal file
50
perf-cpp/scripts/enum-class-quiz.cc
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include <iostream>
|
||||
|
||||
struct Counter {
|
||||
inline static int x = 1;
|
||||
static void bump() { ++x; }
|
||||
};
|
||||
|
||||
struct Counter2 : Counter {
|
||||
inline static int x = 100;
|
||||
static void bump() { x += 10; }
|
||||
};
|
||||
|
||||
enum E { A = 1, B = 2 };
|
||||
|
||||
struct S {
|
||||
enum E { B = 3, C = 4 };
|
||||
static int f() { return B; }
|
||||
};
|
||||
|
||||
enum class M : unsigned char { A = 250, B, C };
|
||||
|
||||
int g() {
|
||||
int B = 40;
|
||||
return S::f() + B;
|
||||
}
|
||||
|
||||
int main() {
|
||||
Counter::bump();
|
||||
Counter2::bump();
|
||||
|
||||
// 112
|
||||
int t1 = Counter::x + Counter2::x;
|
||||
|
||||
// 43
|
||||
int u1 = g();
|
||||
|
||||
int B = 7;
|
||||
// 9
|
||||
int t2 = B + ::B;
|
||||
|
||||
int d;
|
||||
{
|
||||
using enum M;
|
||||
// 251 - 250 = 1?
|
||||
d = static_cast<int>(B) - static_cast<int>(A);
|
||||
}
|
||||
|
||||
std::cout << t1 << " " << u1 << " " << t2 << " " << d << "\n";
|
||||
}
|
||||
|
||||
2
perf-cpp/scripts/io/chapter-1.in
Normal file
2
perf-cpp/scripts/io/chapter-1.in
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
1
|
||||
2
|
||||
7
perf-cpp/scripts/io/chapter-1.out
Normal file
7
perf-cpp/scripts/io/chapter-1.out
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Enter a number:
|
||||
Enter another number:
|
||||
Diff: -1; Sum: 3
|
||||
|
||||
[code]: 0
|
||||
[time]: 2.52771 ms
|
||||
[debug]: false
|
||||
0
perf-cpp/scripts/io/file.in
Normal file
0
perf-cpp/scripts/io/file.in
Normal file
14
perf-cpp/scripts/io/file.out
Normal file
14
perf-cpp/scripts/io/file.out
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
file.cc: In function ‘int main()’:
|
||||
file.cc:66:23: error: narrowing conversion of ‘3.0e+0’ from ‘double’ to ‘int’ [-Wnarrowing]
|
||||
66 | vector<int> a= { 3.0};
|
||||
| ^
|
||||
file.cc: At global scope:
|
||||
file.cc:39:13: warning: ‘void YES()’ defined but not used [-Wunused-function]
|
||||
39 | static void YES() {
|
||||
| ^~~
|
||||
file.cc:35:13: warning: ‘void NO()’ defined but not used [-Wunused-function]
|
||||
35 | static void NO() {
|
||||
| ^~
|
||||
cc1plus: note: unrecognized command-line option ‘-Wno-sign-promotion’ may have been intended to silence earlier diagnostics
|
||||
|
||||
[code]: 1
|
||||
32
perf-cpp/scripts/loops.cc
Normal file
32
perf-cpp/scripts/loops.cc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
void call_for() {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
std::cout << (1 + 123 * 6 ^ 3 << 2);
|
||||
}
|
||||
}
|
||||
|
||||
void call_while() {
|
||||
int i = 0;
|
||||
while (i < 5) {
|
||||
std::cout << (1 + 123 * 6 ^ 3 << 2);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void call_do_while() {
|
||||
int i = 0;
|
||||
do {
|
||||
std::cout << (1 + 123 * 6 ^ 3 << 2);
|
||||
++i;
|
||||
} while (i < 5);
|
||||
}
|
||||
|
||||
int main() {
|
||||
call_for();
|
||||
call_while();
|
||||
call_do_while();
|
||||
|
||||
return 0;
|
||||
}
|
||||
30
perf-cpp/scripts/makefile
Normal file
30
perf-cpp/scripts/makefile
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
.PHONY: run debug clean setup init
|
||||
|
||||
VERSION ?= 20
|
||||
|
||||
SRC = $(word 2,$(MAKECMDGOALS))
|
||||
|
||||
.SILENT:
|
||||
|
||||
run:
|
||||
sh scripts/run.sh $(SRC)
|
||||
|
||||
debug:
|
||||
sh scripts/debug.sh $(SRC)
|
||||
|
||||
clean:
|
||||
rm -rf build/*
|
||||
|
||||
setup:
|
||||
test -d build || mkdir -p build
|
||||
test -d io || mkdir -p io
|
||||
test -d scripts || mkdir -p scripts
|
||||
test -f .clang-format || cp $(HOME)/.config/cp-template/.clang-format .
|
||||
test -f compile_flags.txt || cp $(HOME)/.config/cp-template/compile_flags.txt . && echo -std=c++$(VERSION) >>compile_flags.txt
|
||||
test -f .clangd || cp $(HOME)/.config/cp-template/.clangd . && echo -e "\t\t-std=c++$(VERSION)" >>.clangd
|
||||
|
||||
init:
|
||||
make setup
|
||||
|
||||
%:
|
||||
@:
|
||||
29
perf-cpp/scripts/scripts/debug.sh
Normal file
29
perf-cpp/scripts/scripts/debug.sh
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/sh
|
||||
|
||||
. ./scripts/utils.sh
|
||||
|
||||
SRC="$1"
|
||||
BASE=$(basename "$SRC" .cc)
|
||||
INPUT="${BASE}.in"
|
||||
OUTPUT="${BASE}.out"
|
||||
DBG_BIN="${BASE}.debug"
|
||||
|
||||
test -d build || mkdir -p build
|
||||
test -d io || mkdir -p io
|
||||
|
||||
test -f "$INPUT" && test ! -f "io/$INPUT" && mv "$INPUT" "io/"
|
||||
test -f "$OUTPUT" && test ! -f "io/$OUTPUT" && mv "$OUTPUT" "io/"
|
||||
|
||||
test -f "io/$INPUT" || touch "io/$INPUT"
|
||||
test -f "io/$OUTPUT" || touch "io/$OUTPUT"
|
||||
|
||||
INPUT="io/$INPUT"
|
||||
OUTPUT="io/$OUTPUT"
|
||||
DBG_BIN="build/$DBG_BIN"
|
||||
|
||||
compile_source "$SRC" "$DBG_BIN" "$OUTPUT" @debug_flags.txt
|
||||
CODE=$?
|
||||
test $CODE -gt 0 && exit $CODE
|
||||
|
||||
execute_binary "$DBG_BIN" "$INPUT" "$OUTPUT" true
|
||||
exit $?
|
||||
29
perf-cpp/scripts/scripts/run.sh
Normal file
29
perf-cpp/scripts/scripts/run.sh
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/sh
|
||||
|
||||
. ./scripts/utils.sh
|
||||
|
||||
SRC="$1"
|
||||
BASE=$(basename "$SRC" .cc)
|
||||
INPUT="${BASE}.in"
|
||||
OUTPUT="${BASE}.out"
|
||||
RUN_BIN="${BASE}.run"
|
||||
|
||||
test -d build || mkdir -p build
|
||||
test -d io || mkdir -p io
|
||||
|
||||
test -f "$INPUT" && test ! -f "io/$INPUT" && mv "$INPUT" "io/"
|
||||
test -f "$OUTPUT" && test ! -f "io/$OUTPUT" && mv "$OUTPUT" "io/"
|
||||
|
||||
test -f "io/$INPUT" || touch "io/$INPUT"
|
||||
test -f "io/$OUTPUT" || touch "io/$OUTPUT"
|
||||
|
||||
INPUT="io/$INPUT"
|
||||
OUTPUT="io/$OUTPUT"
|
||||
RUN_BIN="build/$RUN_BIN"
|
||||
|
||||
compile_source "$SRC" "$RUN_BIN" "$OUTPUT" ""
|
||||
CODE=$?
|
||||
test $CODE -gt 0 && exit $CODE
|
||||
|
||||
execute_binary "$RUN_BIN" "$INPUT" "$OUTPUT"
|
||||
exit $?
|
||||
61
perf-cpp/scripts/scripts/utils.sh
Normal file
61
perf-cpp/scripts/scripts/utils.sh
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#!/bin/sh
|
||||
|
||||
execute_binary() {
|
||||
binary="$1"
|
||||
input="$2"
|
||||
output="$3"
|
||||
is_debug="$4"
|
||||
|
||||
start=$(date '+%s.%N')
|
||||
if [ -n "$is_debug" ]; then
|
||||
asan="$(ldconfig -p | grep libasan.so | head -n1 | awk '{print $4}')"
|
||||
LD_PRELOAD="$asan" timeout 2s ./"$binary" <"$input" >"$output" 2>&1
|
||||
else
|
||||
timeout 2s ./"$binary" <"$input" >"$output" 2>&1
|
||||
fi
|
||||
CODE=$?
|
||||
end=$(date '+%s.%N')
|
||||
truncate -s "$(head -n 1000 "$output" | wc -c)" "$output"
|
||||
|
||||
if [ $CODE -ge 124 ]; then
|
||||
MSG=''
|
||||
case $CODE in
|
||||
124) MSG='TIMEOUT' ;;
|
||||
128) MSG='SIGILL' ;;
|
||||
130) MSG='SIGABRT' ;;
|
||||
131) MSG='SIGBUS' ;;
|
||||
136) MSG='SIGFPE' ;;
|
||||
135) MSG='SIGSEGV' ;;
|
||||
137) MSG='SIGPIPE' ;;
|
||||
139) MSG='SIGTERM' ;;
|
||||
esac
|
||||
[ $CODE -ne 124 ] && sed -i '$d' "$output"
|
||||
test -n "$MSG" && printf '\n[code]: %s (%s)' "$CODE" "$MSG" >>"$output"
|
||||
else
|
||||
printf '\n[code]: %s' "$CODE" >>"$output"
|
||||
fi
|
||||
|
||||
printf '\n[time]: %s ms' "$(awk "BEGIN {print ($end - $start) * 1000}")" >>$output
|
||||
test -n "$is_debug" && is_debug_string=true || is_debug_string=false
|
||||
printf '\n[debug]: %s' "$is_debug_string" >>$output
|
||||
return $CODE
|
||||
}
|
||||
|
||||
compile_source() {
|
||||
src="$1"
|
||||
bin="$2"
|
||||
output="$3"
|
||||
flags="$4"
|
||||
|
||||
test -f "$bin" && rm "$bin" || true
|
||||
g++ @compile_flags.txt $flags "$src" -o "$bin" 2>"$output"
|
||||
CODE=$?
|
||||
|
||||
if [ $CODE -gt 0 ]; then
|
||||
printf '\n[code]: %s' "$CODE" >>"$output"
|
||||
return $CODE
|
||||
else
|
||||
echo '' >"$output"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
40
perf-cpp/scripts/struct.cc
Normal file
40
perf-cpp/scripts/struct.cc
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#include <iostream>
|
||||
|
||||
class S {
|
||||
// void print() const { a = 3; std::cout << S::a << '\n'; }
|
||||
int a = 0;
|
||||
|
||||
public:
|
||||
S(int x) : x(x) {
|
||||
}
|
||||
int x{2};
|
||||
};
|
||||
|
||||
class X {
|
||||
int x;
|
||||
|
||||
public:
|
||||
X() : x(0) {};
|
||||
void get() {
|
||||
std::cout << "x; " << x << '\n';
|
||||
}
|
||||
int& y() {
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
// S{}.print();
|
||||
// S.x;
|
||||
// std::cout << S{3}.x << '\n';
|
||||
|
||||
X x;
|
||||
auto& ret = x.y();
|
||||
|
||||
// ++ret;
|
||||
|
||||
x.get();
|
||||
|
||||
// X x;
|
||||
return 0;
|
||||
}
|
||||
39
perf-cpp/scripts/switch.cc
Normal file
39
perf-cpp/scripts/switch.cc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include <iostream>
|
||||
|
||||
extern volatile int sink;
|
||||
|
||||
int g(int x) {
|
||||
if (x == 100) sink = 42;
|
||||
else if (x == 101) sink = 7;
|
||||
else if (x == 102) sink = 99;
|
||||
else if (x == 103) sink = 13;
|
||||
else if (x == 104) sink = 5;
|
||||
else if (x == 105) sink = 88;
|
||||
else if (x == 106) sink = 21;
|
||||
else if (x == 107) sink = 60;
|
||||
else if (x == 108) sink = 33;
|
||||
else if (x == 109) sink = 1;
|
||||
else if (x == 110) sink = 77;
|
||||
else if (x == 111) sink = 12;
|
||||
else if (x == 112) sink = 54;
|
||||
else if (x == 113) sink = 31;
|
||||
else if (x == 114) sink = 73;
|
||||
else if (x == 115) sink = 16;
|
||||
else sink = -1;
|
||||
return sink;
|
||||
}
|
||||
|
||||
int main() {
|
||||
char x;
|
||||
std::cin >> x;
|
||||
|
||||
if (x == 'x') {
|
||||
std::cout << "hi\n";
|
||||
} else {
|
||||
if (x == 'y') {
|
||||
std::cout << "sup\n";
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue