diff --git a/.gitignore b/.gitignore index 444bb3f..40f07a7 100644 --- a/.gitignore +++ b/.gitignore @@ -208,4 +208,10 @@ $RECYCLE.BIN/ # Mac desktop service store files .DS_Store -_NCrunch* \ No newline at end of file +_NCrunch* + +venv +env +.env +.enviroment +__pycache__ \ No newline at end of file diff --git a/NewFile b/NewFile new file mode 100644 index 0000000..e69de29 diff --git a/Writing wxIRC.docx b/Writing wxIRC.docx new file mode 100644 index 0000000..29cb55d Binary files /dev/null and b/Writing wxIRC.docx differ diff --git a/assembly/main.py b/assembly/main.py new file mode 100644 index 0000000..913c606 --- /dev/null +++ b/assembly/main.py @@ -0,0 +1,677 @@ +import tkinter as tk +from tkinter import ttk, scrolledtext, messagebox +import re +from dataclasses import dataclass +from typing import Dict, List, Optional, Tuple +from enum import Enum + +class CPUMode(Enum): + SIMPLE = "simple" + X86 = "x86" + ARM = "arm" + +@dataclass +class CPUState: + """Complete CPU state representation""" + registers: Dict[str, int] + memory: bytearray + ip: int + sp: int + flags: Dict[str, bool] + halted: bool + mode: CPUMode + + def __init__(self, mem_size=65536, mode=CPUMode.SIMPLE): + self.registers = {f"R{i}": 0 for i in range(8)} + self.memory = bytearray(mem_size) + self.ip = 0 + self.sp = mem_size - 4 # Stack starts at top + self.flags = {"Z": False, "N": False, "C": False, "O": False} + self.halted = False + self.mode = mode + self.bp = mem_size - 4 # Base pointer + +class Breakpoint: + def __init__(self, address=None, label=None, condition=None): + self.address = address + self.label = label + self.condition = condition + self.enabled = True + +class Instruction: + def __init__(self, opcode, operands, line_num, label=None, comment=None): + self.opcode = opcode + self.operands = operands + self.line_num = line_num + self.label = label + self.comment = comment + self.address = 0 + +class AssemblyDebugger: + def __init__(self, mode=CPUMode.SIMPLE): + self.cpu = CPUState(mode=mode) + self.instructions: List[Instruction] = [] + self.labels: Dict[str, int] = {} + self.breakpoints: List[Breakpoint] = [] + self.execution_history: List[str] = [] + self.source_lines: List[str] = [] + self.pipeline_enabled = False + self.cache_enabled = False + + def reset(self): + """Reset CPU to initial state""" + mem_size = len(self.cpu.memory) + mode = self.cpu.mode + self.cpu = CPUState(mem_size, mode) + self.execution_history.clear() + + def parse_assembly(self, code: str) -> Tuple[bool, str]: + """Parse assembly code into instructions""" + self.instructions.clear() + self.labels.clear() + self.source_lines = code.split('\n') + + address = 0 + for line_num, line in enumerate(self.source_lines, 1): + line = line.strip() + + # Skip empty lines and comments + if not line or line.startswith(';'): + continue + + # Extract comment + comment = None + if ';' in line: + line, comment = line.split(';', 1) + line = line.strip() + comment = comment.strip() + + # Check for label + label = None + if ':' in line: + label, line = line.split(':', 1) + label = label.strip() + self.labels[label] = address + line = line.strip() + + if not line: + continue + + # Parse instruction + parts = line.split(None, 1) + if not parts: + continue + + opcode = parts[0].upper() + operands = [] + + if len(parts) > 1: + operands = [op.strip() for op in parts[1].split(',')] + + instr = Instruction(opcode, operands, line_num, label, comment) + instr.address = address + self.instructions.append(instr) + + # Estimate instruction size (simplified) + address += 4 + + return True, "Assembly parsed successfully" + + def parse_operand(self, operand: str) -> Tuple[str, int]: + """Parse operand and return (type, value)""" + operand = operand.strip() + + # Register + if operand.upper() in self.cpu.registers or operand.upper() in ['SP', 'BP', 'IP']: + return ('register', operand.upper()) + + # Memory reference [addr] or [register] + if operand.startswith('[') and operand.endswith(']'): + inner = operand[1:-1].strip() + + # [register+offset] or [register-offset] + if '+' in inner or '-' in inner: + return ('memory_offset', inner) + + # [register] + if inner.upper() in self.cpu.registers or inner.upper() in ['SP', 'BP']: + return ('memory_reg', inner.upper()) + + # [address] + try: + addr = self.parse_number(inner) + return ('memory', addr) + except: + return ('error', f"Invalid memory reference: {operand}") + + # Immediate value + try: + value = self.parse_number(operand) + return ('immediate', value) + except: + pass + + # Label + if operand in self.labels: + return ('label', self.labels[operand]) + + return ('error', f"Invalid operand: {operand}") + + def parse_number(self, s: str) -> int: + """Parse number in various formats""" + s = s.strip() + if s.startswith('0x') or s.startswith('0X'): + return int(s, 16) + elif s.startswith('0b') or s.startswith('0B'): + return int(s, 2) + else: + return int(s) + + def get_operand_value(self, operand: str) -> int: + """Get the value of an operand""" + op_type, value = self.parse_operand(operand) + + if op_type == 'register': + if value == 'SP': + return self.cpu.sp + elif value == 'BP': + return self.cpu.bp + elif value == 'IP': + return self.cpu.ip + return self.cpu.registers[value] + + elif op_type == 'immediate' or op_type == 'label': + return value + + elif op_type == 'memory': + return self.read_memory(value, 4) + + elif op_type == 'memory_reg': + addr = self.get_operand_value(value) + return self.read_memory(addr, 4) + + elif op_type == 'memory_offset': + # Parse BP+4 or SP-8 etc + if '+' in value: + reg, offset = value.split('+') + addr = self.get_operand_value(reg.strip()) + self.parse_number(offset.strip()) + else: + reg, offset = value.split('-') + addr = self.get_operand_value(reg.strip()) - self.parse_number(offset.strip()) + return self.read_memory(addr, 4) + + raise ValueError(f"Cannot get value of operand: {operand}") + + def set_operand_value(self, operand: str, value: int): + """Set the value of an operand""" + op_type, op_value = self.parse_operand(operand) + + # Ensure value is in 32-bit range + value = value & 0xFFFFFFFF + + if op_type == 'register': + if op_value == 'SP': + self.cpu.sp = value + elif op_value == 'BP': + self.cpu.bp = value + elif op_value == 'IP': + self.cpu.ip = value + else: + self.cpu.registers[op_value] = value + + elif op_type == 'memory': + self.write_memory(op_value, value, 4) + + elif op_type == 'memory_reg': + addr = self.get_operand_value(op_value) + self.write_memory(addr, value, 4) + + elif op_type == 'memory_offset': + if '+' in op_value: + reg, offset = op_value.split('+') + addr = self.get_operand_value(reg.strip()) + self.parse_number(offset.strip()) + else: + reg, offset = op_value.split('-') + addr = self.get_operand_value(reg.strip()) - self.parse_number(offset.strip()) + self.write_memory(addr, value, 4) + + else: + raise ValueError(f"Cannot set value of operand: {operand}") + + def read_memory(self, address: int, size: int) -> int: + """Read from memory (little-endian)""" + if address < 0 or address + size > len(self.cpu.memory): + raise ValueError(f"Memory access violation at 0x{address:08X}") + + value = 0 + for i in range(size): + value |= self.cpu.memory[address + i] << (i * 8) + return value + + def write_memory(self, address: int, value: int, size: int): + """Write to memory (little-endian)""" + if address < 0 or address + size > len(self.cpu.memory): + raise ValueError(f"Memory access violation at 0x{address:08X}") + + for i in range(size): + self.cpu.memory[address + i] = (value >> (i * 8)) & 0xFF + + def update_flags(self, result: int, original_bits=32): + """Update CPU flags based on result""" + mask = (1 << original_bits) - 1 + result = result & mask + + self.cpu.flags['Z'] = (result == 0) + self.cpu.flags['N'] = (result & (1 << (original_bits - 1))) != 0 + # Carry handled by individual operations + + def execute_instruction(self, instr: Instruction) -> Tuple[bool, str]: + """Execute a single instruction and return detailed explanation""" + explanation = [] + + try: + # Save state before execution + old_registers = self.cpu.registers.copy() + old_flags = self.cpu.flags.copy() + old_sp = self.cpu.sp + old_ip = self.cpu.ip + + explanation.append(f"▶ EXECUTING: {instr.opcode} {', '.join(instr.operands)}") + if instr.comment: + explanation.append(f" Comment: {instr.comment}") + + # Execute based on opcode + if instr.opcode == 'MOV': + src_val = self.get_operand_value(instr.operands[1]) + explanation.append(f" Moving value {src_val} (0x{src_val:08X}) to {instr.operands[0]}") + self.set_operand_value(instr.operands[0], src_val) + + elif instr.opcode == 'ADD': + dst_val = self.get_operand_value(instr.operands[0]) + src_val = self.get_operand_value(instr.operands[1]) + result = dst_val + src_val + explanation.append(f" {dst_val} + {src_val} = {result & 0xFFFFFFFF}") + self.cpu.flags['C'] = result > 0xFFFFFFFF + self.set_operand_value(instr.operands[0], result) + self.update_flags(result) + + elif instr.opcode == 'SUB': + dst_val = self.get_operand_value(instr.operands[0]) + src_val = self.get_operand_value(instr.operands[1]) + result = dst_val - src_val + explanation.append(f" {dst_val} - {src_val} = {result & 0xFFFFFFFF}") + self.cpu.flags['C'] = result < 0 + self.set_operand_value(instr.operands[0], result) + self.update_flags(result) + + elif instr.opcode == 'MUL': + dst_val = self.get_operand_value(instr.operands[0]) + src_val = self.get_operand_value(instr.operands[1]) + result = dst_val * src_val + explanation.append(f" {dst_val} × {src_val} = {result & 0xFFFFFFFF}") + self.cpu.flags['C'] = result > 0xFFFFFFFF + self.set_operand_value(instr.operands[0], result) + self.update_flags(result) + + elif instr.opcode == 'DIV': + dst_val = self.get_operand_value(instr.operands[0]) + src_val = self.get_operand_value(instr.operands[1]) + if src_val == 0: + return False, "❌ DIVISION BY ZERO" + result = dst_val // src_val + explanation.append(f" {dst_val} ÷ {src_val} = {result}") + self.set_operand_value(instr.operands[0], result) + self.update_flags(result) + + elif instr.opcode == 'CMP': + val1 = self.get_operand_value(instr.operands[0]) + val2 = self.get_operand_value(instr.operands[1]) + result = val1 - val2 + explanation.append(f" Comparing {val1} with {val2}: difference = {result}") + self.cpu.flags['Z'] = (val1 == val2) + self.cpu.flags['N'] = (result < 0) + self.cpu.flags['C'] = (val1 < val2) + explanation.append(f" Flags set: Z={int(self.cpu.flags['Z'])}, N={int(self.cpu.flags['N'])}, C={int(self.cpu.flags['C'])}") + + elif instr.opcode == 'JMP': + target = self.labels.get(instr.operands[0]) + if target is None: + return False, f"❌ Unknown label: {instr.operands[0]}" + explanation.append(f" Unconditional jump to {instr.operands[0]} (address 0x{target:04X})") + self.cpu.ip = target + return True, '\n'.join(explanation) + + elif instr.opcode == 'JE' or instr.opcode == 'JZ': + target = self.labels.get(instr.operands[0]) + if target is None: + return False, f"❌ Unknown label: {instr.operands[0]}" + if self.cpu.flags['Z']: + explanation.append(f" Zero flag is SET → Taking jump to {instr.operands[0]}") + self.cpu.ip = target + return True, '\n'.join(explanation) + else: + explanation.append(f" Zero flag is CLEAR → Not jumping, continuing to next instruction") + + elif instr.opcode == 'JNE' or instr.opcode == 'JNZ': + target = self.labels.get(instr.operands[0]) + if target is None: + return False, f"❌ Unknown label: {instr.operands[0]}" + if not self.cpu.flags['Z']: + explanation.append(f" Zero flag is CLEAR → Taking jump to {instr.operands[0]}") + self.cpu.ip = target + return True, '\n'.join(explanation) + else: + explanation.append(f" Zero flag is SET → Not jumping, continuing to next instruction") + + elif instr.opcode == 'JG': + target = self.labels.get(instr.operands[0]) + if target is None: + return False, f"❌ Unknown label: {instr.operands[0]}" + if not self.cpu.flags['Z'] and not self.cpu.flags['N']: + explanation.append(f" Greater than condition met → Taking jump") + self.cpu.ip = target + return True, '\n'.join(explanation) + else: + explanation.append(f" Greater than condition not met → Not jumping") + + elif instr.opcode == 'JL': + target = self.labels.get(instr.operands[0]) + if target is None: + return False, f"❌ Unknown label: {instr.operands[0]}" + if self.cpu.flags['N']: + explanation.append(f" Less than condition met → Taking jump") + self.cpu.ip = target + return True, '\n'.join(explanation) + else: + explanation.append(f" Less than condition not met → Not jumping") + + elif instr.opcode == 'PUSH': + value = self.get_operand_value(instr.operands[0]) + self.cpu.sp -= 4 + explanation.append(f" Pushing value {value} (0x{value:08X}) onto stack") + explanation.append(f" Stack pointer: 0x{old_sp:04X} → 0x{self.cpu.sp:04X}") + self.write_memory(self.cpu.sp, value, 4) + + elif instr.opcode == 'POP': + if self.cpu.sp >= len(self.cpu.memory) - 4: + return False, "❌ STACK UNDERFLOW" + value = self.read_memory(self.cpu.sp, 4) + explanation.append(f" Popping value {value} (0x{value:08X}) from stack") + self.set_operand_value(instr.operands[0], value) + old_sp = self.cpu.sp + self.cpu.sp += 4 + explanation.append(f" Stack pointer: 0x{old_sp:04X} → 0x{self.cpu.sp:04X}") + + elif instr.opcode == 'CALL': + target = self.labels.get(instr.operands[0]) + if target is None: + return False, f"❌ Unknown label: {instr.operands[0]}" + # Push return address + return_addr = self.cpu.ip + 4 + self.cpu.sp -= 4 + self.write_memory(self.cpu.sp, return_addr, 4) + explanation.append(f" Calling function {instr.operands[0]}") + explanation.append(f" Return address 0x{return_addr:04X} pushed to stack") + explanation.append(f" Jumping to 0x{target:04X}") + self.cpu.ip = target + return True, '\n'.join(explanation) + + elif instr.opcode == 'RET': + if self.cpu.sp >= len(self.cpu.memory) - 4: + return False, "❌ STACK UNDERFLOW on RET" + return_addr = self.read_memory(self.cpu.sp, 4) + self.cpu.sp += 4 + explanation.append(f" Returning to address 0x{return_addr:04X}") + self.cpu.ip = return_addr + return True, '\n'.join(explanation) + + elif instr.opcode == 'LOAD': + addr_val = self.get_operand_value(instr.operands[1]) + value = self.read_memory(addr_val, 4) + explanation.append(f" Loading value {value} (0x{value:08X}) from memory[0x{addr_val:04X}]") + self.set_operand_value(instr.operands[0], value) + + elif instr.opcode == 'STORE': + addr_val = self.get_operand_value(instr.operands[0]) + value = self.get_operand_value(instr.operands[1]) + explanation.append(f" Storing value {value} (0x{value:08X}) to memory[0x{addr_val:04X}]") + self.write_memory(addr_val, value, 4) + + elif instr.opcode == 'HLT': + explanation.append(" Halting CPU") + self.cpu.halted = True + return True, '\n'.join(explanation) + + else: + return False, f"❌ Unknown instruction: {instr.opcode}" + + # Advance IP if not already modified by jump/call/ret + if self.cpu.ip == old_ip: + self.cpu.ip += 4 + + # Show what changed + changes = [] + for reg, val in self.cpu.registers.items(): + if val != old_registers[reg]: + changes.append(f" {reg}: 0x{old_registers[reg]:08X} → 0x{val:08X}") + + if self.cpu.sp != old_sp: + changes.append(f" SP: 0x{old_sp:04X} → 0x{self.cpu.sp:04X}") + + if self.cpu.ip != old_ip and instr.opcode not in ['JMP', 'JE', 'JNE', 'JG', 'JL', 'CALL', 'RET']: + changes.append(f" IP: 0x{old_ip:04X} → 0x{self.cpu.ip:04X}") + + flag_changes = [] + for flag, val in self.cpu.flags.items(): + if val != old_flags[flag]: + flag_changes.append(f"{flag}={int(val)}") + + if flag_changes: + changes.append(f" FLAGS: {' '.join(flag_changes)}") + + if changes: + explanation.append("\n🔄 CHANGES:") + explanation.extend(changes) + else: + explanation.append("\n (No register or flag changes)") + + return True, '\n'.join(explanation) + + except Exception as e: + return False, f"❌ ERROR: {str(e)}" + + def find_instruction_at_ip(self) -> Optional[Instruction]: + """Find instruction at current IP""" + for instr in self.instructions: + if instr.address == self.cpu.ip: + return instr + return None + + def check_breakpoints(self) -> Optional[Breakpoint]: + """Check if any breakpoint is hit""" + for bp in self.breakpoints: + if not bp.enabled: + continue + + if bp.address is not None and bp.address == self.cpu.ip: + return bp + + if bp.condition: + # Evaluate condition (simplified) + try: + # Replace register names with values + cond = bp.condition + for reg in self.cpu.registers: + cond = cond.replace(reg, str(self.cpu.registers[reg])) + if eval(cond): + return bp + except: + pass + + return None + + def get_state_display(self) -> str: + """Get formatted CPU state""" + lines = [] + lines.append("REGISTERS:") + + # Show registers in rows of 4 + for i in range(0, 8, 4): + reg_line = " " + for j in range(4): + if i + j < 8: + reg = f"R{i+j}" + val = self.cpu.registers[reg] + reg_line += f"{reg}=0x{val:08X} " + lines.append(reg_line) + + lines.append(f" SP=0x{self.cpu.sp:04X} BP=0x{self.cpu.bp:04X} IP=0x{self.cpu.ip:04X}") + + flags_str = ' '.join([f"{k}={int(v)}" for k, v in self.cpu.flags.items()]) + lines.append(f" FLAGS: {flags_str}") + + # Show stack + lines.append("\nSTACK (top 16 bytes):") + for addr in range(self.cpu.sp, min(self.cpu.sp + 16, len(self.cpu.memory)), 4): + value = self.read_memory(addr, 4) + ascii_repr = ''.join([chr(b) if 32 <= b < 127 else '.' + for b in self.cpu.memory[addr:addr+4]]) + lines.append(f" 0x{addr:04X}: {value:08X} {ascii_repr}") + + return '\n'.join(lines) + + def compile_c_to_asm(self, c_code: str) -> str: + """Simple C to Assembly compiler (educational)""" + output = [] + output.append("C → ASSEMBLY COMPILATION") + output.append("=" * 50) + output.append("") + + # Very simplified C parser for educational purposes + # Handle simple function definitions + + # Example: int add(int a, int b) { return a + b; } + func_pattern = r'(\w+)\s+(\w+)\s*\(([^)]*)\)\s*\{([^}]*)\}' + matches = re.findall(func_pattern, c_code, re.DOTALL) + + if not matches: + output.append("❌ No functions found or unsupported C syntax") + return '\n'.join(output) + + for return_type, func_name, params, body in matches: + output.append(f"FUNCTION: {func_name}") + output.append("") + + # Parse parameters + param_list = [p.strip() for p in params.split(',') if p.strip()] + param_names = [] + for p in param_list: + parts = p.split() + if len(parts) >= 2: + param_names.append(parts[-1]) + + # Stack frame explanation + output.append("STACK FRAME LAYOUT:") + output.append(" [BP+0] ← saved BP") + output.append(" [BP-4] ← return address") + + offset = -8 + var_offsets = {} + for param in param_names: + output.append(f" [BP{offset}] ← {param}") + var_offsets[param] = offset + offset -= 4 + + output.append("") + output.append("GENERATED ASSEMBLY:") + output.append("") + + # Function prologue + asm = [] + asm.append(f"{func_name}:") + asm.append(" PUSH BP") + asm.append(" MOV BP, SP") + + # Parse body for return statement + return_match = re.search(r'return\s+([^;]+);', body) + if return_match: + expr = return_match.group(1).strip() + + # Simple expression parsing + if '+' in expr: + parts = expr.split('+') + var1 = parts[0].strip() + var2 = parts[1].strip() + + asm.append(f" ; Calculate {var1} + {var2}") + asm.append(f" MOV R0, [BP{var_offsets.get(var1, -8)}]") + asm.append(f" ADD R0, [BP{var_offsets.get(var2, -12)}]") + asm.append(" ; Result in R0") + + elif '-' in expr: + parts = expr.split('-') + var1 = parts[0].strip() + var2 = parts[1].strip() + + asm.append(f" ; Calculate {var1} - {var2}") + asm.append(f" MOV R0, [BP{var_offsets.get(var1, -8)}]") + asm.append(f" SUB R0, [BP{var_offsets.get(var2, -12)}]") + + elif expr in var_offsets: + asm.append(f" ; Return {expr}") + asm.append(f" MOV R0, [BP{var_offsets[expr]}]") + + else: + # Try to parse as number + try: + val = int(expr) + asm.append(f" ; Return constant {val}") + asm.append(f" MOV R0, {val}") + except: + asm.append(f" ; Return expression: {expr}") + asm.append(f" MOV R0, 0 ; SIMPLIFIED") + + # Function epilogue + asm.append(" POP BP") + asm.append(" RET") + + output.extend(asm) + output.append("") + + output.append("=" * 50) + output.append("✓ Compilation complete. Copy assembly code to execute.") + + return '\n'.join(output) + + +class DebuggerGUI: + def __init__(self, root): + self.root = root + self.root.title("🧠 Assembly Debugger & CPU Simulator") + self.root.geometry("1400x900") + + self.debugger = AssemblyDebugger() + self.running = False + self.stepping = False + + self.setup_ui() + self.show_startup_message() + + def setup_ui(self): + # Main container with paned window + main_paned = ttk.PanedWindow(self.root, orient=tk.HORIZONTAL) + main_paned.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) + + # Left panel - Code editor + left_frame = ttk.Frame(main_paned) + main_paned.add(left_frame, weight=1) + + # Code input + ttk.Label(left_frame, text="Assembly Code:", font=('Courier', 10, 'bold')).pack(anchor='w') + + self.code_text = scrolledtext.ScrolledText(left_frame, width=50, height=25, + font=('Courier', 10)) + self.code_text.pack(fill=tk.BOTH, expand=True, pady=5) + + # Sample code + sample = """; Simple addition example \ No newline at end of file diff --git a/csv/oesterreich/main.py b/csv/oesterreich/main.py new file mode 100644 index 0000000..7b0cf36 --- /dev/null +++ b/csv/oesterreich/main.py @@ -0,0 +1,36 @@ +import csv +import random +import json +import sys + +use_json = "-json" in sys.argv + +try: + with open("oesterreich.csv", "r", newline="", encoding="latin-1") as f: + reader = csv.reader(f, delimiter=";") + rows = list(reader)[1:] # Header entfernen + + topo = [] + + for row in rows: + if row[0]: # Gebirge + topo.append(row[0]) + if row[2]: # Landschaften + topo.append(row[2]) + + topo = list(set(topo)) # Duplikate entfernen + + result = [] + for i in range(17): + result.append(random.sample(topo, 6)) + + if use_json: + with open("topo.json", "w", encoding="utf-8") as f: + json.dump(result, f, ensure_ascii=False, indent=2) + else: + with open("topo.txt", "w", encoding="utf-8") as f: + for row in result: + f.write(", ".join(row) + "\n") + +except Exception as e: + print("Exception:", e) diff --git a/csv/oesterreich/oesterreich.csv b/csv/oesterreich/oesterreich.csv new file mode 100644 index 0000000..0642c1a --- /dev/null +++ b/csv/oesterreich/oesterreich.csv @@ -0,0 +1,79 @@ +Gebirge;Flsse;Landschaften;Stdte +Bregenzer Wald;Donau;Pinzgau;Bregenz +Rtikon;Inn;Pongau;Lustenau +Silvretta;Salzach;Lungau;Dorbbirn +Lechtaler Alpen;Enns;Tennengau;Feldkirch +tztaler Alpen;Traun;Flachgau;Bludenz +Stubaier Alpen;Groe Mhl;;Schruns +Karwendel;Bregenzerach;;Telfs +Zillertaler Alpen; Ill;;Innsbruck +Kitzbheler Aplen;Lech;;Imst +Hohe Tauern;Sill (Wipptal);;Reutte +Karnische Alpen;Groe Ache;;Schwaz +Tennengebrige;Drau;;Wrgl +Dachstein;Mur;;Kufstein +Totes Gebirge;Mrz;;Kitzbhel +Sengsengebirge;Kamp;;Kaprun +Deferegger Gebirge;Leitha;;Lienz +Gurktaler Alpen;Lafnitz;;Zell am See +Saualpe;Raab;;Saalfelden +Packalpe;Gurk;;Radstadt +Koralpe;Lavant;;Tamsweg +Karawanken;;;Braunau +Fischbacher Alpen;;;Ried im Innkreis +Leithagebirge;;;Schrding +;;;Rohrbach +;;;Grieskirchen +;;;Vlklabruck +;;;Wels +;;;Eferding +;;;Freistadt +;;;Gmunden +;;;Bad Ischl +;;;Enns +;;;Linz +;;;Zwettl +;;;Waidhofen an der Thaya +;;;Horn +;;;Krems +;;;Melk +;;;Hollabrunn +;;;St. Plten +;;;Klosterneuburg +;;;Wien +;;;Gnserndorf +;;;Mistelbach +;;;Wiener Neustadt +;;;Liezen +;;;Bad Aussee +;;;Murau +;;;Judenburg +;;;Knittelfeld +;;;Leoben +;;;Bruck an der Mur +;;;Mrzzuschlag +;;;Kapfenberg +;;;Graz +;;;Hartberg +;;;Weiz +;;;Frstenfeld +;;;Feldbach +;;;Radkersburg +;;;Leibnitz +;;;Deutschlandsberg +;;;Voitsberg +;;;Kflach +;;;Eisenstadt +;;;Oberpullendorf +;;;Bruck an der Leitha +;;;Neusiedl am See +;;;Oberwart +;;;Gssing +;;;Hermagor +;;;Villach +;;;Spital an der Drau +;;;Feldkirchen +;;;Klagenfurt +;;;Wolfsberg +;;;Vlkermarkt +;;;St. Veit an der Glan diff --git a/csv/oesterreich/topo.json b/csv/oesterreich/topo.json new file mode 100644 index 0000000..22561b5 --- /dev/null +++ b/csv/oesterreich/topo.json @@ -0,0 +1,138 @@ +[ + [ + "Tennengau", + "Bregenzer Wald", + "Rätikon", + "Hohe Tauern", + "Dachstein", + "Stubaier Alpen" + ], + [ + "Pinzgau", + "Gurktaler Alpen", + "Flachgau", + "Silvretta", + "Karwendel", + "Koralpe" + ], + [ + "Fischbacher Alpen", + "Dachstein", + "Gurktaler Alpen", + "Karwendel", + "Rätikon", + "Koralpe" + ], + [ + "Lungau", + "Tennengebrige", + "Koralpe", + "Sengsengebirge", + "Zillertaler Alpen", + "Bregenzer Wald" + ], + [ + "Kitzbüheler Aplen", + "Karawanken", + "Deferegger Gebirge", + "Leithagebirge", + "Silvretta", + "Bregenzer Wald" + ], + [ + "Packalpe", + "Stubaier Alpen", + "Lechtaler Alpen", + "Karnische Alpen", + "Silvretta", + "Hohe Tauern" + ], + [ + "Leithagebirge", + "Saualpe", + "Karnische Alpen", + "Dachstein", + "Fischbacher Alpen", + "Hohe Tauern" + ], + [ + "Tennengau", + "Karwendel", + "Ötztaler Alpen", + "Silvretta", + "Tennengebrige", + "Hohe Tauern" + ], + [ + "Tennengau", + "Packalpe", + "Hohe Tauern", + "Ötztaler Alpen", + "Zillertaler Alpen", + "Kitzbüheler Aplen" + ], + [ + "Lungau", + "Saualpe", + "Sengsengebirge", + "Koralpe", + "Leithagebirge", + "Ötztaler Alpen" + ], + [ + "Pinzgau", + "Lungau", + "Rätikon", + "Bregenzer Wald", + "Saualpe", + "Koralpe" + ], + [ + "Karwendel", + "Zillertaler Alpen", + "Stubaier Alpen", + "Karawanken", + "Koralpe", + "Pongau" + ], + [ + "Karawanken", + "Karnische Alpen", + "Kitzbüheler Aplen", + "Karwendel", + "Pinzgau", + "Silvretta" + ], + [ + "Stubaier Alpen", + "Kitzbüheler Aplen", + "Totes Gebirge", + "Lechtaler Alpen", + "Koralpe", + "Rätikon" + ], + [ + "Silvretta", + "Dachstein", + "Flachgau", + "Kitzbüheler Aplen", + "Koralpe", + "Tennengebrige" + ], + [ + "Zillertaler Alpen", + "Packalpe", + "Kitzbüheler Aplen", + "Tennengau", + "Leithagebirge", + "Stubaier Alpen" + ], + [ + "Totes Gebirge", + "Bregenzer Wald", + "Saualpe", + "Tennengau", + "Tennengebrige", + "Gurktaler Alpen" + ] +] \ No newline at end of file diff --git a/csv/oesterreich/topo.txt b/csv/oesterreich/topo.txt new file mode 100644 index 0000000..2c21553 --- /dev/null +++ b/csv/oesterreich/topo.txt @@ -0,0 +1,17 @@ +Lungau, Saualpe, Zillertaler Alpen, Tennengau, Koralpe, Deferegger Gebirge +Deferegger Gebirge, Stubaier Alpen, Kitzbüheler Aplen, Lechtaler Alpen, Leithagebirge, Silvretta +Lechtaler Alpen, Rätikon, Flachgau, Tennengau, Saualpe, Zillertaler Alpen +Fischbacher Alpen, Tennengau, Ötztaler Alpen, Dachstein, Gurktaler Alpen, Deferegger Gebirge +Silvretta, Lungau, Packalpe, Saualpe, Karawanken, Ötztaler Alpen +Totes Gebirge, Silvretta, Packalpe, Koralpe, Leithagebirge, Saualpe +Packalpe, Dachstein, Sengsengebirge, Pongau, Leithagebirge, Tennengebrige +Silvretta, Fischbacher Alpen, Koralpe, Gurktaler Alpen, Karnische Alpen, Deferegger Gebirge +Deferegger Gebirge, Rätikon, Saualpe, Zillertaler Alpen, Karnische Alpen, Bregenzer Wald +Karwendel, Dachstein, Tennengau, Deferegger Gebirge, Pongau, Lungau +Dachstein, Lungau, Karnische Alpen, Pinzgau, Zillertaler Alpen, Stubaier Alpen +Karwendel, Saualpe, Flachgau, Lungau, Hohe Tauern, Tennengebrige +Karwendel, Fischbacher Alpen, Bregenzer Wald, Hohe Tauern, Karawanken, Koralpe +Leithagebirge, Sengsengebirge, Stubaier Alpen, Tennengau, Silvretta, Saualpe +Tennengau, Karawanken, Silvretta, Sengsengebirge, Tennengebrige, Lechtaler Alpen +Karnische Alpen, Karwendel, Zillertaler Alpen, Kitzbüheler Aplen, Silvretta, Sengsengebirge +Gurktaler Alpen, Stubaier Alpen, Tennengau, Saualpe, Packalpe, Tennengebrige diff --git a/math/w3/main.cpp b/math/w3/main.cpp new file mode 100644 index 0000000..1268b19 --- /dev/null +++ b/math/w3/main.cpp @@ -0,0 +1,212 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "user32.lib") +#pragma comment(lib, "gdi32.lib") + +#define WIDTH 1280 +#define HEIGHT 800 +#define MAX_ITER 1000 + +static uint32_t framebuffer[WIDTH * HEIGHT]; + +static double centerX = -0.5; +static double centerY = 0.0; +static double scale = 3.0 / WIDTH; + +static int dragging = 0; +static int lastX, lastY; + +static int numThreads = std::thread::hardware_concurrency(); + +static void render_tile(int yStart, int yEnd) +{ + __m256d two = _mm256_set1_pd(2.0); + __m256d four = _mm256_set1_pd(4.0); + + for (int y = yStart; y < yEnd; y++) + { + double ci_scalar = centerY + (y - HEIGHT / 2.0) * scale; + __m256d ci = _mm256_set1_pd(ci_scalar); + + for (int x = 0; x < WIDTH; x += 4) + { + __m256d cr = _mm256_set_pd( + centerX + (x + 3 - WIDTH / 2.0) * scale, + centerX + (x + 2 - WIDTH / 2.0) * scale, + centerX + (x + 1 - WIDTH / 2.0) * scale, + centerX + (x + 0 - WIDTH / 2.0) * scale + ); + + __m256d zr = _mm256_setzero_pd(); + __m256d zi = _mm256_setzero_pd(); + + int iter[4] = { 0,0,0,0 }; + + for (int i = 0; i < MAX_ITER; i++) + { + __m256d zr2 = _mm256_mul_pd(zr, zr); + __m256d zi2 = _mm256_mul_pd(zi, zi); + __m256d mag = _mm256_add_pd(zr2, zi2); + + __m256d mask = _mm256_cmp_pd(mag, four, _CMP_LT_OS); + if (_mm256_movemask_pd(mask) == 0) + break; + + __m256d zrzi = _mm256_mul_pd(zr, zi); + + zi = _mm256_add_pd(_mm256_mul_pd(two, zrzi), ci); + zr = _mm256_add_pd(_mm256_sub_pd(zr2, zi2), cr); + + for (int k = 0; k < 4; k++) + if (iter[k] < MAX_ITER) + iter[k]++; + } + + for (int k = 0; k < 4; k++) + { + double smooth = iter[k]; + if (iter[k] < MAX_ITER) + { + double zr_s = ((double*)&zr)[k]; + double zi_s = ((double*)&zi)[k]; + double mag = sqrt(zr_s * zr_s + zi_s * zi_s); + smooth = iter[k] + 1 - log2(log2(mag)); + } + + uint8_t c = (uint8_t)(255.0 * smooth / MAX_ITER); + framebuffer[y * WIDTH + x + k] = + (c << 16) | (c << 8) | c; + } + } + } +} + +static void render_mandelbrot() +{ + std::vector threads; + + int tile = HEIGHT / numThreads; + + for (int i = 0; i < numThreads; i++) + { + int yStart = i * tile; + int yEnd = (i == numThreads - 1) ? HEIGHT : yStart + tile; + threads.emplace_back(render_tile, yStart, yEnd); + } + + for (auto& t : threads) + t.join(); +} + +LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_MOUSEWHEEL: + { + int delta = GET_WHEEL_DELTA_WPARAM(wParam); + scale *= (delta > 0) ? 0.8 : 1.25; + render_mandelbrot(); + InvalidateRect(hwnd, NULL, FALSE); + break; + } + + case WM_LBUTTONDOWN: + dragging = 1; + lastX = LOWORD(lParam); + lastY = HIWORD(lParam); + break; + + case WM_MOUSEMOVE: + if (dragging) + { + int x = LOWORD(lParam); + int y = HIWORD(lParam); + + centerX -= (x - lastX) * scale; + centerY -= (y - lastY) * scale; + + lastX = x; + lastY = y; + + render_mandelbrot(); + InvalidateRect(hwnd, NULL, FALSE); + } + break; + + case WM_LBUTTONUP: + dragging = 0; + break; + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + BITMAPINFO bmi = {}; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = WIDTH; + bmi.bmiHeader.biHeight = -HEIGHT; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + + StretchDIBits(hdc, + 0, 0, WIDTH, HEIGHT, + 0, 0, WIDTH, HEIGHT, + framebuffer, + &bmi, + DIB_RGB_COLORS, + SRCCOPY); + + EndPaint(hwnd, &ps); + break; + } + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return 0; +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) +{ + render_mandelbrot(); + + WNDCLASS wc = {}; + wc.lpfnWndProc = WndProc; + wc.hInstance = hInstance; + wc.lpszClassName = "MandelbrotSIMD"; + + RegisterClass(&wc); + + HWND hwnd = CreateWindowEx( + 0, + "MandelbrotSIMD", + "Mandelbrot Explorer (SIMD + Threads)", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, + WIDTH, HEIGHT, + NULL, NULL, hInstance, NULL); + + ShowWindow(hwnd, nCmdShow); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return 0; +} \ No newline at end of file diff --git a/simulations/donut.c/donutdbg.debugtarget b/simulations/donut.c/donutdbg.debugtarget index dcfcb37..2f75280 100644 --- a/simulations/donut.c/donutdbg.debugtarget +++ b/simulations/donut.c/donutdbg.debugtarget @@ -9,5 +9,14 @@ + + \ No newline at end of file diff --git a/simulations/mandelbrotset/wikipedia.py b/simulations/mandelbrotset/wikipedia.py new file mode 100644 index 0000000..f05b3ce --- /dev/null +++ b/simulations/mandelbrotset/wikipedia.py @@ -0,0 +1,41 @@ +import numpy as np +import matplotlib.pyplot as plt + +# Setting parameters (these values can be changed) +x_domain, y_domain = np.linspace(-2, 2, 500), np.linspace(-2, 2, 500) +bound = 2 +max_iterations = 50 # any positive integer value +colormap = "nipy_spectral" # set to any matplotlib valid colormap + +func = lambda z, p, c: z**p + c + +# Computing 2D array to represent the Mandelbrot set +iteration_array = [] +for y in y_domain: + row = [] + for x in x_domain: + z = 0 + p = 2 + c = complex(x, y) + for iteration_number in range(max_iterations): + if abs(z) >= bound: + row.append(iteration_number) + break + else: + try: + z = func(z, p, c) + except (ValueError, ZeroDivisionError): + z = c + else: + row.append(0) + + iteration_array.append(row) + +# Plotting the data +ax = plt.axes() +ax.set_aspect("equal") +graph = ax.pcolormesh(x_domain, y_domain, iteration_array, cmap=colormap) +plt.colorbar(graph) +plt.xlabel("Real-Axis") +plt.ylabel("Imaginary-Axis") +plt.show() \ No newline at end of file diff --git a/turtle/star.py b/turtle/star.py new file mode 100644 index 0000000..0fea5b9 --- /dev/null +++ b/turtle/star.py @@ -0,0 +1,100 @@ +import tkinter as tk +import turtle +import math + +# ---------- Tk setup ---------- +root = tk.Tk() +root.title("Turtle Function Inspector") + +# ---------- Canvas ---------- +canvas = tk.Canvas(root, width=600, height=600) +canvas.grid(row=0, column=0, rowspan=6) + +screen = turtle.TurtleScreen(canvas) +screen.setworldcoordinates(-300, -300, 300, 300) + +t = turtle.RawTurtle(screen) +t.speed(0) +t.hideturtle() + +# ---------- Globals ---------- +scale = 40 # zoom level + +# ---------- Drawing ---------- +def draw_axes(): + t.clear() + t.color("black") + t.penup() + t.goto(-300, 0) + t.pendown() + t.goto(300, 0) + + t.penup() + t.goto(0, -300) + t.pendown() + t.goto(0, 300) + +def plot_function(): + draw_axes() + expr = func_entry.get() + + t.color("blue") + t.penup() + + first = True + for px in range(-300, 300): + try: + x = px / scale + y = eval(expr, {"x": x, "math": math}) + py = y * scale + + if abs(py) > 300: + raise ValueError + + if first: + t.goto(px, py) + t.pendown() + first = False + else: + t.goto(px, py) + except: + t.penup() + first = True + +# ---------- Zoom ---------- +def zoom_in(): + global scale + scale *= 1.25 + plot_function() + +def zoom_out(): + global scale + scale /= 1.25 + plot_function() + +# ---------- Mouse inspection ---------- +info = tk.Label(root, text="x=0 y=0") +info.grid(row=5, column=1) + +def inspect(event): + x = (event.x - 300) / scale + try: + y = eval(func_entry.get(), {"x": x, "math": math}) + info.config(text=f"x={x:.3f} y={y:.3f}") + except: + info.config(text="undefined") + +canvas.bind("", inspect) + +# ---------- Controls ---------- +tk.Label(root, text="f(x) =").grid(row=0, column=1) +func_entry = tk.Entry(root, width=20) +func_entry.insert(0, "math.sin(x)") +func_entry.grid(row=1, column=1) + +tk.Button(root, text="Plot", command=plot_function).grid(row=2, column=1) +tk.Button(root, text="Zoom +", command=zoom_in).grid(row=3, column=1) +tk.Button(root, text="Zoom -", command=zoom_out).grid(row=4, column=1) + +plot_function() +root.mainloop()