From: Yunsup Lee Date: Tue, 30 Apr 2013 01:44:21 +0000 (-0700) Subject: benchmarks initial commit X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=23507d668862dff15a898f20e109a46c6e95780d;p=riscv-tests.git benchmarks initial commit --- diff --git a/benchmarks/Makefile b/benchmarks/Makefile new file mode 100644 index 0000000..a0ce377 --- /dev/null +++ b/benchmarks/Makefile @@ -0,0 +1,144 @@ +#======================================================================= +# UCB VLSI FLOW: Makefile for riscv-bmarks +#----------------------------------------------------------------------- +# Yunsup Lee (yunsup@cs.berkeley.edu) +# + +default: all + +bmarkdir = . + +instname = riscv-bmarks +instbasedir = $(UCB_VLSI_HOME)/install + +#-------------------------------------------------------------------- +# Sources +#-------------------------------------------------------------------- + +bmarks = \ + median \ + qsort \ + towers \ + vvadd \ + multiply \ + dgemm \ + dhrystone \ + spmv \ + vec-vvadd \ + vec-cmplxmult \ + vec-matmul \ + mt-vvadd \ + mt-matmul \ + +bmarks_host = \ + median \ + qsort \ + towers \ + vvadd \ + multiply \ + dgemm \ + spmv \ + vec-vvadd \ + vec-cmplxmult \ + vec-matmul \ + +#-------------------------------------------------------------------- +# Build rules +#-------------------------------------------------------------------- + +HOST_OPTS = -std=gnu99 -DPREALLOCATE=0 -DHOST_DEBUG=1 +HOST_COMP = gcc $(HOST_OPTS) + +RISCV_GCC = riscv-gcc +RISCV_GCC_OPTS = -std=gnu99 -DSET_STATS -O2 -nostdlib -nostartfiles -ffast-math +RISCV_LINK = riscv-gcc -T $(bmarkdir)/common/test.ld +RISCV_LINK_MT = riscv-gcc -T $(bmarkdir)/common/test-mt.ld +RISCV_LINK_OPTS = -lc +RISCV_LINK_SYSCALL = $(bmarkdir)/common/syscalls.c -lc +RISCV_OBJDUMP = riscv-objdump --disassemble-all --disassemble-zeroes --section=.text --section=.text.startup --section=.data +RISCV_SIM = riscv-isa-run + +VPATH += $(addprefix $(bmarkdir)/, $(bmarks)) +VPATH += $(bmarkdir)/common + +incs += -I. -I./common $(addprefix -I$(bmarkdir)/, $(bmarks)) +objs := + +include $(patsubst %, $(bmarkdir)/%/bmark.mk, $(bmarks)) + +#------------------------------------------------------------ +# Build and run benchmarks on riscv simulator + +bmarks_riscv_bin = $(addsuffix .riscv, $(bmarks)) +bmarks_riscv_dump = $(addsuffix .riscv.dump, $(bmarks)) +bmarks_riscv_hex = $(addsuffix .riscv.hex, $(bmarks)) +bmarks_riscv_out = $(addsuffix .riscv.out, $(bmarks)) + +bmarks_defs = -DPREALLOCATE=1 -DHOST_DEBUG=0 +bmarks_cycles = 80000 + +%.hex: % + elf2hex 16 32768 $< > $@ + +$(bmarks_riscv_dump): %.riscv.dump: %.riscv + $(RISCV_OBJDUMP) $< > $@ + +$(bmarks_riscv_out): %.riscv.out: %.riscv + $(RISCV_SIM) $< > $@ + +%.o: %.c + $(RISCV_GCC) $(RISCV_GCC_OPTS) $(bmarks_defs) \ + -c $(incs) $< -o $@ + +%.o: %.S + $(RISCV_GCC) $(RISCV_GCC_OPTS) $(bmarks_defs) \ + -c $(incs) $< -o $@ + +riscv: $(bmarks_riscv_dump) $(bmarks_riscv_hex) +run-riscv: $(bmarks_riscv_out) + echo; perl -ne 'print " [$$1] $$ARGV \t$$2\n" if /\*{3}(.{8})\*{3}(.*)/' \ + $(bmarks_riscv_out); echo; + +junk += $(bmarks_riscv_bin) $(bmarks_riscv_dump) $(bmarks_riscv_hex) $(bmarks_riscv_out) + +#------------------------------------------------------------ +# Build and run benchmarks on host machine + +bmarks_host_bin = $(addsuffix .host, $(bmarks_host)) +bmarks_host_out = $(addsuffix .host.out, $(bmarks_host)) + +$(bmarks_host_out): %.host.out: %.host + ./$< > $@ + +host: $(bmarks_host_bin) +run-host: $(bmarks_host_out) + echo; perl -ne 'print " [$$1] $$ARGV \t$$2\n" if /\*{3}(.{8})\*{3}(.*)/' \ + $(bmarks_host_out); echo; + +junk += $(bmarks_host_bin) $(bmarks_host_out) + +#------------------------------------------------------------ +# Default + +all: riscv + +#------------------------------------------------------------ +# Install + +date_suffix = $(shell date +%Y-%m-%d_%H-%M) +install_dir = $(instbasedir)/$(instname)-$(date_suffix) +latest_install = $(shell ls -1 -d $(instbasedir)/$(instname)* | tail -n 1) + +install: + mkdir $(install_dir) + cp -r $(bmarks_riscv_bin) $(bmarks_riscv_dump) $(install_dir) + +install-link: + rm -rf $(instbasedir)/$(instname) + ln -s $(latest_install) $(instbasedir)/$(instname) + +#------------------------------------------------------------ +# Clean up + +clean: + rm -rf $(objs) $(junk) diff --git a/benchmarks/common/crt-mt.S b/benchmarks/common/crt-mt.S new file mode 100644 index 0000000..283b3bf --- /dev/null +++ b/benchmarks/common/crt-mt.S @@ -0,0 +1,116 @@ + .data + .globl _heapend + .globl environ +_heapend: + .word 0 +environ: + .word 0 + + .text + .globl _start + +_start: + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10,0 + li x11,0 + li x12,0 + li x13,0 + li x14,0 + li x15,0 + li x16,0 + li x17,0 + li x18,0 + li x19,0 + li x20,0 + li x21,0 + li x22,0 + li x23,0 + li x24,0 + li x25,0 + li x26,0 + li x27,0 + li x28,0 + li x29,0 + li x30,0 + li x31,0 + + # enable fp + mfpcr x1,cr0 + ori x1,x1,0x2 + mtpcr x1,cr0 + + # enable vec + mfpcr x1,cr0 + ori x1,x1,0x4 + mtpcr x1,cr0 + + ## if that didn't stick, we don't have an FPU, so don't initialize it + mfpcr x1,cr0 + andi x1,x1,0x2 + beqz x1,1f + + mtfsr x0 + mxtf.s f0, x0 + mxtf.s f1, x0 + mxtf.s f2, x0 + mxtf.s f3, x0 + mxtf.s f4, x0 + mxtf.s f5, x0 + mxtf.s f6, x0 + mxtf.s f7, x0 + mxtf.s f8, x0 + mxtf.s f9, x0 + mxtf.s f10,x0 + mxtf.s f11,x0 + mxtf.s f12,x0 + mxtf.s f13,x0 + mxtf.s f14,x0 + mxtf.s f15,x0 + mxtf.s f16,x0 + mxtf.s f17,x0 + mxtf.s f18,x0 + mxtf.s f19,x0 + mxtf.s f20,x0 + mxtf.s f21,x0 + mxtf.s f22,x0 + mxtf.s f23,x0 + mxtf.s f24,x0 + mxtf.s f25,x0 + mxtf.s f26,x0 + mxtf.s f27,x0 + mxtf.s f28,x0 + mxtf.s f29,x0 + mxtf.s f30,x0 + mxtf.s f31,x0 +1: + + # get core id and number of cores + mfpcr a0,cr10 + lw a1, 4(zero) + + slli a2, a0, 13 + la sp, stacktop + sub sp, sp, a2 + + la tp, tlstop + sub tp, tp, a2 + + jal thread_entry + + .bss + .globl stacktop + .globl tlstop + + .align 4 + .skip 32768 +stacktop: + .skip 65536 +tlstop: diff --git a/benchmarks/common/crt.S b/benchmarks/common/crt.S new file mode 100644 index 0000000..d153210 --- /dev/null +++ b/benchmarks/common/crt.S @@ -0,0 +1,108 @@ + .data + .globl _heapend + .globl environ +_heapend: + .word 0 +environ: + .word 0 + + .text + .globl _start + +_start: + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10,0 + li x11,0 + li x12,0 + li x13,0 + li x14,0 + li x15,0 + li x16,0 + li x17,0 + li x18,0 + li x19,0 + li x20,0 + li x21,0 + li x22,0 + li x23,0 + li x24,0 + li x25,0 + li x26,0 + li x27,0 + li x28,0 + li x29,0 + li x30,0 + li x31,0 + + # enable fp + mfpcr x1,cr0 + ori x1,x1,0x2 + mtpcr x1,cr0 + + # enable vec + mfpcr x1,cr0 + ori x1,x1,0x4 + mtpcr x1,cr0 + + ## if that didn't stick, we don't have an FPU, so don't initialize it + mfpcr x1,cr0 + andi x1,x1,0x2 + beqz x1,1f + + mtfsr x0 + mxtf.s f0, x0 + mxtf.s f1, x0 + mxtf.s f2, x0 + mxtf.s f3, x0 + mxtf.s f4, x0 + mxtf.s f5, x0 + mxtf.s f6, x0 + mxtf.s f7, x0 + mxtf.s f8, x0 + mxtf.s f9, x0 + mxtf.s f10,x0 + mxtf.s f11,x0 + mxtf.s f12,x0 + mxtf.s f13,x0 + mxtf.s f14,x0 + mxtf.s f15,x0 + mxtf.s f16,x0 + mxtf.s f17,x0 + mxtf.s f18,x0 + mxtf.s f19,x0 + mxtf.s f20,x0 + mxtf.s f21,x0 + mxtf.s f22,x0 + mxtf.s f23,x0 + mxtf.s f24,x0 + mxtf.s f25,x0 + mxtf.s f26,x0 + mxtf.s f27,x0 + mxtf.s f28,x0 + mxtf.s f29,x0 + mxtf.s f30,x0 + mxtf.s f31,x0 +1: + + # only allow core 0 to proceed +1:mfpcr a0, cr10 + bnez a0, 1b + + la sp,stacktop + jal main +1:b 1b + + .bss + .globl stacktop + + .align 4 + .skip 131072 +stacktop: diff --git a/benchmarks/common/pcr.h b/benchmarks/common/pcr.h new file mode 100644 index 0000000..7659a97 --- /dev/null +++ b/benchmarks/common/pcr.h @@ -0,0 +1,90 @@ +#ifndef _RISCV_PCR_H +#define _RISCV_PCR_H + +#define SR_ET 0x00000001 +#define SR_EF 0x00000002 +#define SR_EV 0x00000004 +#define SR_EC 0x00000008 +#define SR_PS 0x00000010 +#define SR_S 0x00000020 +#define SR_U64 0x00000040 +#define SR_S64 0x00000080 +#define SR_VM 0x00000100 +#define SR_IM 0x00FF0000 +#define SR_ZERO ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM) +#define SR_IM_SHIFT 16 + +#define PCR_SR 0 +#define PCR_EPC 1 +#define PCR_BADVADDR 2 +#define PCR_EVEC 3 +#define PCR_COUNT 4 +#define PCR_COMPARE 5 +#define PCR_CAUSE 6 +#define PCR_PTBR 7 +#define PCR_SEND_IPI 8 +#define PCR_CLR_IPI 9 +#define PCR_COREID 10 +#define PCR_IMPL 11 +#define PCR_K0 12 +#define PCR_K1 13 +#define PCR_VECBANK 18 +#define PCR_VECCFG 19 +#define PCR_RESET 29 +#define PCR_TOHOST 30 +#define PCR_FROMHOST 31 + +#define IRQ_IPI 5 +#define IRQ_TIMER 7 + +#define CAUSE_MISALIGNED_FETCH 0 +#define CAUSE_FAULT_FETCH 1 +#define CAUSE_ILLEGAL_INSTRUCTION 2 +#define CAUSE_PRIVILEGED_INSTRUCTION 3 +#define CAUSE_FP_DISABLED 4 +#define CAUSE_SYSCALL 6 +#define CAUSE_BREAKPOINT 7 +#define CAUSE_MISALIGNED_LOAD 8 +#define CAUSE_MISALIGNED_STORE 9 +#define CAUSE_FAULT_LOAD 10 +#define CAUSE_FAULT_STORE 11 +#define CAUSE_VECTOR_DISABLED 12 +#define CAUSE_VECTOR_BANK 13 + +#define CAUSE_VECTOR_MISALIGNED_FETCH 24 +#define CAUSE_VECTOR_FAULT_FETCH 25 +#define CAUSE_VECTOR_ILLEGAL_INSTRUCTION 26 +#define CAUSE_VECTOR_ILLEGAL_COMMAND 27 +#define CAUSE_VECTOR_MISALIGNED_LOAD 28 +#define CAUSE_VECTOR_MISALIGNED_STORE 29 +#define CAUSE_VECTOR_FAULT_LOAD 30 +#define CAUSE_VECTOR_FAULT_STORE 31 + +#ifdef __riscv + +#define ASM_CR(r) _ASM_CR(r) +#define _ASM_CR(r) cr##r + +#ifndef __ASSEMBLER__ + +#define mtpcr(reg,val) ({ long __tmp = (long)(val), __tmp2; \ + asm volatile ("mtpcr %0,%1,cr%2" : "=r"(__tmp2) : "r"(__tmp),"i"(reg)); \ + __tmp2; }) + +#define mfpcr(reg) ({ long __tmp; \ + asm volatile ("mfpcr %0,cr%1" : "=r"(__tmp) : "i"(reg)); \ + __tmp; }) + +#define setpcr(reg,val) ({ long __tmp; \ + asm volatile ("setpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \ + __tmp; }) + +#define clearpcr(reg,val) ({ long __tmp; \ + asm volatile ("clearpcr %0,cr%2,%1" : "=r"(__tmp) : "i"(val), "i"(reg)); \ + __tmp; }) + +#endif + +#endif + +#endif diff --git a/benchmarks/common/syscalls.S b/benchmarks/common/syscalls.S new file mode 100644 index 0000000..a0cdf6e --- /dev/null +++ b/benchmarks/common/syscalls.S @@ -0,0 +1,678 @@ + .file 1 "syscalls.c" + .section .mdebug.abi64 + .previous + .section .rodata.str1.8,"aMS",@progbits,1 + .align 3 +$LC0: + .ascii "0123456789abcdef\000" + .text + .align 2 + .ent printnum + .type printnum, @function +printnum: + .frame x30,64,x1 # vars= 0, regs= 7/0, args= 0 + .mask 0x03f00002,-8 + .fmask 0x00000000,0 + add x30,x30,-64 + sd x22,32(x30) + sll x22,x7,32 + srl x22,x22,32 + sd x24,48(x30) + sd x23,40(x30) + sd x21,24(x30) + sd x20,16(x30) + sd x25,56(x30) + sd x1,8(x30) + move x23,x6 + move x20,x4 + move x21,x5 + move x24,x9 + bleu x22,x6,$L2 + addw x8,x8,-1 + move x25,x8 + ble x8,x0,$L4 +$L6: + addw x25,x25,-1 + move x4,x24 + move x5,x21 + jalr x20 + bne x25,x0,$L6 +$L4: + lui x2,%hi($LC0) + add x2,x2,%lo($LC0) + remu x22,x23,x22 + add x22,x22,x2 + lb x4,0(x22) + move x5,x21 + move x19,x20 + ld x25,56(x30) + ld x24,48(x30) + ld x23,40(x30) + ld x22,32(x30) + ld x21,24(x30) + ld x20,16(x30) + ld x1,8(x30) + add x30,x30,64 + jr x19 +$L2: + addw x8,x8,-1 + divu x6,x6,x22 + jal printnum + j $L4 + .end printnum + .size printnum, .-printnum + .align 2 + .ent getuint + .type getuint, @function +getuint: + .frame x30,0,x1 # vars= 0, regs= 0/0, args= 0 + .mask 0x00000000,0 + .fmask 0x00000000,0 + slt x2,x5,2 + bne x2,x0,$L10 +$L13: + ld x2,0(x4) + add x3,x2,8 + sd x3,0(x4) + ld x2,0(x2) + ret +$L10: + bne x5,x0,$L13 + ld x3,0(x4) + lwu x2,0(x3) + add x3,x3,8 + sd x3,0(x4) + ret + .end getuint + .size getuint, .-getuint + .align 2 + .globl putchar + .ent putchar + .type putchar, @function +putchar: + .frame x30,64,x1 # vars= 64, regs= 0/0, args= 0 + .mask 0x00000000,0 + .fmask 0x00000000,0 + li x2,-1 # 0xffffffffffffffff + add x30,x30,-64 + lui x3,%hi(buflen.1596) + beq x4,x2,$L21 + lw x5,%lo(buflen.1596)(x3) + lui x2,%hi(buf.1595) + add x2,x2,%lo(buf.1595) + add x6,x2,x5 + sb x4,0(x6) + addw x5,x5,1 + li x4,64 # 0x40 + sw x5,%lo(buflen.1596)(x3) + beq x5,x4,$L15 + move x2,x0 + add x30,x30,64 + j x1 +$L21: + lui x2,%hi(buf.1595) + add x2,x2,%lo(buf.1595) +$L15: + lw x4,%lo(buflen.1596)(x3) + li x5,4 # 0x4 + sd x0,0(x30) + sd x0,8(x30) + sd x0,16(x30) + sd x0,24(x30) + sd x0,32(x30) + sd x0,40(x30) + sd x0,48(x30) + sd x0,56(x30) + sd x5,0(x30) + li x5,1 # 0x1 + sd x5,8(x30) + sd x2,16(x30) + sd x4,24(x30) + fence + #APP + # 45 "syscalls.c" 1 + mtpcr x2,x30,cr30 + # 0 "" 2 + #NO_APP +$L17: + #APP + # 46 "syscalls.c" 1 + mfpcr x2,cr31 + # 0 "" 2 + #NO_APP + beq x2,x0,$L17 + move x2,x0 + sw x0,%lo(buflen.1596)(x3) + add x30,x30,64 + j x1 + .end putchar + .size putchar, .-putchar + .align 2 + .globl exit + .ent exit + .type exit, @function +exit: + .frame x30,64,x1 # vars= 64, regs= 0/0, args= 0 + .mask 0x00000000,0 + .fmask 0x00000000,0 + add x30,x30,-64 + li x2,1 # 0x1 + sd x0,0(x30) + sd x0,8(x30) + sd x0,16(x30) + sd x0,24(x30) + sd x0,32(x30) + sd x0,40(x30) + sd x0,48(x30) + sd x0,56(x30) + sd x2,0(x30) + sd x4,8(x30) + fence + #APP + # 12 "syscalls.c" 1 + mtpcr x2,x30,cr30 + # 0 "" 2 + #NO_APP +$L23: + j $L23 + .end exit + .size exit, .-exit + .align 2 + .globl printstr + .ent printstr + .type printstr, @function +printstr: + .frame x30,80,x1 # vars= 64, regs= 1/0, args= 0 + .mask 0x00000002,-8 + .fmask 0x00000000,0 + add x30,x30,-80 + li x3,4 # 0x4 + sd x0,0(x30) + sd x0,8(x30) + sd x0,16(x30) + sd x0,24(x30) + sd x0,32(x30) + sd x0,40(x30) + sd x0,48(x30) + sd x0,56(x30) + sd x3,0(x30) + li x3,1 # 0x1 + sd x3,8(x30) + sd x1,72(x30) + sd x4,16(x30) + jal strlen + sd x2,24(x30) + fence + #APP + # 24 "syscalls.c" 1 + mtpcr x2,x30,cr30 + # 0 "" 2 + #NO_APP +$L25: + #APP + # 25 "syscalls.c" 1 + mfpcr x2,cr31 + # 0 "" 2 + #NO_APP + beq x2,x0,$L25 + ld x1,72(x30) + add x30,x30,80 + j x1 + .end printstr + .size printstr, .-printstr + .align 2 + .globl printhex + .ent printhex + .type printhex, @function +printhex: + .frame x30,48,x1 # vars= 32, regs= 1/0, args= 0 + .mask 0x00000002,-8 + .fmask 0x00000000,0 + add x30,x30,-48 + sd x1,40(x30) + add x2,x30,15 + add x7,x30,-1 +$L29: + and x3,x4,15 + sltu x6,x3,10 + li x5,87 # 0x57 + beq x6,x0,$L28 + li x5,48 # 0x30 +$L28: + add x3,x5,x3 + sb x3,0(x2) + add x2,x2,-1 + srl x4,x4,4 + bne x2,x7,$L29 + move x4,x30 + sb x0,16(x30) + jal printstr + ld x1,40(x30) + add x30,x30,48 + j x1 + .end printhex + .size printhex, .-printhex + .section .rodata.str1.8 + .align 3 +$LC1: + .ascii "(null)\000" + .text + .align 2 + .globl vprintfmt + .ent vprintfmt + .type vprintfmt, @function +vprintfmt: + .frame x30,112,x1 # vars= 32, regs= 10/0, args= 0 + .mask 0x2ff00002,-8 + .fmask 0x00000000,0 + add x30,x30,-112 + sd x25,80(x30) + lui x25,%hi($L53) + sd x26,88(x30) + sd x24,72(x30) + sd x23,64(x30) + sd x22,56(x30) + sd x21,48(x30) + sd x20,40(x30) + sd x29,104(x30) + sd x27,96(x30) + sd x1,32(x30) + move x21,x4 + move x20,x5 + move x23,x6 + sd x7,0(x30) + li x22,37 # 0x25 + add x25,x25,%lo($L53) + li x24,-1 # 0xffffffffffffffff + lui x26,%hi($LC1) + j $L84 +$L35: + beq x2,x0,$L32 + move x5,x20 + add x23,x23,1 + jalr x21 +$L84: + lbu x4,0(x23) + move x2,x4 + bne x4,x22,$L35 + ld x2,0(x30) + add x6,x23,1 + move x7,x6 + li x27,32 # 0x20 + sd x0,8(x30) + li x3,-1 # 0xffffffffffffffff + li x29,-1 # 0xffffffffffffffff + move x5,x0 +$L85: + lbu x4,0(x7) + add x23,x7,1 + addw x8,x4,-35 + and x9,x8,0xff + sltu x9,x9,86 + bne x9,x0,$L90 +$L38: + li x4,37 # 0x25 + move x5,x20 + sd x2,0(x30) + move x23,x6 + jalr x21 + j $L84 +$L32: + ld x1,32(x30) + ld x29,104(x30) + ld x27,96(x30) + ld x26,88(x30) + ld x25,80(x30) + ld x24,72(x30) + ld x23,64(x30) + ld x22,56(x30) + ld x21,48(x30) + ld x20,40(x30) + add x30,x30,112 + j x1 +$L90: + and x8,x8,0xff + sll x8,x8,3 + add x8,x25,x8 + ld x8,0(x8) + j x8 + .section .rodata + .align 3 + .align 2 +$L53: + .dword $L39 + .dword $L38 + .dword $L40 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L41 + .dword $L38 + .dword $L38 + .dword $L42 + .dword $L43 + .dword $L38 + .dword $L74 + .dword $L44 + .dword $L44 + .dword $L44 + .dword $L44 + .dword $L44 + .dword $L44 + .dword $L44 + .dword $L44 + .dword $L44 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L45 + .dword $L46 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L38 + .dword $L47 + .dword $L38 + .dword $L38 + .dword $L48 + .dword $L49 + .dword $L38 + .dword $L38 + .dword $L50 + .dword $L38 + .dword $L51 + .dword $L38 + .dword $L38 + .dword $L52 + .text +$L52: + move x4,x30 + sd x2,0(x30) + jal getuint + move x6,x2 + li x7,16 # 0x10 +$L73: + move x4,x21 + move x5,x20 + move x8,x29 + move x9,x27 + jal printnum + j $L84 +$L39: + li x4,1 # 0x1 + move x7,x23 + sd x4,8(x30) + j $L85 +$L40: + move x5,x20 + sd x2,0(x30) + jalr x21 + j $L84 +$L41: + lw x3,0(x2) + move x7,x23 + add x2,x2,8 +$L54: + bge x29,x0,$L85 + move x29,x3 + li x3,-1 # 0xffffffffffffffff + j $L85 +$L42: + move x7,x23 + li x27,45 # 0x2d + j $L85 +$L43: + blt x29,x0,$L91 + move x7,x23 + j $L85 +$L74: + move x7,x23 + li x27,48 # 0x30 + j $L85 +$L44: + lb x8,1(x7) + addw x3,x4,-48 + move x7,x23 + addw x4,x8,-48 + sltu x4,x4,10 + beq x4,x0,$L54 +$L55: + add x7,x7,1 + lb x4,0(x7) + sllw x9,x3,1 + sllw x3,x3,3 + addw x3,x9,x3 + addw x9,x4,-48 + addw x3,x3,x8 + sltu x9,x9,10 + addw x3,x3,-48 + move x8,x4 + bne x9,x0,$L55 + j $L54 +$L45: + lw x4,0(x2) + add x2,x2,8 + move x5,x20 + sd x2,0(x30) + jalr x21 + j $L84 +$L46: + slt x3,x5,2 + bne x3,x0,$L69 +$L88: + add x3,x2,8 + sd x3,0(x30) + ld x6,0(x2) + blt x6,x0,$L72 +$L89: + li x7,10 # 0xa + j $L73 +$L47: + addw x5,x5,1 + move x7,x23 + j $L85 +$L48: + move x4,x30 + sd x2,0(x30) + jal getuint + move x6,x2 + li x7,8 # 0x8 + j $L73 +$L49: + sd x2,0(x30) + li x4,48 # 0x30 + move x5,x20 + jalr x21 + li x4,120 # 0x78 + move x5,x20 + jalr x21 + ld x2,0(x30) + li x7,16 # 0x10 + add x3,x2,8 + sd x3,0(x30) + ld x6,0(x2) + j $L73 +$L50: + add x4,x2,8 + sd x4,0(x30) + ld x2,0(x2) + sd x2,16(x30) + beq x2,x0,$L92 +$L58: + ble x29,x0,$L59 + li x2,45 # 0x2d + beq x27,x2,$L59 + ld x4,16(x30) + move x5,x3 + sd x3,24(x30) + jal strnlen + sllw x2,x2,0 + subw x2,x29,x2 + move x29,x2 + ld x3,24(x30) + ble x2,x0,$L59 + move x29,x2 +$L60: + sd x3,24(x30) + move x4,x27 + move x5,x20 + addw x29,x29,-1 + jalr x21 + ld x3,24(x30) + bne x29,x0,$L60 +$L59: + ld x2,16(x30) + lb x4,0(x2) + add x27,x2,1 + beq x4,x0,$L62 +$L80: + blt x3,x0,$L67 + addw x2,x3,-1 + move x3,x2 + beq x2,x24,$L62 +$L67: + ld x2,8(x30) + beq x2,x0,$L63 + addw x2,x4,-32 + sltu x2,x2,95 + beq x2,x0,$L93 +$L63: + sd x3,24(x30) + move x5,x20 + jalr x21 + ld x3,24(x30) +$L64: + lb x4,0(x27) + addw x29,x29,-1 + add x27,x27,1 + bne x4,x0,$L80 +$L62: + ble x29,x0,$L84 +$L79: + addw x29,x29,-1 + li x4,32 # 0x20 + move x5,x20 + jalr x21 + bne x29,x0,$L79 + j $L84 +$L51: + move x4,x30 + sd x2,0(x30) + jal getuint + move x6,x2 + li x7,10 # 0xa + j $L73 +$L93: + sd x3,24(x30) + li x4,63 # 0x3f + move x5,x20 + jalr x21 + ld x3,24(x30) + j $L64 +$L91: + move x7,x23 + move x29,x0 + j $L85 +$L92: + add x2,x26,%lo($LC1) + sd x2,16(x30) + j $L58 +$L72: + sd x6,24(x30) + li x4,45 # 0x2d + move x5,x20 + jalr x21 + ld x6,24(x30) + li x7,10 # 0xa + sub x6,zero,x6 + j $L73 +$L69: + bne x5,x0,$L88 + lw x6,0(x2) + add x2,x2,8 + sd x2,0(x30) + bge x6,x0,$L89 + j $L72 + .end vprintfmt + .size vprintfmt, .-vprintfmt + .align 2 + .globl printf + .ent printf + .type printf, @function +printf: + .frame x30,96,x1 # vars= 16, regs= 1/0, args= 0 + .mask 0x00000002,-72 + .fmask 0x00000000,0 + add x30,x30,-96 + add x2,x30,40 + move x3,x4 + lui x4,%hi(putchar) + sd x5,40(x30) + sd x6,48(x30) + sd x7,56(x30) + add x4,x4,%lo(putchar) + move x5,x0 + move x6,x3 + move x7,x2 + sd x1,24(x30) + sd x8,64(x30) + sd x9,72(x30) + sd x10,80(x30) + sd x11,88(x30) + sd x2,0(x30) + jal vprintfmt + li x4,-1 # 0xffffffffffffffff + jal putchar + ld x1,24(x30) + move x2,x0 + add x30,x30,96 + j x1 + .end printf + .size printf, .-printf + .local buflen.1596 + .comm buflen.1596,4,4 + .local buf.1595 + .comm buf.1595,64,8 + .ident "GCC: (GNU) 4.6.1" diff --git a/benchmarks/common/syscalls.c b/benchmarks/common/syscalls.c new file mode 100644 index 0000000..f95dde4 --- /dev/null +++ b/benchmarks/common/syscalls.c @@ -0,0 +1,265 @@ +#include +#include +#include +#include "pcr.h" + +void exit(int code) +{ + volatile uint64_t magic_mem[8] = {0}; + magic_mem[0] = 1; + magic_mem[1] = code; + __sync_synchronize(); + mtpcr(PCR_TOHOST, (long)magic_mem); + while(1); +} + +void printstr(const char* s) +{ + volatile uint64_t magic_mem[8] = {0}; + magic_mem[0] = 4; + magic_mem[1] = 1; + magic_mem[2] = (unsigned long)s; + magic_mem[3] = strlen(s); + __sync_synchronize(); + mtpcr(PCR_TOHOST, (long)magic_mem); + while(mtpcr(PCR_FROMHOST, 0) == 0); +} + +int putchar(int ch) +{ + #define buffered_putch_bufsize 64 + static char buf[buffered_putch_bufsize]; + static int buflen = 0; + + if(ch != -1) + buf[buflen++] = ch; + + if(ch == -1 || buflen == buffered_putch_bufsize) + { + volatile uint64_t magic_mem[8] = {0}; + magic_mem[0] = 4; + magic_mem[1] = 1; + magic_mem[2] = (long)buf; + magic_mem[3] = buflen; + __sync_synchronize(); + mtpcr(PCR_TOHOST, (long)magic_mem); + while(mtpcr(PCR_FROMHOST, 0) == 0); + + buflen = 0; + } + + return 0; +} + +void printhex(uint64_t x) +{ + char str[17]; + int i; + for (i = 0; i < 16; i++) + { + str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10); + x >>= 4; + } + str[16] = 0; + + printstr(str); +} + +static void printnum(void (*putch)(int, void**), void **putdat, + unsigned long long num, unsigned base, int width, int padc) +{ + if (num >= base) + printnum(putch, putdat, num / base, base, width - 1, padc); + else while (--width > 0) + putch(padc, putdat); + + putch("0123456789abcdef"[num % base], putdat); +} + +static unsigned long long getuint(va_list *ap, int lflag) +{ + if (lflag >= 2) + return va_arg(*ap, unsigned long long); + else if (lflag) + return va_arg(*ap, unsigned long); + else + return va_arg(*ap, unsigned int); +} + +static long long getint(va_list *ap, int lflag) +{ + if (lflag >= 2) + return va_arg(*ap, long long); + else if (lflag) + return va_arg(*ap, long); + else + return va_arg(*ap, int); +} + +void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap) +{ + register const char* p; + const char* last_fmt; + register int ch, err; + unsigned long long num; + int base, lflag, width, precision, altflag; + char padc; + + while (1) { + while ((ch = *(unsigned char *) fmt) != '%') { + if (ch == '\0') + return; + fmt++; + putch(ch, putdat); + } + fmt++; + + // Process a %-escape sequence + last_fmt = fmt; + padc = ' '; + width = -1; + precision = -1; + lflag = 0; + altflag = 0; + reswitch: + switch (ch = *(unsigned char *) fmt++) { + + // flag to pad on the right + case '-': + padc = '-'; + goto reswitch; + + // flag to pad with 0's instead of spaces + case '0': + padc = '0'; + goto reswitch; + + // width field + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + for (precision = 0; ; ++fmt) { + precision = precision * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + break; + } + goto process_precision; + + case '*': + precision = va_arg(ap, int); + goto process_precision; + + case '.': + if (width < 0) + width = 0; + goto reswitch; + + case '#': + altflag = 1; + goto reswitch; + + process_precision: + if (width < 0) + width = precision, precision = -1; + goto reswitch; + + // long flag (doubled for long long) + case 'l': + lflag++; + goto reswitch; + + // character + case 'c': + putch(va_arg(ap, int), putdat); + break; + + // string + case 's': + if ((p = va_arg(ap, char *)) == NULL) + p = "(null)"; + if (width > 0 && padc != '-') + for (width -= strnlen(p, precision); width > 0; width--) + putch(padc, putdat); + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + if (altflag && (ch < ' ' || ch > '~')) + putch('?', putdat); + else + putch(ch, putdat); + p++; + } + for (; width > 0; width--) + putch(' ', putdat); + break; + + // (signed) decimal + case 'd': + num = getint(&ap, lflag); + if ((long long) num < 0) { + putch('-', putdat); + num = -(long long) num; + } + base = 10; + goto number; + + // unsigned decimal + case 'u': + num = getuint(&ap, lflag); + base = 10; + goto number; + + // (unsigned) octal + case 'o': + // should do something with padding so it's always 3 octits + num = getuint(&ap, lflag); + base = 8; + goto number; + + // pointer + case 'p': + putch('0', putdat); + putch('x', putdat); + num = (unsigned long long) + (uintptr_t) va_arg(ap, void *); + base = 16; + goto number; + + // (unsigned) hexadecimal + case 'x': + num = getuint(&ap, lflag); + base = 16; + number: + printnum(putch, putdat, num, base, width, padc); + break; + + // escaped '%' character + case '%': + putch(ch, putdat); + break; + + // unrecognized escape sequence - just print it literally + default: + putch('%', putdat); + fmt = last_fmt; + break; + } + } +} + +int printf(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + vprintfmt((void*)putchar, 0, fmt, ap); + putchar(-1); + + va_end(ap); + return 0; // incorrect return value, but who cares, anyway? +} diff --git a/benchmarks/common/test-mt.ld b/benchmarks/common/test-mt.ld new file mode 100644 index 0000000..5523032 --- /dev/null +++ b/benchmarks/common/test-mt.ld @@ -0,0 +1,45 @@ +/*======================================================================*/ +/* Proxy kernel linker script */ +/*======================================================================*/ +/* This is the linker script used when building the proxy kernel. */ + +/*----------------------------------------------------------------------*/ +/* Setup */ +/*----------------------------------------------------------------------*/ + +/* The OUTPUT_ARCH command specifies the machine architecture where the + argument is one of the names used in the BFD library. More + specifically one of the entires in bfd/cpu-mips.c */ + +OUTPUT_ARCH( "riscv" ) + +/* The ENTRY command specifies the entry point (ie. first instruction + to execute). The symbol _start should be defined in each test. */ + +ENTRY( _start ) + +/*----------------------------------------------------------------------*/ +/* Sections */ +/*----------------------------------------------------------------------*/ + +SECTIONS +{ + + /* text: test code section */ + . = 0x00002000; + .text : + { + crt-mt.o(.text) + *(.text) + } + + /* data: Initialized data segment */ + .data : + { + *(.data) + } + + /* End of uninitalized data segement */ + _end = .; +} + diff --git a/benchmarks/common/test.ld b/benchmarks/common/test.ld new file mode 100644 index 0000000..952bf53 --- /dev/null +++ b/benchmarks/common/test.ld @@ -0,0 +1,45 @@ +/*======================================================================*/ +/* Proxy kernel linker script */ +/*======================================================================*/ +/* This is the linker script used when building the proxy kernel. */ + +/*----------------------------------------------------------------------*/ +/* Setup */ +/*----------------------------------------------------------------------*/ + +/* The OUTPUT_ARCH command specifies the machine architecture where the + argument is one of the names used in the BFD library. More + specifically one of the entires in bfd/cpu-mips.c */ + +OUTPUT_ARCH( "riscv" ) + +/* The ENTRY command specifies the entry point (ie. first instruction + to execute). The symbol _start should be defined in each test. */ + +ENTRY( _start ) + +/*----------------------------------------------------------------------*/ +/* Sections */ +/*----------------------------------------------------------------------*/ + +SECTIONS +{ + + /* text: test code section */ + . = 0x00002000; + .text : + { + crt.o(.text) + *(.text) + } + + /* data: Initialized data segment */ + .data : + { + *(.data) + } + + /* End of uninitalized data segement */ + _end = .; +} + diff --git a/benchmarks/common/util.h b/benchmarks/common/util.h new file mode 100644 index 0000000..83b2b6c --- /dev/null +++ b/benchmarks/common/util.h @@ -0,0 +1,32 @@ +// helpful utility and synch functions + +// relies on defining "ncores" before including this file... + +#ifndef __UTIL_H +#define __UTIL_H + +#define rdcycle() ({ unsigned long _c; asm volatile ("rdcycle %0" : "=r"(_c) :: "memory"); _c; }) +#define rdinstret() ({ unsigned long _c; asm volatile ("rdinstret %0" : "=r"(_c) :: "memory"); _c; }) + +void __attribute__((noinline)) barrier() +{ + static volatile int sense; + static volatile int count; + static __thread int threadsense; + + __sync_synchronize(); + + threadsense = !threadsense; + if (__sync_fetch_and_add(&count, 1) == ncores-1) + { + count = 0; + sense = threadsense; + } + else while(sense != threadsense) + ; + + __sync_synchronize(); +} + +#endif //__UTIL_H + diff --git a/benchmarks/dgemm/bmark.mk b/benchmarks/dgemm/bmark.mk new file mode 100644 index 0000000..5a26242 --- /dev/null +++ b/benchmarks/dgemm/bmark.mk @@ -0,0 +1,29 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +dgemm_c_src = \ + dgemm_main.c \ + +dgemm_riscv_src = \ + crt.S \ + +dgemm_c_objs = $(patsubst %.c, %.o, $(dgemm_c_src)) +dgemm_riscv_objs = $(patsubst %.S, %.o, $(dgemm_riscv_src)) + +dgemm_host_bin = dgemm.host +$(dgemm_host_bin) : $(dgemm_c_src) + $(HOST_COMP) $^ -o $(dgemm_host_bin) + +dgemm_riscv_bin = dgemm.riscv +$(dgemm_riscv_bin) : $(dgemm_c_objs) $(dgemm_riscv_objs) + $(RISCV_LINK) $(dgemm_c_objs) $(dgemm_riscv_objs) -o $(dgemm_riscv_bin) + +junk += $(dgemm_c_objs) $(dgemm_riscv_objs) \ + $(dgemm_host_bin) $(dgemm_riscv_bin) diff --git a/benchmarks/dgemm/dataset1.h b/benchmarks/dgemm/dataset1.h new file mode 100644 index 0000000..9db066e --- /dev/null +++ b/benchmarks/dgemm/dataset1.h @@ -0,0 +1,97 @@ +#define DATA_SIZE 30 +const double input1_data[DATA_SIZE*DATA_SIZE] = { +745.0, 504.0, 772.0, 818.0, 443.0, 308.0, 823.0, 523.0, 93.0, 379.0, 728.0, 543.0, 40.0, 482.0, 728.0, 487.0, 144.0, 486.0, 109.0, 994.0, 373.0, 257.0, 196.0, 145.0, 234.0, 301.0, 639.0, 379.0, 913.0, 420.0, +264.0, 636.0, 873.0, 677.0, 330.0, 928.0, 30.0, 603.0, 96.0, 510.0, 196.0, 55.0, 702.0, 663.0, 151.0, 526.0, 624.0, 598.0, 529.0, 926.0, 914.0, 641.0, 401.0, 146.0, 756.0, 550.0, 92.0, 452.0, 786.0, 417.0, +115.0, 202.0, 806.0, 841.0, 657.0, 33.0, 66.0, 595.0, 751.0, 302.0, 70.0, 453.0, 318.0, 580.0, 114.0, 85.0, 585.0, 959.0, 393.0, 810.0, 276.0, 839.0, 58.0, 632.0, 940.0, 568.0, 676.0, 625.0, 861.0, 702.0, +413.0, 79.0, 762.0, 494.0, 695.0, 774.0, 877.0, 968.0, 327.0, 742.0, 163.0, 353.0, 692.0, 870.0, 634.0, 60.0, 545.0, 300.0, 625.0, 48.0, 390.0, 713.0, 661.0, 613.0, 673.0, 89.0, 116.0, 472.0, 837.0, 864.0, +256.0, 542.0, 660.0, 768.0, 474.0, 229.0, 783.0, 583.0, 975.0, 278.0, 838.0, 557.0, 372.0, 815.0, 94.0, 820.0, 713.0, 685.0, 606.0, 304.0, 549.0, 150.0, 237.0, 981.0, 111.0, 85.0, 741.0, 960.0, 499.0, 110.0, +540.0, 414.0, 153.0, 809.0, 477.0, 176.0, 46.0, 27.0, 106.0, 704.0, 709.0, 728.0, 355.0, 934.0, 38.0, 974.0, 744.0, 651.0, 169.0, 514.0, 550.0, 742.0, 456.0, 453.0, 106.0, 956.0, 374.0, 945.0, 688.0, 594.0, +983.0, 686.0, 86.0, 247.0, 389.0, 914.0, 378.0, 837.0, 556.0, 332.0, 884.0, 102.0, 651.0, 329.0, 305.0, 874.0, 863.0, 752.0, 94.0, 102.0, 878.0, 200.0, 645.0, 601.0, 573.0, 369.0, 247.0, 241.0, 158.0, 647.0, +166.0, 139.0, 810.0, 531.0, 118.0, 750.0, 759.0, 621.0, 87.0, 472.0, 846.0, 644.0, 209.0, 515.0, 172.0, 565.0, 685.0, 344.0, 850.0, 218.0, 788.0, 323.0, 867.0, 809.0, 991.0, 806.0, 617.0, 878.0, 937.0, 816.0, +517.0, 811.0, 181.0, 590.0, 705.0, 691.0, 847.0, 233.0, 652.0, 374.0, 570.0, 160.0, 873.0, 78.0, 246.0, 652.0, 876.0, 145.0, 587.0, 729.0, 467.0, 111.0, 590.0, 653.0, 972.0, 987.0, 231.0, 809.0, 456.0, 887.0, +861.0, 60.0, 588.0, 71.0, 519.0, 479.0, 640.0, 608.0, 336.0, 259.0, 7.0, 578.0, 53.0, 823.0, 305.0, 911.0, 230.0, 445.0, 216.0, 696.0, 278.0, 804.0, 413.0, 333.0, 409.0, 632.0, 86.0, 401.0, 226.0, 93.0, +815.0, 177.0, 894.0, 51.0, 441.0, 785.0, 888.0, 915.0, 347.0, 55.0, 762.0, 896.0, 964.0, 539.0, 572.0, 889.0, 275.0, 43.0, 220.0, 195.0, 963.0, 342.0, 915.0, 651.0, 750.0, 286.0, 632.0, 168.0, 652.0, 880.0, +803.0, 439.0, 112.0, 544.0, 624.0, 656.0, 679.0, 117.0, 413.0, 798.0, 230.0, 571.0, 106.0, 36.0, 656.0, 848.0, 733.0, 931.0, 513.0, 614.0, 302.0, 776.0, 401.0, 703.0, 510.0, 682.0, 280.0, 351.0, 79.0, 353.0, +106.0, 355.0, 343.0, 802.0, 232.0, 583.0, 103.0, 663.0, 683.0, 37.0, 130.0, 795.0, 261.0, 202.0, 949.0, 739.0, 926.0, 930.0, 522.0, 872.0, 567.0, 724.0, 0.0, 385.0, 191.0, 704.0, 586.0, 974.0, 944.0, 100.0, +506.0, 903.0, 325.0, 622.0, 218.0, 842.0, 298.0, 676.0, 503.0, 4.0, 784.0, 63.0, 195.0, 495.0, 740.0, 518.0, 845.0, 649.0, 730.0, 287.0, 231.0, 477.0, 939.0, 472.0, 324.0, 459.0, 784.0, 988.0, 572.0, 338.0, +114.0, 993.0, 965.0, 134.0, 608.0, 613.0, 527.0, 645.0, 324.0, 497.0, 949.0, 659.0, 555.0, 494.0, 91.0, 317.0, 222.0, 276.0, 232.0, 266.0, 985.0, 146.0, 713.0, 54.0, 592.0, 879.0, 799.0, 16.0, 273.0, 791.0, +47.0, 235.0, 306.0, 873.0, 829.0, 266.0, 672.0, 893.0, 396.0, 396.0, 809.0, 603.0, 307.0, 712.0, 551.0, 390.0, 551.0, 898.0, 777.0, 672.0, 385.0, 810.0, 39.0, 311.0, 868.0, 734.0, 554.0, 941.0, 414.0, 182.0, +549.0, 589.0, 24.0, 141.0, 332.0, 833.0, 76.0, 431.0, 528.0, 313.0, 690.0, 190.0, 860.0, 670.0, 991.0, 679.0, 0.0, 460.0, 122.0, 585.0, 647.0, 157.0, 260.0, 941.0, 943.0, 27.0, 820.0, 81.0, 612.0, 622.0, +252.0, 183.0, 673.0, 275.0, 27.0, 867.0, 36.0, 45.0, 80.0, 321.0, 373.0, 485.0, 232.0, 428.0, 379.0, 973.0, 532.0, 804.0, 763.0, 91.0, 802.0, 463.0, 190.0, 153.0, 910.0, 552.0, 885.0, 976.0, 84.0, 572.0, +83.0, 109.0, 349.0, 881.0, 368.0, 980.0, 316.0, 97.0, 654.0, 737.0, 652.0, 525.0, 714.0, 526.0, 608.0, 245.0, 296.0, 765.0, 222.0, 403.0, 419.0, 663.0, 256.0, 23.0, 144.0, 446.0, 905.0, 933.0, 238.0, 709.0, +17.0, 587.0, 508.0, 879.0, 525.0, 310.0, 486.0, 372.0, 742.0, 764.0, 462.0, 8.0, 108.0, 741.0, 803.0, 502.0, 422.0, 579.0, 993.0, 835.0, 953.0, 584.0, 92.0, 932.0, 579.0, 534.0, 602.0, 473.0, 99.0, 961.0, +413.0, 83.0, 255.0, 849.0, 953.0, 912.0, 552.0, 220.0, 968.0, 600.0, 918.0, 48.0, 863.0, 88.0, 132.0, 278.0, 957.0, 507.0, 320.0, 618.0, 768.0, 776.0, 401.0, 943.0, 995.0, 695.0, 869.0, 295.0, 960.0, 357.0, +446.0, 304.0, 926.0, 664.0, 785.0, 211.0, 287.0, 420.0, 187.0, 325.0, 49.0, 355.0, 607.0, 752.0, 783.0, 963.0, 952.0, 188.0, 939.0, 953.0, 384.0, 255.0, 674.0, 747.0, 243.0, 892.0, 60.0, 3.0, 643.0, 831.0, +734.0, 240.0, 944.0, 943.0, 382.0, 671.0, 12.0, 292.0, 18.0, 966.0, 296.0, 335.0, 206.0, 881.0, 22.0, 473.0, 888.0, 510.0, 725.0, 276.0, 769.0, 506.0, 202.0, 789.0, 515.0, 110.0, 658.0, 835.0, 345.0, 885.0, +776.0, 194.0, 8.0, 124.0, 908.0, 176.0, 144.0, 820.0, 803.0, 56.0, 270.0, 676.0, 741.0, 621.0, 290.0, 214.0, 511.0, 382.0, 431.0, 164.0, 173.0, 504.0, 116.0, 828.0, 68.0, 465.0, 263.0, 383.0, 793.0, 32.0, +313.0, 39.0, 34.0, 331.0, 874.0, 310.0, 607.0, 128.0, 505.0, 948.0, 827.0, 357.0, 31.0, 904.0, 165.0, 491.0, 809.0, 607.0, 390.0, 156.0, 441.0, 219.0, 198.0, 165.0, 592.0, 890.0, 192.0, 791.0, 234.0, 424.0, +886.0, 552.0, 965.0, 615.0, 370.0, 30.0, 79.0, 178.0, 67.0, 148.0, 20.0, 241.0, 928.0, 301.0, 73.0, 55.0, 428.0, 812.0, 752.0, 535.0, 110.0, 518.0, 584.0, 661.0, 35.0, 856.0, 279.0, 633.0, 354.0, 450.0, +327.0, 165.0, 508.0, 261.0, 763.0, 496.0, 415.0, 872.0, 557.0, 428.0, 110.0, 406.0, 341.0, 425.0, 326.0, 644.0, 904.0, 676.0, 542.0, 590.0, 738.0, 651.0, 980.0, 521.0, 865.0, 511.0, 920.0, 563.0, 448.0, 780.0, +920.0, 999.0, 28.0, 940.0, 120.0, 908.0, 167.0, 319.0, 891.0, 53.0, 158.0, 319.0, 202.0, 283.0, 793.0, 608.0, 320.0, 711.0, 447.0, 533.0, 528.0, 300.0, 532.0, 797.0, 571.0, 960.0, 104.0, 773.0, 122.0, 99.0, +156.0, 119.0, 932.0, 689.0, 227.0, 991.0, 396.0, 890.0, 579.0, 54.0, 459.0, 624.0, 976.0, 904.0, 781.0, 712.0, 403.0, 560.0, 226.0, 225.0, 940.0, 68.0, 140.0, 714.0, 937.0, 731.0, 624.0, 416.0, 601.0, 50.0, +883.0, 869.0, 921.0, 350.0, 226.0, 596.0, 698.0, 51.0, 510.0, 865.0, 942.0, 971.0, 794.0, 254.0, 757.0, 19.0, 690.0, 303.0, 664.0, 127.0, 538.0, 487.0, 609.0, 86.0, 688.0, 76.0, 477.0, 664.0, 343.0, 613.0 +}; +const double input2_data[DATA_SIZE*DATA_SIZE] = { +494.0, 929.0, 783.0, 86.0, 317.0, 957.0, 289.0, 481.0, 222.0, 945.0, 97.0, 952.0, 1.0, 834.0, 795.0, 59.0, 127.0, 10.0, 399.0, 904.0, 907.0, 665.0, 623.0, 841.0, 190.0, 903.0, 698.0, 132.0, 775.0, 911.0, +346.0, 417.0, 995.0, 439.0, 159.0, 390.0, 902.0, 917.0, 174.0, 462.0, 638.0, 484.0, 505.0, 353.0, 943.0, 724.0, 684.0, 845.0, 753.0, 983.0, 353.0, 730.0, 883.0, 679.0, 449.0, 442.0, 242.0, 117.0, 64.0, 143.0, +42.0, 476.0, 395.0, 343.0, 983.0, 724.0, 153.0, 3.0, 88.0, 131.0, 475.0, 517.0, 297.0, 917.0, 522.0, 776.0, 796.0, 468.0, 11.0, 9.0, 788.0, 908.0, 161.0, 554.0, 429.0, 381.0, 495.0, 720.0, 795.0, 563.0, +976.0, 786.0, 349.0, 930.0, 421.0, 218.0, 589.0, 210.0, 18.0, 536.0, 888.0, 18.0, 142.0, 674.0, 684.0, 297.0, 190.0, 160.0, 195.0, 232.0, 917.0, 451.0, 955.0, 340.0, 553.0, 470.0, 287.0, 263.0, 164.0, 28.0, +133.0, 206.0, 141.0, 697.0, 860.0, 45.0, 508.0, 61.0, 442.0, 142.0, 991.0, 523.0, 720.0, 544.0, 787.0, 231.0, 635.0, 828.0, 162.0, 150.0, 656.0, 915.0, 557.0, 56.0, 539.0, 108.0, 862.0, 160.0, 739.0, 561.0, +525.0, 564.0, 334.0, 977.0, 789.0, 287.0, 316.0, 169.0, 18.0, 140.0, 322.0, 707.0, 458.0, 646.0, 902.0, 728.0, 877.0, 386.0, 922.0, 657.0, 490.0, 942.0, 127.0, 617.0, 143.0, 979.0, 911.0, 71.0, 348.0, 989.0, +55.0, 968.0, 173.0, 987.0, 959.0, 865.0, 850.0, 194.0, 776.0, 681.0, 893.0, 564.0, 305.0, 645.0, 600.0, 214.0, 613.0, 790.0, 496.0, 127.0, 564.0, 197.0, 818.0, 419.0, 597.0, 414.0, 552.0, 240.0, 517.0, 34.0, +487.0, 497.0, 614.0, 182.0, 761.0, 45.0, 959.0, 441.0, 90.0, 500.0, 76.0, 435.0, 905.0, 920.0, 402.0, 641.0, 621.0, 526.0, 521.0, 438.0, 457.0, 224.0, 718.0, 611.0, 909.0, 347.0, 524.0, 158.0, 491.0, 331.0, +727.0, 536.0, 243.0, 503.0, 252.0, 633.0, 675.0, 671.0, 600.0, 598.0, 479.0, 522.0, 92.0, 778.0, 793.0, 956.0, 562.0, 659.0, 29.0, 132.0, 182.0, 491.0, 107.0, 891.0, 108.0, 664.0, 985.0, 608.0, 610.0, 589.0, +364.0, 665.0, 689.0, 262.0, 356.0, 324.0, 646.0, 275.0, 906.0, 316.0, 551.0, 836.0, 14.0, 495.0, 900.0, 859.0, 529.0, 900.0, 516.0, 654.0, 635.0, 90.0, 337.0, 59.0, 954.0, 419.0, 921.0, 903.0, 393.0, 503.0, +458.0, 879.0, 568.0, 925.0, 809.0, 496.0, 22.0, 780.0, 966.0, 265.0, 759.0, 872.0, 352.0, 110.0, 467.0, 641.0, 321.0, 272.0, 646.0, 765.0, 413.0, 935.0, 309.0, 661.0, 796.0, 881.0, 283.0, 612.0, 602.0, 684.0, +680.0, 332.0, 688.0, 896.0, 483.0, 131.0, 680.0, 265.0, 828.0, 779.0, 410.0, 176.0, 657.0, 776.0, 678.0, 232.0, 522.0, 722.0, 485.0, 878.0, 987.0, 754.0, 225.0, 897.0, 374.0, 704.0, 117.0, 929.0, 586.0, 891.0, +162.0, 237.0, 300.0, 147.0, 648.0, 324.0, 376.0, 552.0, 381.0, 589.0, 788.0, 637.0, 461.0, 802.0, 481.0, 694.0, 406.0, 127.0, 623.0, 743.0, 662.0, 257.0, 636.0, 655.0, 827.0, 649.0, 961.0, 561.0, 511.0, 991.0, +633.0, 907.0, 279.0, 732.0, 527.0, 31.0, 54.0, 320.0, 875.0, 863.0, 82.0, 881.0, 272.0, 677.0, 787.0, 149.0, 709.0, 457.0, 411.0, 287.0, 598.0, 27.0, 231.0, 853.0, 270.0, 520.0, 96.0, 178.0, 51.0, 938.0, +414.0, 639.0, 127.0, 888.0, 18.0, 821.0, 606.0, 253.0, 566.0, 134.0, 833.0, 324.0, 316.0, 393.0, 157.0, 753.0, 888.0, 131.0, 40.0, 450.0, 762.0, 139.0, 603.0, 196.0, 324.0, 590.0, 573.0, 738.0, 252.0, 297.0, +353.0, 280.0, 718.0, 350.0, 813.0, 663.0, 2.0, 405.0, 405.0, 353.0, 957.0, 699.0, 981.0, 499.0, 807.0, 648.0, 0.0, 675.0, 8.0, 514.0, 215.0, 22.0, 463.0, 671.0, 65.0, 764.0, 25.0, 232.0, 891.0, 152.0, +698.0, 426.0, 813.0, 87.0, 12.0, 246.0, 1.0, 834.0, 81.0, 695.0, 296.0, 935.0, 30.0, 699.0, 811.0, 881.0, 822.0, 259.0, 883.0, 935.0, 447.0, 973.0, 629.0, 58.0, 534.0, 745.0, 654.0, 344.0, 826.0, 568.0, +198.0, 814.0, 111.0, 912.0, 84.0, 179.0, 706.0, 700.0, 838.0, 455.0, 972.0, 216.0, 659.0, 210.0, 781.0, 842.0, 248.0, 465.0, 518.0, 37.0, 3.0, 803.0, 562.0, 983.0, 375.0, 34.0, 882.0, 586.0, 668.0, 228.0, +644.0, 632.0, 530.0, 729.0, 783.0, 543.0, 450.0, 151.0, 302.0, 148.0, 225.0, 794.0, 590.0, 212.0, 146.0, 191.0, 718.0, 621.0, 303.0, 343.0, 562.0, 715.0, 516.0, 409.0, 36.0, 486.0, 248.0, 416.0, 624.0, 865.0, +680.0, 460.0, 737.0, 813.0, 658.0, 396.0, 749.0, 132.0, 875.0, 73.0, 243.0, 874.0, 309.0, 5.0, 748.0, 526.0, 273.0, 634.0, 661.0, 382.0, 61.0, 728.0, 511.0, 960.0, 418.0, 454.0, 249.0, 725.0, 68.0, 306.0, +899.0, 127.0, 599.0, 587.0, 7.0, 236.0, 722.0, 531.0, 694.0, 403.0, 163.0, 483.0, 557.0, 10.0, 855.0, 494.0, 90.0, 186.0, 180.0, 335.0, 646.0, 74.0, 869.0, 751.0, 409.0, 777.0, 449.0, 310.0, 989.0, 624.0, +672.0, 27.0, 968.0, 211.0, 459.0, 70.0, 617.0, 431.0, 983.0, 291.0, 878.0, 599.0, 69.0, 873.0, 904.0, 337.0, 250.0, 120.0, 20.0, 389.0, 254.0, 714.0, 478.0, 62.0, 931.0, 992.0, 324.0, 537.0, 84.0, 333.0, +724.0, 874.0, 511.0, 407.0, 915.0, 566.0, 809.0, 905.0, 811.0, 291.0, 572.0, 374.0, 376.0, 988.0, 751.0, 881.0, 888.0, 169.0, 922.0, 616.0, 181.0, 203.0, 389.0, 622.0, 568.0, 204.0, 924.0, 543.0, 331.0, 765.0, +273.0, 742.0, 682.0, 913.0, 38.0, 787.0, 983.0, 783.0, 821.0, 848.0, 114.0, 661.0, 678.0, 634.0, 865.0, 551.0, 700.0, 253.0, 481.0, 231.0, 860.0, 680.0, 801.0, 783.0, 987.0, 624.0, 888.0, 770.0, 11.0, 689.0, +731.0, 72.0, 538.0, 78.0, 324.0, 368.0, 176.0, 305.0, 817.0, 136.0, 122.0, 783.0, 608.0, 391.0, 136.0, 859.0, 13.0, 452.0, 663.0, 826.0, 880.0, 728.0, 947.0, 342.0, 646.0, 182.0, 13.0, 148.0, 450.0, 610.0, +477.0, 121.0, 487.0, 143.0, 125.0, 153.0, 268.0, 635.0, 745.0, 792.0, 981.0, 109.0, 694.0, 353.0, 547.0, 559.0, 974.0, 59.0, 655.0, 694.0, 165.0, 628.0, 544.0, 694.0, 476.0, 702.0, 494.0, 627.0, 88.0, 630.0, +194.0, 650.0, 165.0, 587.0, 884.0, 53.0, 44.0, 931.0, 432.0, 630.0, 214.0, 817.0, 383.0, 3.0, 908.0, 667.0, 205.0, 791.0, 845.0, 584.0, 396.0, 26.0, 547.0, 399.0, 189.0, 438.0, 698.0, 826.0, 734.0, 322.0, +678.0, 305.0, 868.0, 564.0, 480.0, 499.0, 182.0, 215.0, 276.0, 272.0, 803.0, 21.0, 458.0, 2.0, 90.0, 213.0, 223.0, 97.0, 68.0, 589.0, 408.0, 197.0, 472.0, 915.0, 771.0, 830.0, 907.0, 133.0, 146.0, 848.0, +89.0, 17.0, 580.0, 755.0, 909.0, 310.0, 249.0, 606.0, 544.0, 193.0, 409.0, 235.0, 537.0, 580.0, 850.0, 838.0, 882.0, 416.0, 365.0, 263.0, 331.0, 868.0, 68.0, 519.0, 206.0, 70.0, 530.0, 927.0, 590.0, 29.0, +990.0, 507.0, 164.0, 89.0, 550.0, 150.0, 959.0, 787.0, 444.0, 695.0, 79.0, 86.0, 359.0, 841.0, 991.0, 71.0, 537.0, 521.0, 253.0, 88.0, 872.0, 760.0, 71.0, 959.0, 844.0, 24.0, 323.0, 86.0, 284.0, 324.0 +}; +const double verify_data[DATA_SIZE*DATA_SIZE] = { +6411903.0, 7533490.0, 6901412.0, 8515176.0, 7937886.0, 5660376.0, 6684238.0, 5930516.0, 7411434.0, 5963715.0, 7339541.0, 7325224.0, 5773363.0, 6987016.0, 9472107.0, 7333522.0, 6868741.0, 6373927.0, 5818371.0, 6232365.0, 7410967.0, 7456844.0, 7008217.0, 8317827.0, 6560681.0, 6993670.0, 6792972.0, 6664526.0, 6449148.0, 6153016.0, +7767492.0, 6619373.0, 8084203.0, 7609675.0, 7767288.0, 5081659.0, 6915392.0, 6473820.0, 7434817.0, 5832034.0, 7317348.0, 8206514.0, 6552649.0, 7813213.0, 1.0197744E7, 8753506.0, 7589899.0, 6153453.0, 6716065.0, 7097060.0, 7488858.0, 8435675.0, 7671781.0, 8759777.0, 7413370.0, 7802106.0, 7613653.0, 6343832.0, 6741596.0, 7885307.0, +7584476.0, 6627809.0, 7334380.0, 7777143.0, 7311439.0, 4673418.0, 7231791.0, 6792764.0, 8133419.0, 6543855.0, 7278453.0, 7372708.0, 6345899.0, 7821711.0, 1.0014052E7, 8297702.0, 7222827.0, 6550430.0, 5927298.0, 5988751.0, 7626028.0, 8765186.0, 7449916.0, 8719206.0, 7751464.0, 6820384.0, 7786274.0, 7199576.0, 6446456.0, 7164579.0, +7690319.0, 8107202.0, 7462090.0, 8353962.0, 8807718.0, 5963658.0, 8163425.0, 6652851.0, 8169066.0, 6906018.0, 7448498.0, 8403353.0, 6499220.0, 9827668.0, 1.0370807E7, 8413234.0, 8979741.0, 6743719.0, 6583108.0, 6733404.0, 9203350.0, 8305284.0, 7661872.0, 8475391.0, 8638725.0, 7679995.0, 8961802.0, 6750314.0, 7049775.0, 8577580.0, +7412324.0, 8652125.0, 7961811.0, 9598288.0, 8296849.0, 6391772.0, 7240482.0, 7531594.0, 8110724.0, 7533868.0, 8155571.0, 8596878.0, 6925515.0, 7915918.0, 1.0572044E7, 8603488.0, 7693006.0, 7286678.0, 6399408.0, 6860014.0, 8027549.0, 7922416.0, 8053228.0, 9735395.0, 7584369.0, 8588126.0, 8653757.0, 7169521.0, 7682896.0, 8137235.0, +7988409.0, 7238778.0, 8449952.0, 7992084.0, 7262269.0, 5011760.0, 6432958.0, 7422948.0, 8648278.0, 7337408.0, 8462957.0, 7677222.0, 6397788.0, 7568297.0, 1.0797395E7, 7705063.0, 7146568.0, 6022723.0, 6370298.0, 7586299.0, 7452484.0, 7887693.0, 7307727.0, 9197385.0, 7726968.0, 8478492.0, 7601569.0, 6960883.0, 6522251.0, 7976344.0, +7572166.0, 7897218.0, 7706123.0, 7359858.0, 6988842.0, 5975477.0, 7234281.0, 8027665.0, 7471601.0, 7160694.0, 7249166.0, 8618544.0, 6644699.0, 8171915.0, 1.0497206E7, 8729802.0, 7174778.0, 5972218.0, 7216469.0, 7843533.0, 7628960.0, 7931021.0, 7962767.0, 9166492.0, 7547189.0, 8369468.0, 8488684.0, 5609773.0, 7562941.0, 8204473.0, +8857954.0, 8551958.0, 8909718.0, 9431684.0, 9556061.0, 6617423.0, 7827032.0, 8179745.0, 9353072.0, 7550842.0, 8121182.0, 8962388.0, 7937096.0, 8954704.0, 1.1085794E7, 9549551.0, 9145331.0, 7163225.0, 7988163.0, 8211966.0, 9352371.0, 9330003.0, 8532410.0, 1.0197366E7, 8931427.0, 8915845.0, 8823015.0, 7853048.0, 8044845.0, 9386048.0, +8545963.0, 7912549.0, 8606518.0, 8379764.0, 8351466.0, 6814749.0, 8057369.0, 8048780.0, 8451865.0, 7466527.0, 8749940.0, 8919463.0, 7276916.0, 8536482.0, 1.0911699E7, 9197448.0, 8560655.0, 7064115.0, 7860209.0, 8511883.0, 8654584.0, 9323289.0, 8981720.0, 9803015.0, 8598113.0, 8780796.0, 9135261.0, 6665333.0, 7324434.0, 8872122.0, +5946430.0, 6135788.0, 6591364.0, 6433251.0, 6632373.0, 4985963.0, 5769881.0, 4843727.0, 7021916.0, 5697194.0, 6385378.0, 6994046.0, 5502157.0, 7123974.0, 8365161.0, 6212258.0, 6104723.0, 5313031.0, 4845223.0, 5646055.0, 6129753.0, 6289476.0, 6051385.0, 7494259.0, 5723628.0, 6965055.0, 6172636.0, 5253106.0, 5610430.0, 6685980.0, +8055844.0, 8469174.0, 8170470.0, 8793113.0, 9859241.0, 7007325.0, 8137618.0, 8029717.0, 8997562.0, 7852580.0, 7740885.0, 9375326.0, 7883965.0, 1.0029182E7, 1.1346371E7, 9215599.0, 8636081.0, 7104102.0, 7496227.0, 8176023.0, 9732692.0, 8508678.0, 8257884.0, 1.0379885E7, 8448925.0, 9060668.0, 8836821.0, 7441640.0, 8726147.0, 9513821.0, +7367171.0, 7678838.0, 7804927.0, 8158615.0, 6673882.0, 6127379.0, 7575878.0, 6722516.0, 8300529.0, 6711008.0, 8389597.0, 8171405.0, 6196454.0, 7704372.0, 1.029698E7, 8112392.0, 7236981.0, 6508313.0, 6457042.0, 7280014.0, 7526900.0, 8231928.0, 7990796.0, 8184970.0, 7283106.0, 8214745.0, 8201658.0, 6708897.0, 6728783.0, 7449993.0, +7865362.0, 6776674.0, 8132061.0, 9041300.0, 7066772.0, 5445850.0, 7151522.0, 6942482.0, 7679044.0, 6487802.0, 8458847.0, 7314760.0, 6955102.0, 7314651.0, 9998347.0, 8897441.0, 7785211.0, 6248190.0, 6094040.0, 7118063.0, 7145775.0, 8373612.0, 7778499.0, 9104195.0, 6890059.0, 8603542.0, 8143136.0, 7583203.0, 6981314.0, 7304046.0, +7986730.0, 8495508.0, 8226132.0, 8837284.0, 8110164.0, 6270243.0, 7155084.0, 8144444.0, 7505249.0, 6776566.0, 8180893.0, 8341901.0, 6720764.0, 7941827.0, 1.0232075E7, 9099507.0, 8475362.0, 6245408.0, 7407245.0, 7953062.0, 7429359.0, 8415664.0, 8058703.0, 9250511.0, 7408836.0, 8633240.0, 8794298.0, 6612461.0, 6871055.0, 8223063.0, +7048151.0, 7129340.0, 7082981.0, 7489318.0, 8235538.0, 4945598.0, 7158417.0, 7404589.0, 7952446.0, 6524416.0, 7264108.0, 7881673.0, 6788833.0, 7675645.0, 1.0238341E7, 8484876.0, 7867557.0, 7037936.0, 7237519.0, 7346638.0, 7710289.0, 7883823.0, 7209172.0, 8844511.0, 7452039.0, 7340367.0, 7433870.0, 6571140.0, 7229344.0, 7904304.0, +8240448.0, 7954564.0, 8154706.0, 9504953.0, 8400499.0, 5460298.0, 7584126.0, 6871697.0, 9185194.0, 6905207.0, 9141475.0, 8494493.0, 7418418.0, 7753101.0, 1.0000234E7, 8633021.0, 7846515.0, 7199308.0, 6775263.0, 7435406.0, 8253684.0, 8758868.0, 8831361.0, 9095568.0, 8526076.0, 8528570.0, 8182811.0, 7299290.0, 7191919.0, 8226562.0, +6751777.0, 7186625.0, 6646412.0, 8018233.0, 6909389.0, 5658036.0, 6840978.0, 7190409.0, 7959774.0, 6192193.0, 6295944.0, 8365353.0, 6495593.0, 6989066.0, 9678769.0, 8422620.0, 6708233.0, 6122942.0, 6541236.0, 6976638.0, 7715128.0, 7027844.0, 7287427.0, 8765201.0, 6824683.0, 7411205.0, 7587931.0, 6447872.0, 6342510.0, 7582018.0, +7082585.0, 6197492.0, 6807726.0, 6956058.0, 6641216.0, 4830697.0, 5048238.0, 6053977.0, 6808066.0, 5552500.0, 6709804.0, 7175350.0, 6209976.0, 5950372.0, 8477306.0, 7412364.0, 5897445.0, 5540244.0, 5666371.0, 6696737.0, 6961106.0, 6862383.0, 6637593.0, 8019798.0, 5997948.0, 7597047.0, 6638311.0, 5646733.0, 6753680.0, 7600719.0, +7405626.0, 7342316.0, 6412193.0, 8347922.0, 7388131.0, 4709450.0, 6484686.0, 6422277.0, 7614878.0, 6155351.0, 8101524.0, 7056940.0, 5444306.0, 7010298.0, 9663947.0, 7786125.0, 6890705.0, 6006121.0, 6032720.0, 6508389.0, 7243995.0, 7137452.0, 6513236.0, 8338516.0, 7172679.0, 7934665.0, 8344129.0, 6707389.0, 6191989.0, 7659162.0, +8824351.0, 8499764.0, 7935349.0, 9362467.0, 7540129.0, 6218015.0, 8666871.0, 7431305.0, 9119473.0, 7093927.0, 8066413.0, 8889088.0, 6865107.0, 7703744.0, 1.1009442E7, 8749305.0, 8122317.0, 7493355.0, 6353037.0, 6661887.0, 8703986.0, 8305822.0, 8770358.0, 9415405.0, 8359360.0, 8392544.0, 8323587.0, 7316703.0, 6900664.0, 7998790.0, +8559320.0, 8232032.0, 8582628.0, 9561300.0, 8909146.0, 6399353.0, 7974575.0, 8670453.0, 9676934.0, 7602031.0, 9078286.0, 1.0045779E7, 7111219.0, 8996593.0, 1.226795E7, 1.0495147E7, 8627020.0, 7247946.0, 8214785.0, 8248879.0, 8942703.0, 1.0207892E7, 9159335.0, 9386478.0, 9122587.0, 9412550.0, 1.0407378E7, 8320858.0, 8412198.0, 9183005.0, +7864178.0, 7731246.0, 7874580.0, 8126602.0, 8217140.0, 6306880.0, 7598202.0, 6913447.0, 7964758.0, 7035041.0, 7879116.0, 8569671.0, 7028566.0, 9038832.0, 1.0641974E7, 8450936.0, 9082649.0, 6675630.0, 6481241.0, 6939335.0, 8501496.0, 8693928.0, 7876616.0, 8953343.0, 7470078.0, 7817750.0, 7845736.0, 7283306.0, 7144396.0, 8159051.0, +8244761.0, 8043437.0, 8160617.0, 7960796.0, 7638538.0, 5521627.0, 6770600.0, 6827077.0, 7424432.0, 7085102.0, 6703036.0, 8663556.0, 6008305.0, 8127122.0, 1.0757715E7, 7838981.0, 7320679.0, 6470974.0, 6395050.0, 7078761.0, 9051568.0, 8296696.0, 7669203.0, 8793438.0, 7935840.0, 8242858.0, 8167852.0, 6513437.0, 7222152.0, 8621155.0, +5398601.0, 5656258.0, 6127160.0, 6431306.0, 5861315.0, 4330490.0, 5807953.0, 5755300.0, 6320034.0, 6114599.0, 5885148.0, 6497254.0, 5450734.0, 6993714.0, 8061082.0, 6229394.0, 6511621.0, 4914814.0, 4902640.0, 5650877.0, 6261491.0, 6670406.0, 5878213.0, 7134964.0, 5872648.0, 6551681.0, 7116052.0, 5637658.0, 5610163.0, 6938664.0, +6665479.0, 6655902.0, 6361533.0, 6987969.0, 6216951.0, 4491075.0, 5339732.0, 5808102.0, 7720459.0, 6041092.0, 7229382.0, 7153949.0, 5369655.0, 6203304.0, 8545499.0, 6785740.0, 6520276.0, 5817279.0, 5606822.0, 6256946.0, 6558416.0, 6783016.0, 6327605.0, 7218378.0, 6631328.0, 6923787.0, 7005653.0, 5461050.0, 6094680.0, 7234228.0, +5843630.0, 6349173.0, 6588290.0, 6096008.0, 6187686.0, 4971317.0, 6130619.0, 5956329.0, 6069945.0, 6017854.0, 6689679.0, 6237127.0, 5164682.0, 6970236.0, 8278739.0, 6412665.0, 6644780.0, 4531485.0, 5404887.0, 5762443.0, 6496410.0, 7358530.0, 6524107.0, 7809916.0, 6432073.0, 6378435.0, 7274185.0, 5883336.0, 5290775.0, 7048857.0, +8593925.0, 7961767.0, 8292016.0, 8257014.0, 8765041.0, 5832016.0, 8184239.0, 8118105.0, 8933460.0, 7297129.0, 7909218.0, 9048344.0, 7497893.0, 8965430.0, 1.135426E7, 9530131.0, 8401874.0, 7390341.0, 7549933.0, 7675511.0, 8338916.0, 8618154.0, 8505674.0, 9483324.0, 8414926.0, 8193850.0, 9268065.0, 7355728.0, 8122626.0, 8739657.0, +7908996.0, 7506755.0, 7778220.0, 8175639.0, 5766252.0, 6284412.0, 7460913.0, 6975311.0, 7164714.0, 6767688.0, 7763452.0, 7215835.0, 6324251.0, 7271730.0, 9511219.0, 8140001.0, 7262476.0, 5372931.0, 6328202.0, 7443961.0, 7220668.0, 7721429.0, 8144112.0, 9294316.0, 6481768.0, 8506164.0, 8022424.0, 5875671.0, 5724007.0, 7793814.0, +7633150.0, 7688795.0, 7394176.0, 9147539.0, 8138372.0, 6018889.0, 6933383.0, 7053057.0, 8134616.0, 7254464.0, 7889703.0, 8526882.0, 7741309.0, 8523760.0, 1.0130337E7, 9570375.0, 8261785.0, 6437251.0, 6961202.0, 7470969.0, 8885321.0, 7952766.0, 8360734.0, 9775719.0, 7554078.0, 8847637.0, 8491061.0, 7347352.0, 7755601.0, 8960722.0, +7960421.0, 8470588.0, 8332189.0, 8444058.0, 8235295.0, 6839043.0, 7517756.0, 7415098.0, 8360872.0, 7000654.0, 8095598.0, 8937832.0, 5813282.0, 8713683.0, 1.0340755E7, 8893432.0, 8245456.0, 6941267.0, 7209275.0, 8630017.0, 9331110.0, 8897494.0, 7845643.0, 9026386.0, 8115773.0, 8895582.0, 8748333.0, 7461803.0, 7814024.0, 9201676.0 +}; diff --git a/benchmarks/dgemm/dgemm_gendata.scala b/benchmarks/dgemm/dgemm_gendata.scala new file mode 100644 index 0000000..de2740b --- /dev/null +++ b/benchmarks/dgemm/dgemm_gendata.scala @@ -0,0 +1,37 @@ +#!/usr/bin/env scala +!# + +val size = args(0).toInt + +def print_matrix(name: String, rows: Int, cols: Int, data: Array[Double]) = { + println("const double " + name + "[DATA_SIZE*DATA_SIZE] = {") + for (i <- 0 until rows) { + println(data.slice(cols*i, cols*(i+1)).mkString(", ") + (if (i < rows-1) ", " else "")) + } + println("};") +} +def rand_matrix(rows: Int, cols: Int) = { + var r = new scala.util.Random + var m = new Array[Double](rows*cols) + for (i <- 0 until rows*cols) + m(i) = r.nextInt(1000) + m +} +def matmul(a: Array[Double], b: Array[Double], m: Int, n: Int, k: Int) = { + var c = new Array[Double](m*n) + for (i <- 0 until m) + for (j <- 0 until n) + for (l <- 0 until k) + c(i*n+j) += a(i*n+l)*b(l*k+j) + c +} + +println("#define DATA_SIZE " + size) + +val a = rand_matrix(size, size) +val b = rand_matrix(size, size) +val c = matmul(a, b, size, size, size) + +print_matrix("input1_data", size, size, a) +print_matrix("input2_data", size, size, b) +print_matrix("verify_data", size, size, c) diff --git a/benchmarks/dgemm/dgemm_main.c b/benchmarks/dgemm/dgemm_main.c new file mode 100644 index 0000000..7c8ce7c --- /dev/null +++ b/benchmarks/dgemm/dgemm_main.c @@ -0,0 +1,205 @@ +//************************************************************************** +// Double-precision general matrix multiplication benchmark +//-------------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +//-------------------------------------------------------------------------- +// Input/Reference Data + +#include "dataset1.h" + +//-------------------------------------------------------------------------- +// Helper functions + +int verify( long n, const double test[], const double correct[] ) +{ + int i; + for ( i = 0; i < n; i++ ) { + if ( test[i] != correct[i] ) { + return 2; + } + } + return 1; +} + +#if HOST_DEBUG +#include +#include +void printArray( char name[], long n, const double arr[] ) +{ + int i; + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " %8.1f ", arr[i] ); + printf( "\n" ); +} +#endif + +void finishTest( int toHostValue ) +{ +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + asm( "mtpcr %0, cr30" : : "r" (toHostValue) ); + while ( 1 ) { } +#endif +} + +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +//-------------------------------------------------------------------------- +// square_dgemm function + +void square_dgemm( long n0, const double a0[], const double b0[], double c0[] ) +{ + long n = (n0+2)/3*3; + double a[n*n], b[n*n], c[n*n]; + + for (long i = 0; i < n0; i++) + { + long j; + for (j = 0; j < n0; j++) + { + a[i*n+j] = a0[i*n0+j]; + b[i*n+j] = b0[j*n0+i]; + } + for ( ; j < n; j++) + { + a[i*n+j] = b[i*n+j] = 0; + } + } + for (long i = n0; i < n; i++) + for (long j = 0; j < n; j++) + a[i*n+j] = b[i*n+j] = 0; + + long i, j, k; + for (i = 0; i < n; i+=3) + { + for (j = 0; j < n; j+=3) + { + double *a0 = a + (i+0)*n, *b0 = b + (j+0)*n; + double *a1 = a + (i+1)*n, *b1 = b + (j+1)*n; + double *a2 = a + (i+2)*n, *b2 = b + (j+2)*n; + + double s00 = 0, s01 = 0, s02 = 0; + double s10 = 0, s11 = 0, s12 = 0; + double s20 = 0, s21 = 0, s22 = 0; + + while (a0 < a + (i+1)*n) + { + double a00 = a0[0], a01 = a0[1], a02 = a0[2]; + double b00 = b0[0], b01 = b0[1], b02 = b0[2]; + double a10 = a1[0], a11 = a1[1], a12 = a1[2]; + double b10 = b1[0], b11 = b1[1], b12 = b1[2]; + asm ("" ::: "memory"); + double a20 = a2[0], a21 = a2[1], a22 = a2[2]; + double b20 = b2[0], b21 = b2[1], b22 = b2[2]; + + s00 = a00*b00 + (a01*b01 + (a02*b02 + s00)); + s01 = a00*b10 + (a01*b11 + (a02*b12 + s01)); + s02 = a00*b20 + (a01*b21 + (a02*b22 + s02)); + s10 = a10*b00 + (a11*b01 + (a12*b02 + s10)); + s11 = a10*b10 + (a11*b11 + (a12*b12 + s11)); + s12 = a10*b20 + (a11*b21 + (a12*b22 + s12)); + s20 = a20*b00 + (a21*b01 + (a22*b02 + s20)); + s21 = a20*b10 + (a21*b11 + (a22*b12 + s21)); + s22 = a20*b20 + (a21*b21 + (a22*b22 + s22)); + + a0 += 3; b0 += 3; + a1 += 3; b1 += 3; + a2 += 3; b2 += 3; + } + + c[(i+0)*n+j+0] = s00; c[(i+0)*n+j+1] = s01; c[(i+0)*n+j+2] = s02; + c[(i+1)*n+j+0] = s10; c[(i+1)*n+j+1] = s11; c[(i+1)*n+j+2] = s12; + c[(i+2)*n+j+0] = s20; c[(i+2)*n+j+1] = s21; c[(i+2)*n+j+2] = s22; + } + } + + for (long i = 0; i < n0; i++) + { + long j; + for (j = 0; j < n0 - 2; j+=3) + { + c0[i*n0+j+0] = c[i*n+j+0]; + c0[i*n0+j+1] = c[i*n+j+1]; + c0[i*n0+j+2] = c[i*n+j+2]; + } + for ( ; j < n0; j++) + c0[i*n0+j] = c[i*n+j]; + } +} + +//-------------------------------------------------------------------------- +// Main + +int main( int argc, char* argv[] ) +{ + double results_data[DATA_SIZE*DATA_SIZE]; + + // Output the input array + +#if HOST_DEBUG + printArray( "input1", DATA_SIZE*DATA_SIZE, input1_data ); + printArray( "input2", DATA_SIZE*DATA_SIZE, input2_data ); + printArray( "verify", DATA_SIZE*DATA_SIZE, verify_data ); +#endif + + // If needed we preallocate everything in the caches + +#if PREALLOCATE + square_dgemm( DATA_SIZE, input1_data, input2_data, results_data ); +#endif + + // Do the dgemm + + setStats(1); + square_dgemm( DATA_SIZE, input1_data, input2_data, results_data ); + setStats(0); + + // Print out the results + +#if HOST_DEBUG + printArray( "results", DATA_SIZE*DATA_SIZE, results_data ); +#endif + + // Check the results + + finishTest(verify( DATA_SIZE*DATA_SIZE, results_data, verify_data )); + +} diff --git a/benchmarks/dhrystone/bmark.mk b/benchmarks/dhrystone/bmark.mk new file mode 100644 index 0000000..6e45706 --- /dev/null +++ b/benchmarks/dhrystone/bmark.mk @@ -0,0 +1,31 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +dhrystone_c_src = \ + dhrystone_main.c \ + dhrystone.c \ + +dhrystone_riscv_src = \ + crt.S \ + +dhrystone_c_objs = $(patsubst %.c, %.o, $(dhrystone_c_src)) +dhrystone_riscv_objs = $(patsubst %.S, %.o, $(dhrystone_riscv_src)) + +dhrystone_host_bin = dhrystone.host +$(dhrystone_host_bin): $(dhrystone_c_src) + $(HOST_COMP) $^ -o $(dhrystone_host_bin) + +dhrystone_riscv_bin = dhrystone.riscv +$(dhrystone_riscv_bin): $(dhrystone_c_objs) $(dhrystone_riscv_objs) + $(RISCV_LINK) $(dhrystone_c_objs) $(dhrystone_riscv_objs) \ + -o $(dhrystone_riscv_bin) $(RISCV_LINK_OPTS) + +junk += $(dhrystone_c_objs) $(dhrystone_riscv_objs) \ + $(dhrystone_host_bin) $(dhrystone_riscv_bin) diff --git a/benchmarks/dhrystone/dhrystone.c b/benchmarks/dhrystone/dhrystone.c new file mode 100644 index 0000000..abc45d4 --- /dev/null +++ b/benchmarks/dhrystone/dhrystone.c @@ -0,0 +1,160 @@ +#include "dhrystone.h" + +#ifndef REG +#define REG + /* REG becomes defined as empty */ + /* i.e. no register variables */ +#else +#undef REG +#define REG register +#endif + +extern int Int_Glob; +extern char Ch_1_Glob; + + +void Proc_6(Enumeration Enum_Val_Par, Enumeration* Enum_Ref_Par) +/*********************************/ + /* executed once */ + /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */ +{ + *Enum_Ref_Par = Enum_Val_Par; + if (! Func_3 (Enum_Val_Par)) + /* then, not executed */ + *Enum_Ref_Par = Ident_4; + switch (Enum_Val_Par) + { + case Ident_1: + *Enum_Ref_Par = Ident_1; + break; + case Ident_2: + if (Int_Glob > 100) + /* then */ + *Enum_Ref_Par = Ident_1; + else *Enum_Ref_Par = Ident_4; + break; + case Ident_3: /* executed */ + *Enum_Ref_Par = Ident_2; + break; + case Ident_4: break; + case Ident_5: + *Enum_Ref_Par = Ident_3; + break; + } /* switch */ +} /* Proc_6 */ + + +void Proc_7(int Int_1_Par_Val, int Int_2_Par_Val, int* Int_Par_Ref) +/**********************************************/ + /* executed three times */ + /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */ + /* Int_Par_Ref becomes 7 */ + /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */ + /* Int_Par_Ref becomes 17 */ + /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */ + /* Int_Par_Ref becomes 18 */ +{ + One_Fifty Int_Loc; + + Int_Loc = Int_1_Par_Val + 2; + *Int_Par_Ref = Int_2_Par_Val + Int_Loc; +} /* Proc_7 */ + + +void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val) +/*********************************************************************/ + /* executed once */ + /* Int_Par_Val_1 == 3 */ + /* Int_Par_Val_2 == 7 */ +{ + REG One_Fifty Int_Index; + REG One_Fifty Int_Loc; + + Int_Loc = Int_1_Par_Val + 5; + Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val; + Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc]; + Arr_1_Par_Ref [Int_Loc+30] = Int_Loc; + for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index) + Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc; + Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1; + Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc]; + Int_Glob = 5; +} /* Proc_8 */ + + +Enumeration Func_1 (char Ch_1_Par_Val, char Ch_2_Par_Val) +/*************************************************/ + /* executed three times */ + /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */ + /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */ + /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */ +{ + Capital_Letter Ch_1_Loc; + Capital_Letter Ch_2_Loc; + + Ch_1_Loc = Ch_1_Par_Val; + Ch_2_Loc = Ch_1_Loc; + if (Ch_2_Loc != Ch_2_Par_Val) + /* then, executed */ + return (Ident_1); + else /* not executed */ + { + Ch_1_Glob = Ch_1_Loc; + return (Ident_2); + } +} /* Func_1 */ + + +Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref) +/*************************************************/ + /* executed once */ + /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */ + /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */ +{ + REG One_Thirty Int_Loc; + Capital_Letter Ch_Loc; + + Int_Loc = 2; + while (Int_Loc <= 2) /* loop body executed once */ + if (Func_1 (Str_1_Par_Ref[Int_Loc], + Str_2_Par_Ref[Int_Loc+1]) == Ident_1) + /* then, executed */ + { + Ch_Loc = 'A'; + Int_Loc += 1; + } /* if, while */ + if (Ch_Loc >= 'W' && Ch_Loc < 'Z') + /* then, not executed */ + Int_Loc = 7; + if (Ch_Loc == 'R') + /* then, not executed */ + return (true); + else /* executed */ + { + if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0) + /* then, not executed */ + { + Int_Loc += 7; + Int_Glob = Int_Loc; + return (true); + } + else /* executed */ + return (false); + } /* if Ch_Loc */ +} /* Func_2 */ + + +Boolean Func_3(Enumeration Enum_Par_Val) +/***************************/ + /* executed once */ + /* Enum_Par_Val == Ident_3 */ +{ + Enumeration Enum_Loc; + + Enum_Loc = Enum_Par_Val; + if (Enum_Loc == Ident_3) + /* then, executed */ + return (true); + else /* not executed */ + return (false); +} /* Func_3 */ diff --git a/benchmarks/dhrystone/dhrystone.h b/benchmarks/dhrystone/dhrystone.h new file mode 100644 index 0000000..8abb874 --- /dev/null +++ b/benchmarks/dhrystone/dhrystone.h @@ -0,0 +1,491 @@ +#ifndef _DHRYSTONE_H +#define _DHRYSTONE_H + +/****************** "DHRYSTONE" Benchmark Program ***************************/ +#define Version "C, Version 2.2" +/* File: dhry_1.c (part 2 of 3) + * Author: Reinhold P. Weicker + * Siemens Nixdorf, Paderborn/Germany + * weicker@specbench.org + * Date: May 25, 1988 + * Modified: Steven Pemberton, CWI, Amsterdam; Steven.Pemberton@cwi.nl + * Date: October, 1993; March 1995 + * Included both files into one source, that gets compiled + * in two passes. Made program auto-compiling, and auto-running, + * and generally made it much easier to use. + * + * Original Version (in Ada) published in + * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984), + * pp. 1013 - 1030, together with the statistics + * on which the distribution of statements etc. is based. + * + * In this C version, the following C library functions are used: + * - strcpy, strcmp (inside the measurement loop) + * - printf, scanf (outside the measurement loop) + * In addition, Berkeley UNIX system calls "times ()" or "time ()" + * are used for execution time measurement. For measurements + * on other systems, these calls have to be changed. + * + * Collection of Results: + * Reinhold Weicker (address see above) and + * + * Rick Richardson + * PC Research. Inc. + * 94 Apple Orchard Drive + * Tinton Falls, NJ 07724 + * Phone: (201) 389-8963 (9-17 EST) + * Usenet: ...!uunet!pcrat!rick + * + * Please send results to Rick Richardson and/or Reinhold Weicker. + * Complete information should be given on hardware and software used. + * Hardware information includes: Machine type, CPU, type and size + * of caches; for microprocessors: clock frequency, memory speed + * (number of wait states). + * Software information includes: Compiler (and runtime library) + * manufacturer and version, compilation switches, OS version. + * The Operating System version may give an indication about the compiler; + * Dhrystone itself performs no OS calls in the measurement loop. + * + * The complete output generated by the program should be mailed + * such that at least some checks for correctness can be made. + * + *************************************************************************** + * + * Defines: The following "Defines" are possible: + * -DREG (default: Not defined) + * As an approximation to what an average C programmer + * might do, causes the "register" storage class to be applied + * - for local variables, if they are used (dynamically) + * five or more times + * - for parameters if they are used (dynamically) + * six or more times + * Note that an optimal "register" strategy is + * compiler-dependent, and that "register" declarations + * do not necessarily lead to faster execution. + * -DNOSTRUCTASSIGN (default: Not defined) + * Define if the C compiler does not support + * assignment of structures. + * -DNOENUMS (default: Not defined) + * Define if the C compiler does not support + * enumeration types. + * -DTIMES (default) + * -DTIME + * The "times" function of UNIX (returning process times) + * or the "time" function (returning wallclock time) + * is used for measurement. + * For single user machines, "time ()" is adequate. For + * multi-user machines where you cannot get single-user + * access, use the "times ()" function. If you have + * neither, use a stopwatch in the dead of night. + * "printf"s are provided marking the points "Start Timer" + * and "Stop Timer". DO NOT use the UNIX "time(1)" + * command, as this will measure the total time to + * run this program, which will (erroneously) include + * the time to allocate storage (malloc) and to perform + * the initialization. + * -DHZ=nnn + * In Berkeley UNIX, the function "times" returns process + * time in 1/HZ seconds, with HZ = 60 for most systems. + * CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY + * A VALUE. + * + *************************************************************************** + * + * History: Version C/2.1 was made for two reasons: + * + * 1) There was an obvious need for a common C version of + * Dhrystone, since C is at present the most popular system + * programming language for the class of processors + * (microcomputers, minicomputers) where Dhrystone is used most. + * There should be, as far as possible, only one C version of + * Dhrystone such that results can be compared without + * restrictions. In the past, the C versions distributed + * by Rick Richardson (Version 1.1) and by Reinhold Weicker + * had small (though not significant) differences. + * + * 2) As far as it is possible without changes to the Dhrystone + * statistics, optimizing compilers should be prevented from + * removing significant statements. + * + * This C version has been developed in cooperation with + * Rick Richardson (Tinton Falls, NJ), it incorporates many + * ideas from the "Version 1.1" distributed previously by + * him over the UNIX network Usenet. + * I also thank Chaim Benedelac (National Semiconductor), + * David Ditzel (SUN), Earl Killian and John Mashey (MIPS), + * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) + * for their help with comments on earlier versions of the + * benchmark. + * + * Changes: In the initialization part, this version follows mostly + * Rick Richardson's version distributed via Usenet, not the + * version distributed earlier via floppy disk by Reinhold Weicker. + * As a concession to older compilers, names have been made + * unique within the first 8 characters. + * Inside the measurement loop, this version follows the + * version previously distributed by Reinhold Weicker. + * + * At several places in the benchmark, code has been added, + * but within the measurement loop only in branches that + * are not executed. The intention is that optimizing compilers + * should be prevented from moving code out of the measurement + * loop, or from removing code altogether. Since the statements + * that are executed within the measurement loop have NOT been + * changed, the numbers defining the "Dhrystone distribution" + * (distribution of statements, operand types and locality) + * still hold. Except for sophisticated optimizing compilers, + * execution times for this version should be the same as + * for previous versions. + * + * Since it has proven difficult to subtract the time for the + * measurement loop overhead in a correct way, the loop check + * has been made a part of the benchmark. This does have + * an impact - though a very minor one - on the distribution + * statistics which have been updated for this version. + * + * All changes within the measurement loop are described + * and discussed in the companion paper "Rationale for + * Dhrystone version 2". + * + * Because of the self-imposed limitation that the order and + * distribution of the executed statements should not be + * changed, there are still cases where optimizing compilers + * may not generate code for some statements. To a certain + * degree, this is unavoidable for small synthetic benchmarks. + * Users of the benchmark are advised to check code listings + * whether code is generated for all statements of Dhrystone. + * + * Version 2.1 is identical to version 2.0 distributed via + * the UNIX network Usenet in March 1988 except that it corrects + * some minor deficiencies that were found by users of version 2.0. + * The only change within the measurement loop is that a + * non-executed "else" part was added to the "if" statement in + * Func_3, and a non-executed "else" part removed from Proc_3. + * + * Version C/2.2, Steven Pemberton, October 1993 + * Functionally, identical to version 2.2; the changes are in + * how you compile and use it: + * - Everything is in one file now, but compiled in 2 passes + * - Compile (and run) by running the file through the shell: 'sh dhry.c" + * - Uses the system definition of HZ if one can be found + * - HZ must be defined, otherwise it won't compile (no defaults here) + * - The (uninteresting) output is printed to stderr (dhry2 > /dev/null) + * - The number of loops is passed as a parameter, rather than read + * (dhry2 500000) + * - If the number of loops is insufficient to get a good result, + * it repeats it with loops*10 until it is enough (rather than just + * stopping) + * - Output says which sort of clock it is using, and the HZ value + * - You can use -DREG instead of the -DREG=register of previous versions + * - Some stylistic cleanups. + * + *************************************************************************** + * + * Compilation model and measurement (IMPORTANT): + * + * The following "ground rules" apply for measurements: + * - Separate compilation + * - No procedure merging + * - Otherwise, compiler optimizations are allowed but should be indicated + * - Default results are those without register declarations + * See the companion paper "Rationale for Dhrystone Version 2" for a more + * detailed discussion of these ground rules. + * + * For 16-Bit processors (e.g. 80186, 80286), times for all compilation + * models ("small", "medium", "large" etc.) should be given if possible, + * together with a definition of these models for the compiler system used. + * + ************************************************************************** + * + * Dhrystone (C version) statistics: + * + * [Comment from the first distribution, updated for version 2. + * Note that because of language differences, the numbers are slightly + * different from the Ada version.] + * + * The following program contains statements of a high level programming + * language (here: C) in a distribution considered representative: + * + * assignments 52 (51.0 %) + * control statements 33 (32.4 %) + * procedure, function calls 17 (16.7 %) + * + * 103 statements are dynamically executed. The program is balanced with + * respect to the three aspects: + * + * - statement type + * - operand type + * - operand locality + * operand global, local, parameter, or constant. + * + * The combination of these three aspects is balanced only approximately. + * + * 1. Statement Type: + * ----------------- number + * + * V1 = V2 9 + * (incl. V1 = F(..) + * V = Constant 12 + * Assignment, 7 + * with array element + * Assignment, 6 + * with record component + * -- + * 34 34 + * + * X = Y +|-|"&&"|"|" Z 5 + * X = Y +|-|"==" Constant 6 + * X = X +|- 1 3 + * X = Y *|/ Z 2 + * X = Expression, 1 + * two operators + * X = Expression, 1 + * three operators + * -- + * 18 18 + * + * if .... 14 + * with "else" 7 + * without "else" 7 + * executed 3 + * not executed 4 + * for ... 7 | counted every time + * while ... 4 | the loop condition + * do ... while 1 | is evaluated + * switch ... 1 + * break 1 + * declaration with 1 + * initialization + * -- + * 34 34 + * + * P (...) procedure call 11 + * user procedure 10 + * library procedure 1 + * X = F (...) + * function call 6 + * user function 5 + * library function 1 + * -- + * 17 17 + * --- + * 103 + * + * The average number of parameters in procedure or function calls + * is 1.82 (not counting the function values aX * + * + * 2. Operators + * ------------ + * number approximate + * percentage + * + * Arithmetic 32 50.8 + * + * + 21 33.3 + * - 7 11.1 + * * 3 4.8 + * / (int div) 1 1.6 + * + * Comparison 27 42.8 + * + * == 9 14.3 + * /= 4 6.3 + * > 1 1.6 + * < 3 4.8 + * >= 1 1.6 + * <= 9 14.3 + * + * Logic 4 6.3 + * + * && (AND-THEN) 1 1.6 + * | (OR) 1 1.6 + * ! (NOT) 2 3.2 + * + * -- ----- + * 63 100.1 + * + * + * 3. Operand Type (counted once per operand reference): + * --------------- + * number approximate + * percentage + * + * Integer 175 72.3 % + * Character 45 18.6 % + * Pointer 12 5.0 % + * String30 6 2.5 % + * Array 2 0.8 % + * Record 2 0.8 % + * --- ------- + * 242 100.0 % + * + * When there is an access path leading to the final operand (e.g. a record + * component), only the final data type on the access path is counted. + * + * + * 4. Operand Locality: + * ------------------- + * number approximate + * percentage + * + * local variable 114 47.1 % + * global variable 22 9.1 % + * parameter 45 18.6 % + * value 23 9.5 % + * reference 22 9.1 % + * function result 6 2.5 % + * constant 55 22.7 % + * --- ------- + * 242 100.0 % + * + * The program does not compute anything meaningful, but it is syntactically + * and semantically correct. All variables have a value assigned to them + * before they are used as a source operand. + * + * There has been no explicit effort to account for the effects of a + * cache, or to balance the use of long or short displacements for code or + * data. + * + *************************************************************************** + */ + +/* Compiler and system dependent definitions: */ + +/* variables for time measurement: */ + +#ifdef TIME + +#define CLOCK_TYPE "time()" +#undef HZ +#define HZ (1) /* time() returns time in seconds */ +extern long time(); /* see library function "time" */ +#define Too_Small_Time 2 /* Measurements should last at least 2 seconds */ +#define Start_Timer() Begin_Time = time ( (long *) 0) +#define Stop_Timer() End_Time = time ( (long *) 0) + +#else + +#ifdef MSC_CLOCK /* Use Microsoft C hi-res clock */ + +#undef HZ +#undef TIMES +#include +#define HZ CLK_TCK +#define CLOCK_TYPE "MSC clock()" +extern clock_t clock(); +#define Too_Small_Time (2*HZ) +#define Start_Timer() Begin_Time = clock() +#define Stop_Timer() End_Time = clock() + +#elif defined(__riscv) + +#define HZ 976563 +#define Too_Small_Time 50 +#define rdcycle() ({ \ + long __x; \ + asm volatile("rdcycle %0; srl %0, %0, 10" : "=r"(__x)); \ + __x; }) +#define CLOCK_TYPE "rdcycle()" +#define Start_Timer() Begin_Time = rdcycle() +#define Stop_Timer() End_Time = rdcycle() + +#else + /* Use times(2) time function unless */ + /* explicitly defined otherwise */ +#define CLOCK_TYPE "times()" +#include +#include +#ifndef HZ /* Added by SP 900619 */ +#include /* If your system doesn't have this, use -DHZ=xxx */ +#else + *** You must define HZ!!! *** +#endif /* HZ */ +#ifndef PASS2 +struct tms time_info; +#endif +/*extern int times ();*/ + /* see library function "times" */ +#define Too_Small_Time (2*HZ) + /* Measurements should last at least about 2 seconds */ +#define Start_Timer() times(&time_info); Begin_Time=(long)time_info.tms_utime +#define Stop_Timer() times(&time_info); End_Time = (long)time_info.tms_utime + +#endif /* MSC_CLOCK */ +#endif /* TIME */ + + +#define Mic_secs_Per_Second 1000000.0 +#define NUMBER_OF_RUNS 500 /* Default number of runs */ + +#ifdef NOSTRUCTASSIGN +#define structassign(d, s) memcpy(&(d), &(s), sizeof(d)) +#else +#define structassign(d, s) d = s +#endif + +#ifdef NOENUM +#define Ident_1 0 +#define Ident_2 1 +#define Ident_3 2 +#define Ident_4 3 +#define Ident_5 4 + typedef int Enumeration; +#else + typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5} + Enumeration; +#endif + /* for boolean and enumeration types in Ada, Pascal */ + +/* General definitions: */ + +#include +#include + /* for strcpy, strcmp */ + +#define Null 0 + /* Value of a Null pointer */ +#define true 1 +#define false 0 + +typedef int One_Thirty; +typedef int One_Fifty; +typedef char Capital_Letter; +typedef int Boolean; +typedef char Str_30 [31]; +typedef int Arr_1_Dim [50]; +typedef int Arr_2_Dim [50] [50]; + +typedef struct record + { + struct record *Ptr_Comp; + Enumeration Discr; + union { + struct { + Enumeration Enum_Comp; + int Int_Comp; + char Str_Comp [31]; + } var_1; + struct { + Enumeration E_Comp_2; + char Str_2_Comp [31]; + } var_2; + struct { + char Ch_1_Comp; + char Ch_2_Comp; + } var_3; + } variant; + } Rec_Type, *Rec_Pointer; + +void Proc_1(Rec_Pointer Ptr_Val_Par); +void Proc_2(int* Int_Par_Ref); +void Proc_3(Rec_Pointer* Ptr_Ref_Par); +void Proc_4(); +void Proc_5(); +void Proc_6(Enumeration Enum_Val_Par, Enumeration* Enum_Ref_Par); +void Proc_7(int Int_1_Par_Val, int Int_2_Par_Val, int* Int_Par_Ref); +void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val); +Enumeration Func_1 (char Ch_1_Par_Val, char Ch_2_Par_Val); +Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref); +Boolean Func_3(Enumeration Enum_Par_Val); + +#endif diff --git a/benchmarks/dhrystone/dhrystone_main.c b/benchmarks/dhrystone/dhrystone_main.c new file mode 100644 index 0000000..7e8c6af --- /dev/null +++ b/benchmarks/dhrystone/dhrystone_main.c @@ -0,0 +1,400 @@ +//************************************************************************** +// Dhrystone bencmark +//-------------------------------------------------------------------------- +// +// This is the classic Dhrystone synthetic integer benchmark. +// You should not change anything except the HOST_DEBUG and +// PREALLOCATE macros for your timing run. + +#include "dhrystone.h" + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +#if HOST_DEBUG +# define do_fprintf fprintf +#else +int __attribute__((noinline)) do_fprintf(FILE* f, const char* str, ...) +{ + return 0; +} +#endif + +void finishTest( int toHostValue ) +{ +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + asm( "mtpcr %0, cr30" : : "r" (toHostValue) ); + while ( 1 ) { } +#endif +} + +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +#include + +/* Global Variables: */ + +Rec_Pointer Ptr_Glob, + Next_Ptr_Glob; +int Int_Glob; +Boolean Bool_Glob; +char Ch_1_Glob, + Ch_2_Glob; +int Arr_1_Glob [50]; +int Arr_2_Glob [50] [50]; + +#ifndef REG + Boolean Reg = false; +#define REG + /* REG becomes defined as empty */ + /* i.e. no register variables */ +#else + Boolean Reg = true; +#undef REG +#define REG register +#endif + +Boolean Done; + +long Begin_Time, + End_Time, + User_Time; +float Microseconds, + Dhrystones_Per_Second; + +/* end of variables for time measurement */ + + +int main (int argc, char** argv) +/*****/ + /* main program, corresponds to procedures */ + /* Main and Proc_0 in the Ada version */ +{ + One_Fifty Int_1_Loc; + REG One_Fifty Int_2_Loc; + One_Fifty Int_3_Loc; + REG char Ch_Index; + Enumeration Enum_Loc; + Str_30 Str_1_Loc; + Str_30 Str_2_Loc; + REG int Run_Index; + REG int Number_Of_Runs; + + /* Arguments */ +#if HOST_DEBUG + if (argc > 2) + { + do_fprintf (stdout, "Usage: %s [number of loops]\n", argv[0]); + exit (1); + } + if (argc == 2) + { + Number_Of_Runs = atoi (argv[1]); + } else +#endif + { + Number_Of_Runs = NUMBER_OF_RUNS; + } + if (Number_Of_Runs <= 0) + { + Number_Of_Runs = NUMBER_OF_RUNS; + } + + /* Initializations */ + + Next_Ptr_Glob = (Rec_Pointer) alloca (sizeof (Rec_Type)); + Ptr_Glob = (Rec_Pointer) alloca (sizeof (Rec_Type)); + + Ptr_Glob->Ptr_Comp = Next_Ptr_Glob; + Ptr_Glob->Discr = Ident_1; + Ptr_Glob->variant.var_1.Enum_Comp = Ident_3; + Ptr_Glob->variant.var_1.Int_Comp = 40; + strcpy (Ptr_Glob->variant.var_1.Str_Comp, + "DHRYSTONE PROGRAM, SOME STRING"); + strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); + + Arr_2_Glob [8][7] = 10; + /* Was missing in published program. Without this statement, */ + /* Arr_2_Glob [8][7] would have an undefined value. */ + /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */ + /* overflow may occur for this array element. */ + +#if HOST_DEBUG + do_fprintf (stdout, "\n"); + do_fprintf (stdout, "Dhrystone Benchmark, Version %s\n", Version); + if (Reg) + { + do_fprintf (stdout, "Program compiled with 'register' attribute\n"); + } + else + { + do_fprintf (stdout, "Program compiled without 'register' attribute\n"); + } + do_fprintf (stdout, "Using %s, HZ=%d\n", CLOCK_TYPE, HZ); + do_fprintf (stdout, "\n"); +#endif + + Done = false; + while (!Done) { +#if HOST_DEBUG + do_fprintf (stdout, "Trying %d runs through Dhrystone:\n", Number_Of_Runs); +#endif + + /***************/ + /* Start timer */ + /***************/ + + Start_Timer(); + setStats(1); + + for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) + { + + Proc_5(); + Proc_4(); + /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ + Int_1_Loc = 2; + Int_2_Loc = 3; + strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); + Enum_Loc = Ident_2; + Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc); + /* Bool_Glob == 1 */ + while (Int_1_Loc < Int_2_Loc) /* loop body executed once */ + { + Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; + /* Int_3_Loc == 7 */ + Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); + /* Int_3_Loc == 7 */ + Int_1_Loc += 1; + } /* while */ + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); + /* Int_Glob == 5 */ + Proc_1 (Ptr_Glob); + for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) + /* loop body executed twice */ + { + if (Enum_Loc == Func_1 (Ch_Index, 'C')) + /* then, not executed */ + { + Proc_6 (Ident_1, &Enum_Loc); + strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); + Int_2_Loc = Run_Index; + Int_Glob = Run_Index; + } + } + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Int_2_Loc = Int_2_Loc * Int_1_Loc; + Int_1_Loc = Int_2_Loc / Int_3_Loc; + Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; + /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ + Proc_2 (&Int_1_Loc); + /* Int_1_Loc == 5 */ + + } /* loop "for Run_Index" */ + + /**************/ + /* Stop timer */ + /**************/ + + setStats(0); + Stop_Timer(); + + User_Time = End_Time - Begin_Time; + + if (User_Time < Too_Small_Time) + { + do_fprintf (stdout, "Measured time too small to obtain meaningful results\n"); + Number_Of_Runs = Number_Of_Runs * 10; + do_fprintf (stdout, "\n"); + } else Done = true; + } + + do_fprintf (stderr, "Final values of the variables used in the benchmark:\n"); + do_fprintf (stderr, "\n"); + do_fprintf (stderr, "Int_Glob: %d\n", Int_Glob); + do_fprintf (stderr, " should be: %d\n", 5); + do_fprintf (stderr, "Bool_Glob: %d\n", Bool_Glob); + do_fprintf (stderr, " should be: %d\n", 1); + do_fprintf (stderr, "Ch_1_Glob: %c\n", Ch_1_Glob); + do_fprintf (stderr, " should be: %c\n", 'A'); + do_fprintf (stderr, "Ch_2_Glob: %c\n", Ch_2_Glob); + do_fprintf (stderr, " should be: %c\n", 'B'); + do_fprintf (stderr, "Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]); + do_fprintf (stderr, " should be: %d\n", 7); + do_fprintf (stderr, "Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]); + do_fprintf (stderr, " should be: Number_Of_Runs + 10\n"); + do_fprintf (stderr, "Ptr_Glob->\n"); + do_fprintf (stderr, " Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp); + do_fprintf (stderr, " should be: (implementation-dependent)\n"); + do_fprintf (stderr, " Discr: %d\n", Ptr_Glob->Discr); + do_fprintf (stderr, " should be: %d\n", 0); + do_fprintf (stderr, " Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp); + do_fprintf (stderr, " should be: %d\n", 2); + do_fprintf (stderr, " Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp); + do_fprintf (stderr, " should be: %d\n", 17); + do_fprintf (stderr, " Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp); + do_fprintf (stderr, " should be: DHRYSTONE PROGRAM, SOME STRING\n"); + do_fprintf (stderr, "Next_Ptr_Glob->\n"); + do_fprintf (stderr, " Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp); + do_fprintf (stderr, " should be: (implementation-dependent), same as above\n"); + do_fprintf (stderr, " Discr: %d\n", Next_Ptr_Glob->Discr); + do_fprintf (stderr, " should be: %d\n", 0); + do_fprintf (stderr, " Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp); + do_fprintf (stderr, " should be: %d\n", 1); + do_fprintf (stderr, " Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp); + do_fprintf (stderr, " should be: %d\n", 18); + do_fprintf (stderr, " Str_Comp: %s\n", + Next_Ptr_Glob->variant.var_1.Str_Comp); + do_fprintf (stderr, " should be: DHRYSTONE PROGRAM, SOME STRING\n"); + do_fprintf (stderr, "Int_1_Loc: %d\n", Int_1_Loc); + do_fprintf (stderr, " should be: %d\n", 5); + do_fprintf (stderr, "Int_2_Loc: %d\n", Int_2_Loc); + do_fprintf (stderr, " should be: %d\n", 13); + do_fprintf (stderr, "Int_3_Loc: %d\n", Int_3_Loc); + do_fprintf (stderr, " should be: %d\n", 7); + do_fprintf (stderr, "Enum_Loc: %d\n", Enum_Loc); + do_fprintf (stderr, " should be: %d\n", 1); + do_fprintf (stderr, "Str_1_Loc: %s\n", Str_1_Loc); + do_fprintf (stderr, " should be: DHRYSTONE PROGRAM, 1'ST STRING\n"); + do_fprintf (stderr, "Str_2_Loc: %s\n", Str_2_Loc); + do_fprintf (stderr, " should be: DHRYSTONE PROGRAM, 2'ND STRING\n"); + do_fprintf (stderr, "\n"); + + +#if HOST_DEBUG + Microseconds = (float) User_Time * Mic_secs_Per_Second + / ((float) HZ * ((float) Number_Of_Runs)); + Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs) + / (float) User_Time; + + do_fprintf (stdout, "Microseconds for one run through Dhrystone: "); + do_fprintf (stdout, "%10.1f \n", Microseconds); + do_fprintf (stdout, "Dhrystones per Second: "); + do_fprintf (stdout, "%10.0f \n", Dhrystones_Per_Second); + do_fprintf (stdout, "\n"); +#endif + + finishTest(1); +} + + +void Proc_1(Rec_Pointer Ptr_Val_Par) +/******************/ + /* executed once */ +{ + REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp; + /* == Ptr_Glob_Next */ + /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */ + /* corresponds to "rename" in Ada, "with" in Pascal */ + + structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); + Ptr_Val_Par->variant.var_1.Int_Comp = 5; + Next_Record->variant.var_1.Int_Comp + = Ptr_Val_Par->variant.var_1.Int_Comp; + Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp; + Proc_3 (&Next_Record->Ptr_Comp); + /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp + == Ptr_Glob->Ptr_Comp */ + if (Next_Record->Discr == Ident_1) + /* then, executed */ + { + Next_Record->variant.var_1.Int_Comp = 6; + Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, + &Next_Record->variant.var_1.Enum_Comp); + Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp; + Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, + &Next_Record->variant.var_1.Int_Comp); + } + else /* not executed */ + structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp); +} /* Proc_1 */ + + +void Proc_2(int* Int_Par_Ref) +/******************/ + /* executed once */ + /* *Int_Par_Ref == 1, becomes 4 */ +{ + One_Fifty Int_Loc; + Enumeration Enum_Loc; + + Int_Loc = *Int_Par_Ref + 10; + do /* executed once */ + if (Ch_1_Glob == 'A') + /* then, executed */ + { + Int_Loc -= 1; + *Int_Par_Ref = Int_Loc - Int_Glob; + Enum_Loc = Ident_1; + } /* if */ + while (Enum_Loc != Ident_1); /* true */ +} /* Proc_2 */ + + +void Proc_3(Rec_Pointer* Ptr_Ref_Par) +/******************/ + /* executed once */ + /* Ptr_Ref_Par becomes Ptr_Glob */ +{ + if (Ptr_Glob != Null) + /* then, executed */ + *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp; + Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp); +} /* Proc_3 */ + + +void Proc_4() +/*******/ + /* executed once */ +{ + Boolean Bool_Loc; + + Bool_Loc = Ch_1_Glob == 'A'; + Bool_Glob = Bool_Loc | Bool_Glob; + Ch_2_Glob = 'B'; +} /* Proc_4 */ + + +void Proc_5() +/*******/ + /* executed once */ +{ + Ch_1_Glob = 'A'; + Bool_Glob = false; +} /* Proc_5 */ diff --git a/benchmarks/median/bmark.mk b/benchmarks/median/bmark.mk new file mode 100644 index 0000000..31c853a --- /dev/null +++ b/benchmarks/median/bmark.mk @@ -0,0 +1,30 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +median_c_src = \ + median_main.c \ + median.c \ + +median_riscv_src = \ + crt.S \ + +median_c_objs = $(patsubst %.c, %.o, $(median_c_src)) +median_riscv_objs = $(patsubst %.S, %.o, $(median_riscv_src)) + +median_host_bin = median.host +$(median_host_bin): $(median_c_src) + $(HOST_COMP) $^ -o $(median_host_bin) + +median_riscv_bin = median.riscv +$(median_riscv_bin): $(median_c_objs) $(median_riscv_objs) + $(RISCV_LINK) $(median_c_objs) $(median_riscv_objs) -o $(median_riscv_bin) + +junk += $(median_c_objs) $(median_riscv_objs) \ + $(median_host_bin) $(median_riscv_bin) diff --git a/benchmarks/median/dataset1.h b/benchmarks/median/dataset1.h new file mode 100644 index 0000000..a7bc568 --- /dev/null +++ b/benchmarks/median/dataset1.h @@ -0,0 +1,51 @@ + +#define DATA_SIZE 400 + +int input_data[DATA_SIZE] = +{ + 41, 454, 833, 335, 564, 1, 187, 989, 749, 365, 350, 572, 132, 64, 949, 153, 584, 216, 805, 140, + 621, 210, 6, 572, 931, 339, 890, 593, 392, 898, 694, 228, 961, 12, 110, 883, 116, 750, 296, 646, + 426, 500, 314, 436, 659, 701, 774, 812, 319, 981, 678, 150, 875, 696, 376, 564, 474, 272, 938, 258, + 539, 647, 569, 509, 203, 88, 280, 703, 759, 669, 606, 375, 511, 551, 657, 936, 195, 592, 81, 569, + 267, 952, 229, 800, 337, 584, 944, 643, 902, 368, 241, 489, 913, 328, 826, 313, 933, 592, 985, 388, + 195, 543, 960, 649, 566, 979, 350, 997, 649, 814, 657, 79, 181, 208, 111, 998, 859, 629, 65, 847, + 288, 704, 349, 997, 141, 253, 905, 715, 886, 430, 264, 415, 576, 538, 979, 700, 761, 4, 241, 494, + 478, 100, 499, 864, 403, 693, 222, 416, 444, 296, 721, 285, 676, 620, 317, 78, 224, 351, 937, 540, + 288, 646, 119, 169, 615, 527, 606, 289, 389, 796, 351, 801, 455, 720, 278, 758, 367, 745, 358, 92, + 584, 989, 62, 271, 985, 853, 403, 788, 346, 531, 517, 222, 559, 461, 908, 241, 775, 358, 255, 332, + 778, 684, 598, 740, 143, 446, 33, 311, 125, 743, 941, 557, 933, 479, 799, 557, 553, 925, 431, 796, + 648, 357, 952, 891, 287, 666, 19, 514, 49, 557, 86, 870, 95, 853, 441, 440, 587, 61, 614, 678, + 382, 396, 280, 9, 808, 17, 971, 170, 819, 291, 344, 380, 450, 536, 512, 185, 965, 917, 347, 539, + 808, 983, 882, 887, 537, 54, 946, 612, 701, 951, 356, 479, 567, 151, 891, 7, 22, 641, 568, 335, + 665, 730, 423, 95, 434, 728, 158, 280, 2, 395, 84, 688, 247, 911, 49, 476, 435, 815, 792, 729, + 869, 265, 486, 127, 414, 236, 369, 214, 548, 180, 518, 6, 888, 503, 682, 596, 284, 173, 264, 643, + 499, 346, 290, 599, 897, 68, 215, 849, 731, 658, 688, 619, 251, 121, 786, 131, 555, 828, 302, 667, + 528, 433, 544, 487, 322, 753, 947, 125, 287, 626, 824, 14, 304, 10, 788, 403, 733, 106, 959, 703, + 366, 818, 722, 964, 294, 406, 975, 874, 653, 856, 748, 86, 91, 60, 378, 660, 105, 667, 102, 153, + 381, 121, 651, 98, 825, 412, 840, 236, 356, 12, 148, 423, 54, 965, 140, 216, 955, 621, 343, 361 +}; + +int verify_data[DATA_SIZE] = +{ + 0, 454, 454, 564, 335, 187, 187, 749, 749, 365, 365, 350, 132, 132, 153, 584, 216, 584, 216, 621, + 210, 210, 210, 572, 572, 890, 593, 593, 593, 694, 694, 694, 228, 110, 110, 116, 750, 296, 646, 426, + 500, 426, 436, 436, 659, 701, 774, 774, 812, 678, 678, 678, 696, 696, 564, 474, 474, 474, 272, 539, + 539, 569, 569, 509, 203, 203, 280, 703, 703, 669, 606, 511, 511, 551, 657, 657, 592, 195, 569, 267, + 569, 267, 800, 337, 584, 584, 643, 902, 643, 368, 368, 489, 489, 826, 328, 826, 592, 933, 592, 388, + 388, 543, 649, 649, 649, 566, 979, 649, 814, 657, 657, 181, 181, 181, 208, 859, 859, 629, 629, 288, + 704, 349, 704, 349, 253, 253, 715, 886, 715, 430, 415, 415, 538, 576, 700, 761, 700, 241, 241, 478, + 478, 478, 499, 499, 693, 403, 416, 416, 416, 444, 296, 676, 620, 620, 317, 224, 224, 351, 540, 540, + 540, 288, 169, 169, 527, 606, 527, 389, 389, 389, 796, 455, 720, 455, 720, 367, 745, 367, 358, 358, + 584, 584, 271, 271, 853, 853, 788, 403, 531, 517, 517, 517, 461, 559, 461, 775, 358, 358, 332, 332, + 684, 684, 684, 598, 446, 143, 311, 125, 311, 743, 743, 933, 557, 799, 557, 557, 557, 553, 796, 648, + 648, 648, 891, 891, 666, 287, 514, 49, 514, 86, 557, 95, 853, 441, 441, 441, 440, 587, 614, 614, + 396, 382, 280, 280, 17, 808, 170, 819, 291, 344, 344, 380, 450, 512, 512, 512, 917, 917, 539, 539, + 808, 882, 887, 882, 537, 537, 612, 701, 701, 701, 479, 479, 479, 567, 151, 22, 22, 568, 568, 568, + 665, 665, 423, 423, 434, 434, 280, 158, 280, 84, 395, 247, 688, 247, 476, 435, 476, 792, 792, 792, + 729, 486, 265, 414, 236, 369, 236, 369, 214, 518, 180, 518, 503, 682, 596, 596, 284, 264, 264, 499, + 499, 346, 346, 599, 599, 215, 215, 731, 731, 688, 658, 619, 251, 251, 131, 555, 555, 555, 667, 528, + 528, 528, 487, 487, 487, 753, 753, 287, 287, 626, 626, 304, 14, 304, 403, 733, 403, 733, 703, 703, + 703, 722, 818, 722, 406, 406, 874, 874, 856, 748, 748, 91, 86, 91, 378, 378, 660, 105, 153, 153, + 153, 381, 121, 651, 412, 825, 412, 356, 236, 148, 148, 148, 423, 140, 216, 216, 621, 621, 361, 0 +}; + diff --git a/benchmarks/median/median.c b/benchmarks/median/median.c new file mode 100644 index 0000000..3c509cc --- /dev/null +++ b/benchmarks/median/median.c @@ -0,0 +1,40 @@ +//************************************************************************** +// Median filter (c version) +//-------------------------------------------------------------------------- + +void median( int n, int input[], int results[] ) +{ + int A, B, C, i; + + // Zero the ends + results[0] = 0; + results[n-1] = 0; + + // Do the filter + for ( i = 1; i < (n-1); i++ ) { + + A = input[i-1]; + B = input[i]; + C = input[i+1]; + + if ( A < B ) { + if ( B < C ) + results[i] = B; + else if ( C < A ) + results[i] = A; + else + results[i] = C; + } + + else { + if ( A < C ) + results[i] = A; + else if ( C < B ) + results[i] = B; + else + results[i] = C; + } + + } + +} diff --git a/benchmarks/median/median.h b/benchmarks/median/median.h new file mode 100644 index 0000000..b8b9a94 --- /dev/null +++ b/benchmarks/median/median.h @@ -0,0 +1,9 @@ +//************************************************************************** +// Median filters +//-------------------------------------------------------------------------- + +// Simple C version +void median( int n, int input[], int results[] ); + +// Simple assembly version +void median_asm( int n, int input[], int results[] ); diff --git a/benchmarks/median/median_gendata.pl b/benchmarks/median/median_gendata.pl new file mode 100755 index 0000000..373904e --- /dev/null +++ b/benchmarks/median/median_gendata.pl @@ -0,0 +1,140 @@ +#!/usr/bin/perl -w +#========================================================================== +# median_gendata.pl +# +# Author : Christopher Batten (cbatten@mit.edu) +# Date : May 9, 2005 +# +(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm; +# +# Simple script which creates an input data set and the reference data +# for the median benchmark. +# +ENDMSG + +use strict "vars"; +use warnings; +no warnings("once"); +use Getopt::Long; + +#-------------------------------------------------------------------------- +# Command line processing +#-------------------------------------------------------------------------- + +our %opts; + +sub usage() +{ + + print "\n"; + print " Usage: median_gendata.pl [options] \n"; + print "\n"; + print " Options:\n"; + print " --help print this message\n"; + print " --size size of input data [750]\n"; + print " --seed random seed [1]\n"; + print "$usageMsg"; + + exit(); +} + +sub processCommandLine() +{ + + $opts{"help"} = 0; + $opts{"size"} = 750; + $opts{"seed"} = 1; + Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage(); + $opts{"help"} and usage(); + +} + +#-------------------------------------------------------------------------- +# Helper Functions +#-------------------------------------------------------------------------- + +sub printArray +{ + my $arrayName = $_[0]; + my $arrayRef = $_[1]; + + my $numCols = 20; + my $arrayLen = scalar(@{$arrayRef}); + + print "int ".$arrayName."[DATA_SIZE] = \n"; + print "{\n"; + + if ( $arrayLen <= $numCols ) { + print " "; + for ( my $i = 0; $i < $arrayLen; $i++ ) { + print sprintf("%3d",$arrayRef->[$i]); + if ( $i != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + else { + my $numRows = int($arrayLen/$numCols); + for ( my $j = 0; $j < $numRows; $j++ ) { + print " "; + for ( my $i = 0; $i < $numCols; $i++ ) { + my $index = $j*$numCols + $i; + print sprintf("%3d",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + if ( $arrayLen > ($numRows*$numCols) ) { + print " "; + for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) { + my $index = $numCols*$numRows + $i; + print sprintf("%3d",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + } + + print "};\n\n"; +} + +#-------------------------------------------------------------------------- +# Main +#-------------------------------------------------------------------------- + +sub main() +{ + + processCommandLine(); + srand($opts{"seed"}); + + my @values; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + push( @values, int(rand(999)) ); + } + + my @median; + $median[0] = 0; + $median[$opts{"size"}-1] = 0; + for ( my $i = 1; $i < $opts{"size"}-1; $i++ ) { + my @tempList = ( $values[$i-1], $values[$i], $values[$i+1] ); + my @sorted = sort { $a <=> $b } @tempList; + $median[$i] = $sorted[1]; + } + + print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n"; + printArray( "input_data", \@values ); + printArray( "verify_data", \@median ); + +} + +main(); + diff --git a/benchmarks/median/median_main.c b/benchmarks/median/median_main.c new file mode 100644 index 0000000..6decd3d --- /dev/null +++ b/benchmarks/median/median_main.c @@ -0,0 +1,131 @@ +//************************************************************************** +// Median filter bencmark +//-------------------------------------------------------------------------- +// +// This benchmark performs a 1D three element median filter. The +// input data (and reference data) should be generated using the +// median_gendata.pl perl script and dumped to a file named +// dataset1.h You should not change anything except the +// HOST_DEBUG and PREALLOCATE macros for your timing run. + +#include "median.h" + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +//-------------------------------------------------------------------------- +// Input/Reference Data + +#include "dataset1.h" + +//-------------------------------------------------------------------------- +// Helper functions + +int verify( int n, int test[], int correct[] ) +{ + int i; + for ( i = 0; i < n; i++ ) { + if ( test[i] != correct[i] ) { + return 2; + } + } + return 1; +} + +#if HOST_DEBUG +void printArray( char name[], int n, int arr[] ) +{ + int i; + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " %3d ", arr[i] ); + printf( "\n" ); +} +#endif + +void finishTest( int toHostValue ) +{ +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + asm( "mtpcr %0, cr30" : : "r" (toHostValue) ); + while ( 1 ) { } +#endif +} + +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +//-------------------------------------------------------------------------- +// Main + +int main( int argc, char* argv[] ) +{ + int results_data[DATA_SIZE]; + + // Output the input array + +#if HOST_DEBUG + printArray( "input", DATA_SIZE, input_data ); + printArray( "verify", DATA_SIZE, verify_data ); +#endif + + // If needed we preallocate everything in the caches + +#if ( !HOST_DEBUG && PREALLOCATE ) + median( DATA_SIZE, input_data, results_data ); +#endif + + // Do the filter + +#if HOST_DEBUG + median( DATA_SIZE, input_data, results_data ); +#else + setStats(1); + median( DATA_SIZE, input_data, results_data ); + setStats(0); +#endif + + // Print out the results + +#if HOST_DEBUG + printArray( "results", DATA_SIZE, results_data ); +#endif + + // Check the results + + finishTest(verify( DATA_SIZE, results_data, verify_data )); + +} diff --git a/benchmarks/mt-matmul/bmark.mk b/benchmarks/mt-matmul/bmark.mk new file mode 100644 index 0000000..67d6af3 --- /dev/null +++ b/benchmarks/mt-matmul/bmark.mk @@ -0,0 +1,29 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +mt_matmul_c_src = \ + mt-matmul.c \ + +mt_matmul_riscv_src = \ + crt-mt.S \ + +mt_matmul_c_objs = $(patsubst %.c, %.o, $(mt_matmul_c_src)) +mt_matmul_riscv_objs = $(patsubst %.S, %.o, $(mt_matmul_riscv_src)) + +mt_matmul_host_bin = mt-matmul.host +$(mt_matmul_host_bin) : $(mt_matmul_c_src) + $(HOST_COMP) $^ -o $(mt_matmul_host_bin) + +mt_matmul_riscv_bin = mt-matmul.riscv +$(mt_matmul_riscv_bin) : $(mt_matmul_c_objs) $(mt_matmul_riscv_objs) + $(RISCV_LINK_MT) $(RISCV_LINK_SYSCALL) $(mt_matmul_c_objs) $(mt_matmul_riscv_objs) -o $(mt_matmul_riscv_bin) + +junk += $(mt_matmul_c_objs) $(mt_matmul_riscv_objs) \ + $(mt_matmul_host_bin) $(mt_matmul_riscv_bin) diff --git a/benchmarks/mt-matmul/dataset.h b/benchmarks/mt-matmul/dataset.h new file mode 100644 index 0000000..dde3ee4 --- /dev/null +++ b/benchmarks/mt-matmul/dataset.h @@ -0,0 +1,174 @@ + +#define ARRAY_SIZE 1024 + + +#define DIM_SIZE 32 + +static data_t input1_data[ARRAY_SIZE] = +{ + 0, 3, 2, 0, 3, 1, 0, 3, 2, 3, 2, 0, 3, 3, 1, 2, 3, 0, 0, 1, + 1, 1, 2, 3, 1, 2, 3, 1, 1, 3, 2, 2, 0, 1, 3, 2, 2, 2, 0, 0, + 1, 0, 1, 3, 3, 0, 3, 3, 3, 3, 0, 3, 2, 1, 2, 2, 0, 0, 3, 0, + 1, 1, 0, 3, 3, 1, 2, 3, 3, 0, 1, 2, 1, 0, 1, 2, 2, 1, 0, 3, + 1, 0, 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 3, 1, 1, 2, 2, 3, 3, 1, + 3, 2, 0, 0, 0, 3, 3, 3, 2, 1, 2, 3, 1, 0, 0, 0, 0, 1, 2, 2, + 1, 1, 3, 3, 3, 1, 1, 2, 3, 1, 3, 3, 2, 3, 2, 1, 2, 3, 0, 2, + 2, 1, 1, 0, 0, 0, 0, 0, 1, 3, 3, 1, 1, 1, 2, 2, 3, 2, 1, 1, + 1, 1, 3, 0, 2, 2, 1, 3, 2, 1, 2, 2, 1, 3, 1, 3, 1, 3, 2, 3, + 1, 2, 1, 3, 2, 2, 0, 1, 0, 0, 1, 2, 3, 3, 1, 0, 0, 0, 3, 1, + 2, 3, 2, 3, 2, 0, 0, 0, 0, 0, 3, 1, 3, 0, 0, 0, 3, 1, 1, 1, + 1, 2, 1, 2, 3, 2, 0, 0, 2, 2, 3, 0, 3, 0, 0, 3, 0, 3, 1, 3, + 3, 1, 1, 1, 2, 2, 1, 3, 0, 3, 3, 1, 0, 0, 3, 2, 1, 3, 3, 3, + 1, 0, 1, 1, 2, 1, 0, 1, 1, 2, 2, 3, 1, 2, 2, 2, 0, 1, 3, 3, + 3, 2, 2, 1, 0, 1, 2, 0, 1, 1, 1, 1, 2, 3, 2, 2, 3, 3, 0, 0, + 2, 0, 0, 0, 3, 0, 1, 0, 3, 0, 0, 0, 3, 0, 0, 2, 0, 2, 0, 0, + 2, 3, 2, 0, 0, 3, 3, 2, 1, 1, 0, 2, 0, 0, 3, 3, 2, 3, 3, 0, + 1, 0, 2, 2, 0, 3, 3, 1, 1, 0, 2, 3, 2, 1, 1, 0, 1, 2, 1, 2, + 2, 0, 0, 1, 0, 1, 1, 0, 1, 0, 2, 3, 3, 2, 0, 0, 1, 3, 0, 3, + 3, 0, 0, 0, 0, 3, 3, 1, 0, 0, 3, 3, 2, 1, 2, 1, 3, 3, 0, 1, + 3, 0, 2, 3, 1, 3, 3, 3, 3, 3, 0, 1, 1, 3, 0, 2, 2, 3, 1, 2, + 2, 2, 1, 3, 3, 0, 3, 0, 0, 2, 0, 2, 3, 0, 1, 3, 2, 2, 0, 0, + 2, 3, 0, 2, 2, 2, 3, 1, 0, 3, 3, 3, 3, 1, 0, 3, 3, 2, 0, 3, + 2, 0, 3, 0, 2, 0, 0, 2, 2, 1, 0, 2, 3, 1, 1, 1, 1, 2, 3, 3, + 3, 0, 0, 3, 3, 3, 2, 3, 3, 1, 2, 2, 3, 1, 2, 1, 1, 3, 0, 1, + 2, 0, 2, 0, 0, 1, 3, 2, 0, 1, 3, 2, 3, 3, 0, 0, 0, 1, 0, 3, + 3, 2, 2, 2, 1, 1, 2, 2, 1, 3, 2, 0, 1, 3, 2, 0, 2, 1, 3, 0, + 0, 0, 1, 3, 3, 2, 2, 2, 3, 1, 0, 0, 1, 1, 2, 1, 3, 1, 1, 2, + 2, 3, 2, 3, 0, 2, 3, 3, 0, 3, 0, 0, 1, 0, 0, 0, 1, 3, 1, 1, + 2, 3, 2, 1, 1, 2, 2, 2, 3, 0, 1, 1, 2, 1, 2, 0, 2, 3, 1, 3, + 0, 1, 1, 3, 0, 2, 3, 0, 1, 2, 3, 2, 0, 0, 3, 3, 2, 1, 1, 2, + 3, 0, 1, 1, 1, 1, 2, 0, 1, 2, 0, 1, 1, 1, 0, 1, 3, 2, 3, 1, + 0, 2, 1, 2, 1, 3, 3, 1, 0, 2, 2, 3, 1, 3, 1, 3, 0, 1, 0, 3, + 0, 3, 2, 0, 3, 3, 3, 0, 3, 2, 2, 2, 1, 3, 0, 0, 1, 1, 3, 0, + 1, 2, 1, 0, 0, 0, 3, 2, 2, 0, 0, 2, 1, 3, 0, 0, 3, 0, 0, 2, + 1, 1, 2, 2, 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 1, 1, 3, 0, 1, 3, + 3, 2, 2, 1, 0, 3, 2, 2, 2, 3, 0, 1, 3, 3, 2, 3, 0, 3, 2, 3, + 1, 1, 0, 0, 0, 2, 3, 0, 3, 0, 1, 1, 3, 1, 3, 2, 1, 1, 2, 1, + 3, 2, 0, 2, 1, 0, 2, 3, 2, 3, 2, 1, 2, 3, 0, 0, 1, 1, 0, 0, + 2, 1, 0, 1, 2, 2, 2, 2, 0, 3, 3, 1, 0, 0, 0, 0, 3, 1, 1, 0, + 0, 0, 0, 1, 2, 2, 1, 3, 0, 2, 3, 2, 3, 2, 2, 1, 2, 2, 3, 3, + 1, 3, 0, 2, 2, 3, 3, 1, 2, 2, 2, 3, 1, 1, 1, 0, 0, 0, 3, 0, + 1, 0, 3, 1, 1, 3, 0, 1, 2, 2, 0, 0, 3, 3, 3, 3, 2, 1, 0, 0, + 1, 0, 2, 0, 1, 1, 0, 0, 3, 3, 2, 1, 1, 1, 0, 1, 1, 2, 2, 1, + 1, 2, 0, 3, 1, 3, 1, 0, 3, 0, 3, 1, 1, 1, 0, 2, 0, 3, 1, 0, + 1, 0, 2, 0, 2, 3, 3, 3, 1, 2, 3, 2, 2, 0, 1, 1, 0, 3, 3, 1, + 3, 3, 2, 0, 2, 0, 2, 2, 3, 3, 3, 0, 2, 3, 3, 1, 3, 2, 2, 2, + 0, 2, 3, 0, 2, 0, 3, 2, 2, 1, 1, 0, 2, 2, 2, 0, 2, 2, 0, 1, + 3, 2, 1, 3, 2, 2, 0, 3, 3, 1, 2, 2, 0, 0, 3, 2, 1, 2, 2, 1, + 3, 1, 2, 0, 0, 1, 1, 2, 1, 3, 2, 2, 3, 0, 2, 1, 3, 2, 1, 3, + 2, 3, 3, 1, 2, 1, 2, 2, 0, 0, 0, 3, 0, 2, 3, 1, 0, 0, 2, 3, + 3, 2, 2, 1 +}; + +static data_t input2_data[ARRAY_SIZE] = +{ + 1, 1, 0, 3, 1, 2, 0, 0, 0, 0, 0, 2, 1, 2, 3, 0, 0, 3, 3, 2, + 2, 1, 2, 3, 3, 0, 2, 2, 1, 1, 2, 2, 0, 2, 2, 1, 2, 3, 2, 2, + 3, 3, 2, 2, 1, 1, 1, 1, 2, 1, 2, 2, 3, 3, 3, 0, 0, 3, 2, 3, + 2, 3, 1, 2, 1, 1, 2, 2, 0, 1, 0, 3, 2, 1, 1, 1, 2, 0, 1, 2, + 2, 0, 2, 1, 3, 3, 2, 3, 2, 0, 3, 1, 3, 3, 2, 0, 1, 0, 1, 1, + 2, 2, 1, 1, 2, 2, 1, 2, 3, 3, 1, 3, 2, 2, 2, 3, 3, 1, 0, 2, + 1, 0, 0, 0, 1, 1, 2, 0, 3, 2, 3, 3, 0, 2, 3, 1, 0, 0, 2, 1, + 2, 0, 2, 1, 1, 2, 3, 1, 3, 2, 1, 0, 0, 0, 0, 0, 2, 2, 0, 2, + 1, 2, 0, 3, 2, 2, 0, 0, 3, 2, 1, 1, 3, 0, 2, 0, 0, 1, 0, 2, + 3, 3, 1, 3, 3, 0, 0, 2, 2, 0, 0, 0, 1, 0, 0, 1, 3, 0, 2, 1, + 3, 2, 2, 1, 3, 2, 0, 1, 2, 2, 3, 2, 1, 1, 1, 1, 3, 0, 1, 3, + 2, 2, 3, 1, 1, 2, 0, 2, 1, 1, 2, 3, 1, 0, 1, 0, 1, 1, 0, 0, + 2, 0, 3, 0, 3, 0, 3, 2, 2, 3, 3, 2, 1, 0, 2, 2, 1, 1, 0, 3, + 3, 2, 2, 0, 0, 3, 0, 1, 0, 0, 1, 2, 0, 1, 3, 0, 1, 2, 2, 0, + 0, 3, 0, 3, 0, 1, 1, 2, 0, 0, 0, 3, 0, 0, 2, 1, 1, 1, 0, 2, + 1, 3, 1, 2, 0, 3, 0, 3, 1, 3, 0, 0, 2, 2, 2, 2, 3, 3, 2, 1, + 2, 2, 1, 1, 2, 2, 2, 2, 0, 3, 0, 0, 2, 0, 1, 2, 0, 3, 2, 3, + 2, 0, 2, 1, 2, 1, 0, 2, 1, 1, 3, 2, 2, 3, 1, 0, 3, 3, 1, 0, + 3, 2, 2, 0, 0, 3, 0, 0, 2, 0, 3, 2, 3, 1, 1, 0, 0, 2, 3, 0, + 0, 1, 1, 1, 2, 1, 3, 2, 1, 3, 0, 1, 3, 3, 1, 1, 1, 1, 1, 1, + 0, 0, 2, 3, 2, 2, 2, 3, 2, 3, 1, 2, 3, 2, 2, 2, 0, 1, 3, 0, + 1, 1, 0, 1, 0, 1, 1, 3, 3, 1, 2, 2, 3, 2, 0, 2, 2, 0, 1, 3, + 0, 1, 3, 2, 1, 3, 3, 2, 0, 1, 3, 2, 0, 2, 1, 1, 0, 3, 0, 1, + 1, 1, 1, 1, 3, 0, 0, 1, 0, 2, 3, 1, 3, 0, 2, 1, 3, 0, 3, 0, + 3, 2, 2, 0, 0, 2, 1, 3, 3, 2, 3, 2, 2, 1, 2, 2, 3, 0, 3, 2, + 2, 0, 3, 2, 3, 2, 0, 0, 1, 2, 0, 0, 2, 0, 0, 3, 3, 2, 0, 0, + 3, 3, 0, 2, 3, 1, 0, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 3, 0, 2, + 2, 3, 0, 0, 2, 1, 0, 1, 0, 0, 0, 2, 2, 3, 2, 0, 3, 3, 2, 1, + 0, 0, 3, 1, 2, 3, 3, 1, 0, 3, 1, 1, 0, 3, 3, 3, 2, 2, 2, 0, + 1, 2, 0, 3, 0, 1, 0, 1, 1, 0, 1, 2, 0, 3, 2, 0, 1, 2, 2, 0, + 2, 0, 0, 1, 0, 3, 0, 3, 2, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 0, + 2, 1, 1, 3, 2, 0, 2, 1, 1, 0, 2, 2, 1, 3, 0, 2, 1, 0, 1, 2, + 0, 1, 3, 2, 3, 2, 1, 0, 2, 0, 2, 2, 3, 1, 1, 3, 2, 3, 2, 2, + 0, 2, 0, 0, 0, 3, 2, 0, 2, 2, 3, 3, 3, 2, 1, 2, 0, 0, 3, 0, + 2, 0, 3, 2, 2, 3, 0, 3, 2, 1, 2, 2, 1, 2, 0, 0, 3, 1, 2, 0, + 2, 3, 2, 2, 1, 1, 1, 3, 3, 3, 3, 3, 1, 3, 0, 1, 3, 2, 2, 1, + 0, 1, 1, 2, 1, 2, 3, 1, 2, 2, 1, 2, 1, 1, 0, 3, 3, 1, 1, 3, + 2, 0, 0, 1, 2, 0, 1, 3, 1, 0, 0, 2, 2, 3, 3, 0, 2, 3, 2, 1, + 1, 3, 0, 2, 2, 3, 3, 1, 2, 3, 3, 3, 1, 3, 0, 3, 1, 1, 2, 2, + 2, 1, 0, 3, 2, 3, 0, 2, 3, 2, 3, 1, 2, 3, 3, 1, 2, 1, 0, 0, + 0, 3, 3, 3, 3, 0, 3, 3, 3, 3, 2, 1, 0, 3, 0, 3, 2, 3, 1, 0, + 0, 1, 3, 1, 0, 2, 2, 3, 1, 0, 2, 1, 1, 3, 1, 1, 3, 1, 2, 1, + 0, 0, 3, 2, 1, 1, 1, 1, 3, 2, 1, 3, 3, 1, 0, 3, 1, 1, 2, 0, + 0, 0, 2, 3, 3, 2, 2, 3, 0, 2, 3, 1, 3, 3, 0, 2, 1, 2, 2, 2, + 1, 0, 1, 3, 2, 3, 1, 1, 2, 1, 1, 0, 0, 2, 3, 2, 1, 0, 3, 1, + 3, 0, 1, 1, 2, 2, 1, 3, 3, 1, 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, + 3, 1, 3, 0, 0, 0, 3, 3, 2, 1, 3, 0, 1, 3, 1, 1, 1, 0, 1, 0, + 1, 2, 2, 2, 3, 3, 0, 2, 3, 2, 1, 3, 3, 1, 1, 3, 0, 3, 3, 2, + 1, 1, 2, 0, 3, 0, 1, 2, 1, 1, 0, 0, 1, 2, 2, 0, 3, 1, 1, 1, + 3, 3, 3, 1, 0, 3, 3, 2, 2, 2, 1, 2, 0, 1, 1, 3, 0, 3, 1, 0, + 2, 2, 0, 1, 2, 3, 2, 1, 2, 0, 3, 2, 1, 3, 0, 1, 2, 0, 3, 0, + 1, 1, 2, 1 +}; + +static data_t verify_data[ARRAY_SIZE] = +{ + 72, 75, 88, 101, 80, 88, 73, 75, 80, 81, 58, 75, 86, 65, 60, 80, 84, 83, 87, 83, + 108, 93, 85, 76, 72, 98, 79, 86, 80, 96, 91, 85, 72, 64, 70, 83, 68, 92, 51, 54, + 85, 85, 60, 58, 90, 64, 55, 69, 72, 48, 94, 77, 91, 83, 70, 69, 67, 77, 59, 50, + 67, 74, 77, 67, 67, 62, 72, 71, 68, 79, 54, 61, 67, 61, 55, 62, 78, 60, 53, 64, + 67, 69, 99, 68, 88, 60, 66, 63, 70, 62, 65, 50, 53, 66, 70, 72, 75, 78, 85, 95, + 71, 89, 70, 68, 86, 88, 58, 77, 84, 70, 65, 68, 73, 75, 91, 96, 105, 92, 76, 68, + 86, 69, 80, 59, 73, 83, 88, 75, 64, 63, 71, 99, 77, 77, 69, 55, 80, 73, 54, 73, + 87, 78, 60, 69, 65, 78, 86, 89, 95, 92, 63, 69, 89, 61, 80, 65, 70, 77, 89, 77, + 79, 79, 73, 92, 64, 81, 60, 78, 81, 80, 61, 63, 89, 65, 56, 83, 77, 65, 102, 70, + 98, 86, 96, 68, 72, 89, 73, 73, 70, 89, 84, 76, 48, 61, 63, 70, 70, 79, 50, 53, + 64, 63, 43, 51, 59, 62, 43, 63, 55, 77, 79, 74, 75, 74, 64, 44, 65, 69, 72, 66, + 54, 71, 74, 72, 69, 76, 68, 89, 94, 75, 65, 53, 85, 79, 65, 74, 82, 73, 58, 70, + 84, 77, 99, 72, 92, 84, 78, 62, 59, 83, 71, 74, 63, 85, 80, 78, 71, 72, 79, 83, + 73, 82, 60, 85, 76, 82, 60, 70, 82, 68, 54, 85, 84, 70, 86, 74, 100, 88, 98, 68, + 67, 87, 69, 73, 68, 88, 76, 71, 47, 43, 47, 80, 54, 65, 40, 37, 59, 53, 33, 48, + 62, 40, 36, 55, 36, 62, 53, 57, 70, 69, 45, 43, 53, 61, 42, 57, 56, 63, 51, 47, + 59, 75, 64, 89, 83, 75, 59, 75, 91, 92, 58, 64, 83, 74, 58, 60, 76, 66, 97, 69, + 90, 95, 92, 64, 78, 75, 77, 73, 65, 78, 82, 75, 47, 54, 59, 71, 59, 56, 53, 42, + 60, 55, 40, 51, 60, 46, 36, 59, 46, 57, 67, 43, 51, 53, 53, 38, 54, 56, 55, 48, + 41, 46, 63, 63, 80, 77, 89, 102, 89, 98, 74, 86, 98, 93, 63, 76, 98, 77, 48, 101, + 86, 88, 100, 82, 102, 90, 95, 75, 86, 103, 83, 98, 80, 104, 98, 86, 71, 74, 80, 90, + 86, 87, 73, 70, 81, 83, 55, 66, 90, 66, 58, 84, 77, 84, 93, 72, 99, 75, 85, 65, + 70, 89, 71, 82, 64, 79, 82, 80, 67, 73, 86, 101, 78, 97, 66, 64, 84, 80, 55, 64, + 79, 73, 51, 79, 89, 68, 94, 77, 109, 102, 82, 61, 66, 93, 88, 70, 82, 82, 85, 69, + 69, 72, 66, 97, 85, 90, 70, 59, 76, 89, 53, 56, 90, 79, 71, 64, 70, 67, 100, 92, + 106, 89, 83, 78, 73, 80, 70, 72, 65, 70, 92, 88, 57, 76, 55, 85, 66, 80, 61, 63, + 63, 78, 54, 58, 71, 73, 54, 63, 63, 62, 89, 76, 86, 81, 83, 54, 70, 81, 78, 64, + 56, 72, 74, 81, 75, 63, 68, 89, 65, 77, 58, 68, 75, 83, 52, 62, 82, 63, 55, 75, + 51, 70, 95, 66, 83, 77, 86, 61, 64, 77, 48, 70, 66, 82, 72, 75, 79, 71, 72, 89, + 78, 78, 66, 59, 91, 80, 55, 64, 79, 68, 54, 71, 67, 75, 87, 84, 100, 101, 76, 58, + 74, 82, 61, 74, 75, 97, 85, 79, 61, 55, 69, 68, 72, 65, 52, 64, 80, 73, 48, 54, + 71, 66, 42, 61, 66, 63, 92, 64, 85, 77, 73, 54, 74, 73, 76, 66, 62, 79, 85, 70, + 71, 84, 87, 81, 88, 86, 77, 77, 93, 88, 78, 71, 101, 89, 58, 84, 95, 81, 89, 97, + 104, 79, 83, 76, 90, 81, 91, 74, 70, 76, 91, 80, 51, 48, 56, 69, 47, 63, 54, 42, + 63, 63, 42, 52, 66, 56, 39, 59, 61, 52, 59, 63, 62, 68, 57, 35, 67, 58, 56, 52, + 61, 63, 60, 47, 85, 75, 89, 106, 88, 95, 74, 82, 107, 107, 64, 78, 98, 90, 62, 91, + 79, 87, 111, 84, 104, 106, 96, 68, 94, 99, 81, 89, 79, 105, 95, 86, 65, 63, 77, 89, + 66, 88, 56, 73, 82, 92, 41, 62, 85, 66, 50, 81, 57, 71, 77, 78, 86, 89, 77, 53, + 67, 78, 61, 63, 72, 82, 69, 66, 59, 46, 55, 70, 56, 64, 45, 50, 65, 64, 42, 56, + 78, 49, 51, 52, 38, 56, 72, 55, 73, 72, 61, 50, 63, 60, 47, 57, 55, 73, 53, 68, + 85, 88, 91, 96, 82, 89, 73, 76, 87, 86, 67, 69, 96, 84, 57, 89, 87, 89, 99, 88, + 104, 90, 85, 75, 88, 92, 85, 75, 74, 87, 103, 94, 55, 48, 56, 65, 72, 50, 45, 51, + 63, 62, 47, 57, 79, 53, 36, 63, 54, 68, 71, 59, 63, 61, 63, 41, 50, 73, 57, 59, + 56, 76, 73, 65, 61, 64, 61, 79, 53, 73, 57, 44, 61, 59, 59, 56, 81, 59, 49, 62, + 65, 55, 69, 72, 79, 70, 58, 57, 68, 61, 62, 50, 57, 60, 66, 66, 63, 77, 81, 89, + 85, 81, 76, 73, 78, 95, 59, 70, 81, 77, 46, 79, 78, 79, 83, 81, 84, 82, 85, 48, + 74, 85, 85, 74, 74, 80, 80, 74, 60, 76, 80, 97, 88, 93, 66, 66, 73, 84, 56, 70, + 90, 63, 58, 78, 73, 93, 90, 78, 94, 88, 82, 67, 85, 70, 81, 86, 74, 82, 88, 82, + 68, 73, 75, 91, 78, 97, 71, 66, 74, 85, 50, 59, 86, 77, 70, 74, 75, 74, 99, 82, + 99, 91, 86, 65, 80, 77, 72, 69, 60, 78, 90, 87, 79, 69, 74, 98, 70, 86, 81, 67, + 69, 78, 48, 65, 88, 70, 70, 70, 69, 72, 96, 90, 99, 82, 81, 76, 98, 73, 74, 71, + 69, 73, 94, 89 +}; + diff --git a/benchmarks/mt-matmul/matmul_gendata.pl b/benchmarks/mt-matmul/matmul_gendata.pl new file mode 100755 index 0000000..f21bb46 --- /dev/null +++ b/benchmarks/mt-matmul/matmul_gendata.pl @@ -0,0 +1,200 @@ +#!/usr/bin/perl -w +#========================================================================== +# matmul_gendata.pl +# +# Author : Christopher Batten (cbatten@mit.edu) +# Date : April 29, 2005 +# +(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm; +# +# Simple script which creates an input data set and the reference data +# for the matmul benchmark. +# +ENDMSG + +use strict "vars"; +use warnings; +no warnings("once"); +use Getopt::Long; + +#-------------------------------------------------------------------------- +# Command line processing +#-------------------------------------------------------------------------- + +our %opts; + +sub usage() +{ + + print "\n"; + print " Usage: matmul_gendata.pl [options] \n"; + print "\n"; + print " Options:\n"; + print " --help print this message\n"; + print " --size size of input data [1000]\n"; + print " --seed random seed [1]\n"; + print "$usageMsg"; + + exit(); +} + +sub processCommandLine() +{ + + $opts{"help"} = 0; + $opts{"size"} = 1000; + $opts{"seed"} = 1; + Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage(); + $opts{"help"} and usage(); + +} + +#-------------------------------------------------------------------------- +# Helper Functions +#-------------------------------------------------------------------------- + +sub printArray +{ + my $arrayName = $_[0]; + my $arrayRef = $_[1]; + + my $numCols = 20; + my $arrayLen = scalar(@{$arrayRef}); + + print "static data_t ".$arrayName."[ARRAY_SIZE] = \n"; + print "{\n"; + + if ( $arrayLen <= $numCols ) { + print " "; + for ( my $i = 0; $i < $arrayLen; $i++ ) { + print sprintf("%3d",$arrayRef->[$i]); + if ( $i != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + else { + my $numRows = int($arrayLen/$numCols); + for ( my $j = 0; $j < $numRows; $j++ ) { + print " "; + for ( my $i = 0; $i < $numCols; $i++ ) { + my $index = $j*$numCols + $i; + print sprintf("%3d",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + if ( $arrayLen > ($numRows*$numCols) ) { + print " "; + for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) { + my $index = $numCols*$numRows + $i; + print sprintf("%3d",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + } + + print "};\n\n"; +} + + + +#-------------------------------------------------------------------------- +# Matmul +#-------------------------------------------------------------------------- + +# http://answers.oreilly.com/topic/418-how-to-multiply-matrices-in-perl/ + +sub mmult { + my ($m1,$m2) = @_; + my ($m1rows,$m1cols) = matdim($m1); + my ($m2rows,$m2cols) = matdim($m2); + + my $result = [ ]; + my ($i, $j, $k); + + for $i (range($m1rows)) { + for $j (range($m2cols)) { + for $k (range($m1cols)) { + $result->[$i][$j] += $m1->[$i][$k] * $m2->[$k][$j]; + } + } + } + return $result; +} + +sub range { 0 .. ($_[0] - 1) } + + +sub veclen { + my $ary_ref = $_[0]; + my $type = ref $ary_ref; + if ($type ne "ARRAY") { die "$type is bad array ref for $ary_ref" } + return scalar(@$ary_ref); +} + +sub matdim { + my $matrix = $_[0]; + my $rows = veclen($matrix); + my $cols = veclen($matrix->[0]); + return ($rows, $cols); +} + +#-------------------------------------------------------------------------- +# Main +#-------------------------------------------------------------------------- + +sub main() +{ + + processCommandLine(); + srand($opts{"seed"}); + + # create random input arrays + my $mat_values1; + my $mat_values2; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + for ( my $j = 0; $j < $opts{"size"}; $j++ ) { + $mat_values1->[$i][$j] = int(rand(4)); + $mat_values2->[$i][$j] = int(rand(4)); + } + } + + # perform matmul + my $mat_results = mmult( $mat_values1, $mat_values2 ); + + # translate 2d arrays to 1d-somethings (I don't know how to code in perl - Chris) + my @values1; + my @values2; + my @results; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + for ( my $j = 0; $j < $opts{"size"}; $j++ ) { + my $value1 = $mat_values1->[$i][$j]; + my $value2 = $mat_values2->[$i][$j]; + my $result = $mat_results->[$i][$j]; + push( @values1, $value1 ); + push( @values2, $value2 ); + push( @results, $result ); + } + } + + print "\n\#define ARRAY_SIZE ".($opts{"size"}*$opts{"size"})." \n\n"; + print "\n\#define DIM_SIZE ".$opts{"size"}." \n\n"; + + printArray( "input1_data", \@values1 ); + printArray( "input2_data", \@values2 ); + printArray( "verify_data", \@results); + +} + +main(); + diff --git a/benchmarks/mt-matmul/mt-matmul.c b/benchmarks/mt-matmul/mt-matmul.c new file mode 100644 index 0000000..93f8ea9 --- /dev/null +++ b/benchmarks/mt-matmul/mt-matmul.c @@ -0,0 +1,167 @@ +//************************************************************************** +// Multi-threaded Matrix Multiply benchmark +//-------------------------------------------------------------------------- +// TA : Christopher Celio +// Student: +// +// +// This benchmark multiplies two 2-D arrays together and writes the results to +// a third vector. The input data (and reference data) should be generated +// using the matmul_gendata.pl perl script and dumped to a file named +// dataset.h. + + +// print out arrays, etc. +//#define DEBUG + +//-------------------------------------------------------------------------- +// Includes + +#include +#include +#include + + +//-------------------------------------------------------------------------- +// Input/Reference Data + +typedef float data_t; +#include "dataset.h" + + +//-------------------------------------------------------------------------- +// Basic Utilities and Multi-thread Support + +__thread unsigned long coreid; +unsigned long ncores; + +#include "util.h" + +#define stringify_1(s) #s +#define stringify(s) stringify_1(s) +#define stats(code) do { \ + unsigned long _c = -rdcycle(), _i = -rdinstret(); \ + code; \ + _c += rdcycle(), _i += rdinstret(); \ + if (coreid == 0) \ + printf("%s: %ld cycles, %ld.%ld cycles/iter, %ld.%ld CPI\n", \ + stringify(code), _c, _c/DIM_SIZE/DIM_SIZE/DIM_SIZE, 10*_c/DIM_SIZE/DIM_SIZE/DIM_SIZE%10, _c/_i, 10*_c/_i%10); \ + } while(0) + + +//-------------------------------------------------------------------------- +// Helper functions + +void printArray( char name[], int n, data_t arr[] ) +{ + int i; + if (coreid != 0) + return; + + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " %3ld ", (long) arr[i] ); + printf( "\n" ); +} + +void __attribute__((noinline)) verify(size_t n, const data_t* test, const data_t* correct) +{ + if (coreid != 0) + return; + + size_t i; + for (i = 0; i < n; i++) + { + if (test[i] != correct[i]) + { + printf("FAILED test[%d]= %3ld, correct[%d]= %3ld\n", + i, (long)test[i], i, (long)correct[i]); + exit(-1); + } + } + + return; +} + +//-------------------------------------------------------------------------- +// matmul function + +// single-thread, naive version +void __attribute__((noinline)) matmul_naive(const int lda, const data_t A[], const data_t B[], data_t C[] ) +{ + int i, j, k; + + if (coreid > 0) + return; + + for ( i = 0; i < lda; i++ ) + for ( j = 0; j < lda; j++ ) + { + for ( k = 0; k < lda; k++ ) + { + C[i + j*lda] += A[j*lda + k] * B[k*lda + i]; + } + } + +} + + + +void __attribute__((noinline)) matmul(const int lda, const data_t A[], const data_t B[], data_t C[] ) +{ + + // ***************************** // + // **** ADD YOUR CODE HERE ***** // + // ***************************** // + // + // feel free to make a separate function for MI and MSI versions. + +} + +//-------------------------------------------------------------------------- +// Main +// +// all threads start executing thread_entry(). Use their "coreid" to +// differentiate between threads (each thread is running on a separate core). + +void thread_entry(int cid, int nc) +{ + coreid = cid; + ncores = nc; + + // static allocates data in the binary, which is visible to both threads + static data_t results_data[ARRAY_SIZE]; + + + // Execute the provided, naive matmul + barrier(); + stats(matmul_naive(DIM_SIZE, input1_data, input2_data, results_data); barrier()); + + + // verify + verify(ARRAY_SIZE, results_data, verify_data); + + // clear results from the first trial + size_t i; + if (coreid == 0) + for (i=0; i < ARRAY_SIZE; i++) + results_data[i] = 0; + barrier(); + + + // Execute your faster matmul + barrier(); + stats(matmul(DIM_SIZE, input1_data, input2_data, results_data); barrier()); + +#ifdef DEBUG + printArray("results:", ARRAY_SIZE, results_data); + printArray("verify :", ARRAY_SIZE, verify_data); +#endif + + // verify + verify(ARRAY_SIZE, results_data, verify_data); + barrier(); + + exit(0); +} + diff --git a/benchmarks/mt-vvadd/bmark.mk b/benchmarks/mt-vvadd/bmark.mk new file mode 100644 index 0000000..0ab2504 --- /dev/null +++ b/benchmarks/mt-vvadd/bmark.mk @@ -0,0 +1,29 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +mt_vvadd_c_src = \ + mt-vvadd.c \ + +mt_vvadd_riscv_src = \ + crt-mt.S \ + +mt_vvadd_c_objs = $(patsubst %.c, %.o, $(mt_vvadd_c_src)) +mt_vvadd_riscv_objs = $(patsubst %.S, %.o, $(mt_vvadd_riscv_src)) + +mt_vvadd_host_bin = mt-vvadd.host +$(mt_vvadd_host_bin) : $(mt_vvadd_c_src) + $(HOST_COMP) $^ -o $(mt_vvadd_host_bin) + +mt_vvadd_riscv_bin = mt-vvadd.riscv +$(mt_vvadd_riscv_bin) : $(mt_vvadd_c_objs) $(mt_vvadd_riscv_objs) + $(RISCV_LINK_MT) $(RISCV_LINK_SYSCALL) $(mt_vvadd_c_objs) $(mt_vvadd_riscv_objs) -o $(mt_vvadd_riscv_bin) + +junk += $(mt_vvadd_c_objs) $(mt_vvadd_riscv_objs) \ + $(mt_vvadd_host_bin) $(mt_vvadd_riscv_bin) diff --git a/benchmarks/mt-vvadd/dataset.h b/benchmarks/mt-vvadd/dataset.h new file mode 100644 index 0000000..ce9f936 --- /dev/null +++ b/benchmarks/mt-vvadd/dataset.h @@ -0,0 +1,165 @@ + +#define DATA_SIZE 1000 + +static data_t input1_data[DATA_SIZE] = +{ + 0.00, 15.00, 10.00, 3.00, 14.00, 6.00, 2.00, 18.00, 11.00, 15.00, 11.00, 0.00, 17.00, 16.00, 7.00, 13.00, 18.00, 2.00, 2.00, 5.00, + 8.00, 5.00, 12.00, 14.00, 6.00, 12.00, 16.00, 7.00, 9.00, 17.00, 10.00, 10.00, 3.00, 5.00, 14.00, 11.00, 9.00, 12.00, 3.00, 1.00, + 5.00, 4.00, 6.00, 17.00, 17.00, 4.00, 17.00, 15.00, 17.00, 18.00, 3.00, 18.00, 10.00, 6.00, 12.00, 12.00, 3.00, 2.00, 16.00, 1.00, + 5.00, 6.00, 2.00, 17.00, 16.00, 5.00, 10.00, 18.00, 14.00, 4.00, 9.00, 9.00, 7.00, 4.00, 8.00, 13.00, 12.00, 6.00, 4.00, 17.00, + 5.00, 2.00, 11.00, 11.00, 7.00, 6.00, 8.00, 5.00, 6.00, 6.00, 11.00, 1.00, 18.00, 7.00, 6.00, 9.00, 10.00, 17.00, 14.00, 4.00, + 14.00, 11.00, 2.00, 0.00, 2.00, 17.00, 17.00, 15.00, 10.00, 8.00, 12.00, 18.00, 5.00, 0.00, 0.00, 1.00, 1.00, 8.00, 11.00, 11.00, + 7.00, 5.00, 15.00, 18.00, 15.00, 6.00, 8.00, 9.00, 18.00, 6.00, 15.00, 16.00, 10.00, 18.00, 13.00, 6.00, 10.00, 16.00, 0.00, 10.00, + 12.00, 8.00, 8.00, 3.00, 0.00, 1.00, 4.00, 0.00, 8.00, 15.00, 16.00, 9.00, 7.00, 7.00, 10.00, 9.00, 16.00, 12.00, 5.00, 5.00, + 9.00, 5.00, 17.00, 4.00, 13.00, 13.00, 4.00, 14.00, 10.00, 5.00, 10.00, 10.00, 6.00, 18.00, 5.00, 15.00, 5.00, 15.00, 13.00, 18.00, + 6.00, 13.00, 5.00, 18.00, 12.00, 14.00, 1.00, 7.00, 2.00, 1.00, 7.00, 12.00, 15.00, 15.00, 6.00, 2.00, 1.00, 2.00, 18.00, 6.00, + 10.00, 14.00, 9.00, 15.00, 11.00, 0.00, 3.00, 1.00, 2.00, 2.00, 14.00, 7.00, 18.00, 0.00, 2.00, 2.00, 16.00, 8.00, 4.00, 5.00, + 7.00, 11.00, 7.00, 10.00, 14.00, 10.00, 3.00, 0.00, 13.00, 9.00, 14.00, 0.00, 14.00, 1.00, 3.00, 16.00, 2.00, 14.00, 6.00, 17.00, + 17.00, 6.00, 9.00, 8.00, 9.00, 12.00, 5.00, 14.00, 2.00, 16.00, 17.00, 5.00, 4.00, 0.00, 14.00, 10.00, 6.00, 15.00, 15.00, 14.00, + 5.00, 1.00, 8.00, 8.00, 13.00, 8.00, 0.00, 4.00, 7.00, 9.00, 13.00, 16.00, 9.00, 14.00, 9.00, 13.00, 0.00, 7.00, 16.00, 17.00, + 18.00, 10.00, 13.00, 8.00, 4.00, 9.00, 13.00, 0.00, 6.00, 4.00, 6.00, 4.00, 10.00, 14.00, 14.00, 9.00, 15.00, 15.00, 3.00, 3.00, + 12.00, 0.00, 3.00, 2.00, 16.00, 1.00, 7.00, 2.00, 16.00, 2.00, 2.00, 0.00, 14.00, 3.00, 3.00, 10.00, 4.00, 10.00, 3.00, 4.00, + 13.00, 14.00, 13.00, 0.00, 1.00, 15.00, 16.00, 9.00, 7.00, 9.00, 0.00, 11.00, 1.00, 1.00, 15.00, 17.00, 12.00, 16.00, 15.00, 4.00, + 8.00, 2.00, 10.00, 10.00, 0.00, 18.00, 17.00, 7.00, 7.00, 2.00, 10.00, 17.00, 9.00, 7.00, 5.00, 3.00, 8.00, 11.00, 6.00, 9.00, + 13.00, 0.00, 3.00, 5.00, 2.00, 5.00, 7.00, 4.00, 9.00, 2.00, 13.00, 17.00, 14.00, 12.00, 1.00, 3.00, 7.00, 17.00, 0.00, 14.00, + 16.00, 2.00, 2.00, 1.00, 2.00, 15.00, 16.00, 8.00, 2.00, 4.00, 15.00, 15.00, 10.00, 6.00, 11.00, 9.00, 15.00, 17.00, 3.00, 8.00, + 15.00, 3.00, 10.00, 15.00, 8.00, 14.00, 16.00, 15.00, 15.00, 14.00, 1.00, 7.00, 4.00, 18.00, 2.00, 13.00, 11.00, 15.00, 7.00, 10.00, + 13.00, 10.00, 7.00, 14.00, 18.00, 4.00, 18.00, 4.00, 3.00, 9.00, 1.00, 13.00, 15.00, 2.00, 5.00, 15.00, 12.00, 10.00, 2.00, 0.00, + 10.00, 15.00, 0.00, 11.00, 14.00, 11.00, 14.00, 9.00, 1.00, 18.00, 14.00, 18.00, 15.00, 5.00, 1.00, 15.00, 18.00, 14.00, 3.00, 15.00, + 11.00, 2.00, 15.00, 0.00, 13.00, 1.00, 4.00, 14.00, 14.00, 5.00, 2.00, 13.00, 17.00, 8.00, 7.00, 6.00, 5.00, 10.00, 14.00, 14.00, + 17.00, 0.00, 0.00, 17.00, 18.00, 15.00, 10.00, 16.00, 18.00, 5.00, 9.00, 10.00, 18.00, 7.00, 11.00, 5.00, 4.00, 16.00, 2.00, 8.00, + 13.00, 1.00, 12.00, 3.00, 4.00, 6.00, 15.00, 12.00, 0.00, 6.00, 18.00, 12.00, 14.00, 18.00, 3.00, 2.00, 3.00, 5.00, 3.00, 14.00, + 18.00, 12.00, 10.00, 11.00, 8.00, 4.00, 10.00, 10.00, 9.00, 18.00, 14.00, 3.00, 7.00, 17.00, 12.00, 0.00, 10.00, 9.00, 17.00, 3.00, + 0.00, 4.00, 6.00, 16.00, 14.00, 12.00, 13.00, 13.00, 18.00, 7.00, 0.00, 1.00, 9.00, 7.00, 12.00, 6.00, 18.00, 8.00, 9.00, 13.00, + 13.00, 17.00, 10.00, 16.00, 1.00, 10.00, 17.00, 16.00, 2.00, 18.00, 4.00, 2.00, 6.00, 1.00, 1.00, 1.00, 8.00, 14.00, 6.00, 6.00, + 13.00, 14.00, 13.00, 6.00, 5.00, 10.00, 11.00, 11.00, 16.00, 1.00, 5.00, 9.00, 13.00, 8.00, 10.00, 2.00, 12.00, 15.00, 5.00, 14.00, + 3.00, 7.00, 9.00, 18.00, 2.00, 11.00, 16.00, 4.00, 5.00, 10.00, 17.00, 10.00, 3.00, 4.00, 14.00, 18.00, 13.00, 6.00, 8.00, 11.00, + 14.00, 3.00, 5.00, 6.00, 6.00, 5.00, 13.00, 0.00, 9.00, 9.00, 1.00, 7.00, 5.00, 5.00, 1.00, 6.00, 18.00, 11.00, 17.00, 7.00, + 1.00, 10.00, 5.00, 12.00, 6.00, 16.00, 16.00, 5.00, 1.00, 10.00, 10.00, 15.00, 7.00, 18.00, 8.00, 17.00, 3.00, 5.00, 3.00, 14.00, + 0.00, 16.00, 12.00, 0.00, 14.00, 17.00, 16.00, 2.00, 18.00, 13.00, 10.00, 13.00, 4.00, 14.00, 2.00, 3.00, 4.00, 8.00, 17.00, 0.00, + 6.00, 11.00, 5.00, 3.00, 3.00, 2.00, 15.00, 13.00, 10.00, 4.00, 1.00, 11.00, 6.00, 17.00, 1.00, 0.00, 18.00, 3.00, 3.00, 11.00, + 7.00, 7.00, 11.00, 14.00, 7.00, 16.00, 11.00, 10.00, 8.00, 6.00, 11.00, 5.00, 17.00, 10.00, 7.00, 8.00, 14.00, 2.00, 9.00, 17.00, + 15.00, 13.00, 10.00, 6.00, 0.00, 15.00, 11.00, 10.00, 11.00, 18.00, 2.00, 5.00, 17.00, 18.00, 11.00, 15.00, 3.00, 17.00, 9.00, 17.00, + 8.00, 6.00, 2.00, 4.00, 2.00, 11.00, 15.00, 2.00, 18.00, 3.00, 9.00, 7.00, 15.00, 9.00, 14.00, 10.00, 9.00, 6.00, 13.00, 8.00, + 15.00, 14.00, 0.00, 11.00, 5.00, 2.00, 12.00, 14.00, 10.00, 16.00, 9.00, 7.00, 9.00, 17.00, 4.00, 4.00, 7.00, 8.00, 4.00, 4.00, + 9.00, 7.00, 3.00, 5.00, 11.00, 11.00, 10.00, 13.00, 3.00, 14.00, 15.00, 8.00, 1.00, 1.00, 3.00, 0.00, 16.00, 9.00, 6.00, 1.00, + 0.00, 2.00, 0.00, 6.00, 13.00, 12.00, 5.00, 18.00, 1.00, 11.00, 17.00, 11.00, 16.00, 14.00, 14.00, 9.00, 11.00, 9.00, 17.00, 15.00, + 5.00, 18.00, 2.00, 11.00, 10.00, 16.00, 18.00, 5.00, 11.00, 12.00, 11.00, 18.00, 7.00, 6.00, 8.00, 3.00, 4.00, 3.00, 16.00, 4.00, + 6.00, 2.00, 15.00, 6.00, 7.00, 16.00, 0.00, 7.00, 11.00, 10.00, 3.00, 0.00, 14.00, 16.00, 15.00, 15.00, 12.00, 7.00, 1.00, 4.00, + 8.00, 4.00, 12.00, 0.00, 7.00, 8.00, 1.00, 1.00, 14.00, 15.00, 9.00, 8.00, 6.00, 6.00, 4.00, 7.00, 8.00, 13.00, 10.00, 5.00, + 8.00, 11.00, 2.00, 16.00, 7.00, 17.00, 5.00, 2.00, 17.00, 0.00, 18.00, 6.00, 7.00, 4.00, 4.00, 12.00, 0.00, 18.00, 8.00, 4.00, + 7.00, 0.00, 11.00, 1.00, 11.00, 17.00, 18.00, 15.00, 8.00, 11.00, 15.00, 9.00, 12.00, 1.00, 5.00, 6.00, 1.00, 18.00, 14.00, 7.00, + 16.00, 16.00, 10.00, 3.00, 13.00, 0.00, 12.00, 9.00, 18.00, 14.00, 15.00, 4.00, 11.00, 15.00, 15.00, 8.00, 16.00, 11.00, 13.00, 12.00, + 1.00, 13.00, 14.00, 2.00, 11.00, 0.00, 17.00, 11.00, 12.00, 6.00, 4.00, 4.00, 11.00, 13.00, 10.00, 2.00, 10.00, 14.00, 0.00, 6.00, + 18.00, 10.00, 7.00, 14.00, 12.00, 9.00, 4.00, 16.00, 17.00, 8.00, 14.00, 9.00, 0.00, 4.00, 15.00, 13.00, 8.00, 13.00, 13.00, 8.00, + 15.00, 6.00, 11.00, 4.00, 2.00, 6.00, 5.00, 14.00, 5.00, 17.00, 12.00, 11.00, 17.00, 4.00, 13.00, 7.00, 16.00, 12.00, 7.00, 18.00 +}; + +static data_t input2_data[DATA_SIZE] = +{ + 8.00, 6.00, 0.00, 18.00, 6.00, 10.00, 1.00, 2.00, 4.00, 2.00, 4.00, 10.00, 6.00, 11.00, 17.00, 4.00, 0.00, 16.00, 14.00, 12.00, + 9.00, 8.00, 13.00, 15.00, 18.00, 2.00, 13.00, 10.00, 5.00, 4.00, 12.00, 9.00, 1.00, 13.00, 12.00, 7.00, 10.00, 17.00, 11.00, 10.00, + 18.00, 15.00, 11.00, 12.00, 7.00, 9.00, 6.00, 5.00, 11.00, 7.00, 10.00, 12.00, 18.00, 18.00, 15.00, 1.00, 3.00, 18.00, 11.00, 16.00, + 13.00, 18.00, 4.00, 13.00, 8.00, 7.00, 10.00, 13.00, 0.00, 9.00, 1.00, 16.00, 13.00, 7.00, 5.00, 5.00, 11.00, 1.00, 6.00, 10.00, + 12.00, 3.00, 10.00, 5.00, 15.00, 15.00, 13.00, 14.00, 14.00, 1.00, 18.00, 5.00, 16.00, 14.00, 10.00, 4.00, 8.00, 4.00, 6.00, 6.00, + 13.00, 14.00, 8.00, 5.00, 14.00, 10.00, 9.00, 10.00, 17.00, 15.00, 6.00, 16.00, 12.00, 9.00, 10.00, 16.00, 16.00, 8.00, 1.00, 12.00, + 7.00, 0.00, 0.00, 3.00, 5.00, 7.00, 10.00, 3.00, 17.00, 10.00, 18.00, 16.00, 1.00, 11.00, 18.00, 9.00, 2.00, 0.00, 12.00, 6.00, + 13.00, 1.00, 13.00, 5.00, 7.00, 13.00, 17.00, 9.00, 15.00, 13.00, 5.00, 2.00, 4.00, 4.00, 3.00, 0.00, 9.00, 11.00, 3.00, 12.00, + 6.00, 11.00, 1.00, 16.00, 12.00, 11.00, 2.00, 2.00, 15.00, 12.00, 8.00, 9.00, 14.00, 2.00, 11.00, 0.00, 0.00, 7.00, 2.00, 13.00, + 15.00, 18.00, 7.00, 16.00, 16.00, 1.00, 1.00, 12.00, 12.00, 2.00, 2.00, 1.00, 7.00, 4.00, 0.00, 8.00, 18.00, 4.00, 11.00, 6.00, + 17.00, 13.00, 12.00, 5.00, 16.00, 12.00, 0.00, 9.00, 10.00, 10.00, 18.00, 12.00, 8.00, 7.00, 5.00, 8.00, 16.00, 3.00, 9.00, 18.00, + 12.00, 13.00, 18.00, 6.00, 8.00, 12.00, 2.00, 12.00, 8.00, 8.00, 9.00, 18.00, 8.00, 0.00, 9.00, 2.00, 6.00, 7.00, 0.00, 3.00, + 11.00, 2.00, 18.00, 2.00, 16.00, 1.00, 16.00, 11.00, 11.00, 16.00, 16.00, 11.00, 7.00, 4.00, 14.00, 10.00, 5.00, 8.00, 4.00, 14.00, + 17.00, 13.00, 13.00, 3.00, 1.00, 14.00, 1.00, 7.00, 0.00, 2.00, 7.00, 14.00, 4.00, 9.00, 14.00, 3.00, 9.00, 13.00, 13.00, 3.00, + 3.00, 17.00, 0.00, 18.00, 4.00, 8.00, 6.00, 9.00, 4.00, 2.00, 0.00, 14.00, 3.00, 3.00, 14.00, 8.00, 6.00, 7.00, 2.00, 12.00, + 5.00, 14.00, 6.00, 12.00, 2.00, 16.00, 1.00, 15.00, 7.00, 18.00, 0.00, 0.00, 13.00, 13.00, 12.00, 11.00, 16.00, 15.00, 14.00, 8.00, + 9.00, 10.00, 8.00, 8.00, 13.00, 13.00, 13.00, 10.00, 1.00, 15.00, 4.00, 0.00, 12.00, 1.00, 8.00, 12.00, 1.00, 18.00, 12.00, 18.00, + 9.00, 1.00, 11.00, 5.00, 13.00, 7.00, 1.00, 13.00, 5.00, 8.00, 17.00, 11.00, 13.00, 15.00, 9.00, 3.00, 17.00, 18.00, 9.00, 3.00, + 15.00, 11.00, 12.00, 0.00, 2.00, 15.00, 3.00, 0.00, 13.00, 1.00, 14.00, 14.00, 15.00, 8.00, 6.00, 0.00, 0.00, 11.00, 17.00, 0.00, + 1.00, 8.00, 6.00, 6.00, 10.00, 6.00, 18.00, 12.00, 7.00, 18.00, 4.00, 6.00, 15.00, 18.00, 7.00, 5.00, 8.00, 6.00, 6.00, 7.00, + 4.00, 4.00, 10.00, 17.00, 12.00, 13.00, 11.00, 15.00, 12.00, 18.00, 7.00, 12.00, 17.00, 10.00, 14.00, 12.00, 2.00, 7.00, 17.00, 3.00, + 8.00, 6.00, 3.00, 9.00, 3.00, 7.00, 7.00, 15.00, 18.00, 5.00, 13.00, 13.00, 15.00, 10.00, 0.00, 11.00, 10.00, 1.00, 5.00, 16.00, + 2.00, 7.00, 14.00, 12.00, 7.00, 17.00, 17.00, 11.00, 0.00, 5.00, 16.00, 14.00, 1.00, 9.00, 8.00, 8.00, 3.00, 17.00, 0.00, 8.00, + 6.00, 5.00, 7.00, 6.00, 17.00, 3.00, 3.00, 8.00, 3.00, 12.00, 17.00, 5.00, 14.00, 3.00, 11.00, 5.00, 17.00, 2.00, 15.00, 1.00, + 18.00, 11.00, 12.00, 0.00, 0.00, 14.00, 7.00, 17.00, 15.00, 10.00, 18.00, 10.00, 11.00, 7.00, 12.00, 10.00, 17.00, 2.00, 18.00, 9.00, + 11.00, 4.00, 17.00, 10.00, 15.00, 12.00, 4.00, 1.00, 5.00, 10.00, 4.00, 2.00, 11.00, 3.00, 4.00, 15.00, 16.00, 10.00, 2.00, 2.00, + 15.00, 16.00, 0.00, 13.00, 16.00, 9.00, 1.00, 7.00, 3.00, 10.00, 7.00, 2.00, 12.00, 8.00, 1.00, 5.00, 0.00, 16.00, 4.00, 14.00, + 13.00, 16.00, 3.00, 0.00, 10.00, 6.00, 3.00, 9.00, 1.00, 3.00, 0.00, 13.00, 12.00, 17.00, 11.00, 4.00, 15.00, 15.00, 12.00, 4.00, + 4.00, 2.00, 16.00, 6.00, 11.00, 17.00, 14.00, 7.00, 4.00, 14.00, 8.00, 8.00, 3.00, 18.00, 17.00, 17.00, 12.00, 10.00, 11.00, 1.00, + 8.00, 13.00, 1.00, 14.00, 0.00, 9.00, 0.00, 7.00, 9.00, 0.00, 7.00, 12.00, 0.00, 18.00, 10.00, 1.00, 5.00, 13.00, 13.00, 2.00, + 10.00, 4.00, 2.00, 6.00, 0.00, 16.00, 2.00, 15.00, 13.00, 6.00, 8.00, 5.00, 6.00, 15.00, 12.00, 6.00, 6.00, 7.00, 8.00, 1.00, + 11.00, 9.00, 7.00, 18.00, 14.00, 4.00, 9.00, 6.00, 4.00, 2.00, 10.00, 13.00, 6.00, 17.00, 2.00, 11.00, 7.00, 3.00, 8.00, 9.00, + 2.00, 6.00, 18.00, 12.00, 18.00, 13.00, 8.00, 1.00, 11.00, 4.00, 13.00, 14.00, 16.00, 8.00, 6.00, 18.00, 14.00, 15.00, 9.00, 11.00, + 2.00, 13.00, 4.00, 3.00, 3.00, 15.00, 14.00, 3.00, 13.00, 12.00, 14.00, 16.00, 18.00, 12.00, 5.00, 11.00, 2.00, 3.00, 15.00, 1.00, + 12.00, 1.00, 15.00, 13.00, 12.00, 18.00, 4.00, 17.00, 13.00, 7.00, 11.00, 13.00, 7.00, 10.00, 1.00, 3.00, 18.00, 6.00, 10.00, 3.00, + 9.00, 16.00, 12.00, 10.00, 6.00, 6.00, 7.00, 16.00, 16.00, 16.00, 17.00, 18.00, 8.00, 18.00, 0.00, 6.00, 17.00, 13.00, 14.00, 8.00, + 0.00, 7.00, 5.00, 13.00, 8.00, 12.00, 14.00, 9.00, 10.00, 10.00, 9.00, 9.00, 8.00, 6.00, 0.00, 14.00, 16.00, 8.00, 7.00, 16.00, + 10.00, 3.00, 1.00, 9.00, 11.00, 2.00, 6.00, 18.00, 5.00, 4.00, 2.00, 11.00, 10.00, 17.00, 16.00, 2.00, 12.00, 15.00, 14.00, 6.00, + 6.00, 17.00, 3.00, 10.00, 9.00, 18.00, 18.00, 6.00, 11.00, 16.00, 18.00, 17.00, 7.00, 14.00, 1.00, 16.00, 7.00, 9.00, 11.00, 12.00, + 10.00, 6.00, 1.00, 16.00, 9.00, 18.00, 0.00, 9.00, 16.00, 10.00, 14.00, 6.00, 9.00, 14.00, 15.00, 7.00, 12.00, 8.00, 1.00, 1.00, + 1.00, 17.00, 17.00, 17.00, 18.00, 1.00, 15.00, 18.00, 16.00, 16.00, 11.00, 7.00, 4.00, 15.00, 3.00, 14.00, 13.00, 14.00, 9.00, 2.00, + 4.00, 8.00, 14.00, 7.00, 0.00, 12.00, 14.00, 15.00, 8.00, 2.00, 11.00, 5.00, 6.00, 16.00, 6.00, 4.00, 16.00, 7.00, 9.00, 5.00, + 1.00, 0.00, 16.00, 10.00, 9.00, 6.00, 5.00, 8.00, 15.00, 13.00, 7.00, 18.00, 18.00, 8.00, 0.00, 15.00, 4.00, 6.00, 14.00, 3.00, + 3.00, 2.00, 9.00, 14.00, 18.00, 13.00, 10.00, 15.00, 0.00, 11.00, 16.00, 7.00, 16.00, 18.00, 0.00, 12.00, 6.00, 13.00, 12.00, 12.00, + 5.00, 3.00, 5.00, 16.00, 13.00, 16.00, 8.00, 5.00, 12.00, 8.00, 8.00, 0.00, 2.00, 9.00, 18.00, 11.00, 8.00, 4.00, 14.00, 6.00, + 17.00, 2.00, 6.00, 8.00, 11.00, 13.00, 6.00, 18.00, 17.00, 6.00, 8.00, 0.00, 1.00, 14.00, 18.00, 4.00, 0.00, 4.00, 3.00, 3.00, + 16.00, 8.00, 16.00, 1.00, 2.00, 0.00, 15.00, 14.00, 10.00, 9.00, 15.00, 3.00, 5.00, 18.00, 5.00, 6.00, 7.00, 3.00, 7.00, 2.00, + 6.00, 12.00, 10.00, 10.00, 18.00, 16.00, 0.00, 9.00, 17.00, 10.00, 9.00, 14.00, 15.00, 5.00, 8.00, 15.00, 3.00, 15.00, 14.00, 11.00, + 6.00, 6.00, 14.00, 0.00, 14.00, 0.00, 7.00, 12.00, 8.00, 7.00, 1.00, 3.00, 6.00, 10.00, 12.00, 1.00, 16.00, 5.00, 5.00, 6.00, + 17.00, 15.00, 15.00, 9.00, 4.00, 18.00, 17.00, 13.00, 12.00, 9.00, 7.00, 10.00, 2.00, 5.00, 8.00, 18.00, 1.00, 15.00, 8.00, 0.00 +}; + +static data_t verify_data[DATA_SIZE] = +{ + 8.00, 21.00, 10.00, 21.00, 20.00, 16.00, 3.00, 20.00, 15.00, 17.00, 15.00, 10.00, 23.00, 27.00, 24.00, 17.00, 18.00, 18.00, 16.00, 17.00, + 17.00, 13.00, 25.00, 29.00, 24.00, 14.00, 29.00, 17.00, 14.00, 21.00, 22.00, 19.00, 4.00, 18.00, 26.00, 18.00, 19.00, 29.00, 14.00, 11.00, + 23.00, 19.00, 17.00, 29.00, 24.00, 13.00, 23.00, 20.00, 28.00, 25.00, 13.00, 30.00, 28.00, 24.00, 27.00, 13.00, 6.00, 20.00, 27.00, 17.00, + 18.00, 24.00, 6.00, 30.00, 24.00, 12.00, 20.00, 31.00, 14.00, 13.00, 10.00, 25.00, 20.00, 11.00, 13.00, 18.00, 23.00, 7.00, 10.00, 27.00, + 17.00, 5.00, 21.00, 16.00, 22.00, 21.00, 21.00, 19.00, 20.00, 7.00, 29.00, 6.00, 34.00, 21.00, 16.00, 13.00, 18.00, 21.00, 20.00, 10.00, + 27.00, 25.00, 10.00, 5.00, 16.00, 27.00, 26.00, 25.00, 27.00, 23.00, 18.00, 34.00, 17.00, 9.00, 10.00, 17.00, 17.00, 16.00, 12.00, 23.00, + 14.00, 5.00, 15.00, 21.00, 20.00, 13.00, 18.00, 12.00, 35.00, 16.00, 33.00, 32.00, 11.00, 29.00, 31.00, 15.00, 12.00, 16.00, 12.00, 16.00, + 25.00, 9.00, 21.00, 8.00, 7.00, 14.00, 21.00, 9.00, 23.00, 28.00, 21.00, 11.00, 11.00, 11.00, 13.00, 9.00, 25.00, 23.00, 8.00, 17.00, + 15.00, 16.00, 18.00, 20.00, 25.00, 24.00, 6.00, 16.00, 25.00, 17.00, 18.00, 19.00, 20.00, 20.00, 16.00, 15.00, 5.00, 22.00, 15.00, 31.00, + 21.00, 31.00, 12.00, 34.00, 28.00, 15.00, 2.00, 19.00, 14.00, 3.00, 9.00, 13.00, 22.00, 19.00, 6.00, 10.00, 19.00, 6.00, 29.00, 12.00, + 27.00, 27.00, 21.00, 20.00, 27.00, 12.00, 3.00, 10.00, 12.00, 12.00, 32.00, 19.00, 26.00, 7.00, 7.00, 10.00, 32.00, 11.00, 13.00, 23.00, + 19.00, 24.00, 25.00, 16.00, 22.00, 22.00, 5.00, 12.00, 21.00, 17.00, 23.00, 18.00, 22.00, 1.00, 12.00, 18.00, 8.00, 21.00, 6.00, 20.00, + 28.00, 8.00, 27.00, 10.00, 25.00, 13.00, 21.00, 25.00, 13.00, 32.00, 33.00, 16.00, 11.00, 4.00, 28.00, 20.00, 11.00, 23.00, 19.00, 28.00, + 22.00, 14.00, 21.00, 11.00, 14.00, 22.00, 1.00, 11.00, 7.00, 11.00, 20.00, 30.00, 13.00, 23.00, 23.00, 16.00, 9.00, 20.00, 29.00, 20.00, + 21.00, 27.00, 13.00, 26.00, 8.00, 17.00, 19.00, 9.00, 10.00, 6.00, 6.00, 18.00, 13.00, 17.00, 28.00, 17.00, 21.00, 22.00, 5.00, 15.00, + 17.00, 14.00, 9.00, 14.00, 18.00, 17.00, 8.00, 17.00, 23.00, 20.00, 2.00, 0.00, 27.00, 16.00, 15.00, 21.00, 20.00, 25.00, 17.00, 12.00, + 22.00, 24.00, 21.00, 8.00, 14.00, 28.00, 29.00, 19.00, 8.00, 24.00, 4.00, 11.00, 13.00, 2.00, 23.00, 29.00, 13.00, 34.00, 27.00, 22.00, + 17.00, 3.00, 21.00, 15.00, 13.00, 25.00, 18.00, 20.00, 12.00, 10.00, 27.00, 28.00, 22.00, 22.00, 14.00, 6.00, 25.00, 29.00, 15.00, 12.00, + 28.00, 11.00, 15.00, 5.00, 4.00, 20.00, 10.00, 4.00, 22.00, 3.00, 27.00, 31.00, 29.00, 20.00, 7.00, 3.00, 7.00, 28.00, 17.00, 14.00, + 17.00, 10.00, 8.00, 7.00, 12.00, 21.00, 34.00, 20.00, 9.00, 22.00, 19.00, 21.00, 25.00, 24.00, 18.00, 14.00, 23.00, 23.00, 9.00, 15.00, + 19.00, 7.00, 20.00, 32.00, 20.00, 27.00, 27.00, 30.00, 27.00, 32.00, 8.00, 19.00, 21.00, 28.00, 16.00, 25.00, 13.00, 22.00, 24.00, 13.00, + 21.00, 16.00, 10.00, 23.00, 21.00, 11.00, 25.00, 19.00, 21.00, 14.00, 14.00, 26.00, 30.00, 12.00, 5.00, 26.00, 22.00, 11.00, 7.00, 16.00, + 12.00, 22.00, 14.00, 23.00, 21.00, 28.00, 31.00, 20.00, 1.00, 23.00, 30.00, 32.00, 16.00, 14.00, 9.00, 23.00, 21.00, 31.00, 3.00, 23.00, + 17.00, 7.00, 22.00, 6.00, 30.00, 4.00, 7.00, 22.00, 17.00, 17.00, 19.00, 18.00, 31.00, 11.00, 18.00, 11.00, 22.00, 12.00, 29.00, 15.00, + 35.00, 11.00, 12.00, 17.00, 18.00, 29.00, 17.00, 33.00, 33.00, 15.00, 27.00, 20.00, 29.00, 14.00, 23.00, 15.00, 21.00, 18.00, 20.00, 17.00, + 24.00, 5.00, 29.00, 13.00, 19.00, 18.00, 19.00, 13.00, 5.00, 16.00, 22.00, 14.00, 25.00, 21.00, 7.00, 17.00, 19.00, 15.00, 5.00, 16.00, + 33.00, 28.00, 10.00, 24.00, 24.00, 13.00, 11.00, 17.00, 12.00, 28.00, 21.00, 5.00, 19.00, 25.00, 13.00, 5.00, 10.00, 25.00, 21.00, 17.00, + 13.00, 20.00, 9.00, 16.00, 24.00, 18.00, 16.00, 22.00, 19.00, 10.00, 0.00, 14.00, 21.00, 24.00, 23.00, 10.00, 33.00, 23.00, 21.00, 17.00, + 17.00, 19.00, 26.00, 22.00, 12.00, 27.00, 31.00, 23.00, 6.00, 32.00, 12.00, 10.00, 9.00, 19.00, 18.00, 18.00, 20.00, 24.00, 17.00, 7.00, + 21.00, 27.00, 14.00, 20.00, 5.00, 19.00, 11.00, 18.00, 25.00, 1.00, 12.00, 21.00, 13.00, 26.00, 20.00, 3.00, 17.00, 28.00, 18.00, 16.00, + 13.00, 11.00, 11.00, 24.00, 2.00, 27.00, 18.00, 19.00, 18.00, 16.00, 25.00, 15.00, 9.00, 19.00, 26.00, 24.00, 19.00, 13.00, 16.00, 12.00, + 25.00, 12.00, 12.00, 24.00, 20.00, 9.00, 22.00, 6.00, 13.00, 11.00, 11.00, 20.00, 11.00, 22.00, 3.00, 17.00, 25.00, 14.00, 25.00, 16.00, + 3.00, 16.00, 23.00, 24.00, 24.00, 29.00, 24.00, 6.00, 12.00, 14.00, 23.00, 29.00, 23.00, 26.00, 14.00, 35.00, 17.00, 20.00, 12.00, 25.00, + 2.00, 29.00, 16.00, 3.00, 17.00, 32.00, 30.00, 5.00, 31.00, 25.00, 24.00, 29.00, 22.00, 26.00, 7.00, 14.00, 6.00, 11.00, 32.00, 1.00, + 18.00, 12.00, 20.00, 16.00, 15.00, 20.00, 19.00, 30.00, 23.00, 11.00, 12.00, 24.00, 13.00, 27.00, 2.00, 3.00, 36.00, 9.00, 13.00, 14.00, + 16.00, 23.00, 23.00, 24.00, 13.00, 22.00, 18.00, 26.00, 24.00, 22.00, 28.00, 23.00, 25.00, 28.00, 7.00, 14.00, 31.00, 15.00, 23.00, 25.00, + 15.00, 20.00, 15.00, 19.00, 8.00, 27.00, 25.00, 19.00, 21.00, 28.00, 11.00, 14.00, 25.00, 24.00, 11.00, 29.00, 19.00, 25.00, 16.00, 33.00, + 18.00, 9.00, 3.00, 13.00, 13.00, 13.00, 21.00, 20.00, 23.00, 7.00, 11.00, 18.00, 25.00, 26.00, 30.00, 12.00, 21.00, 21.00, 27.00, 14.00, + 21.00, 31.00, 3.00, 21.00, 14.00, 20.00, 30.00, 20.00, 21.00, 32.00, 27.00, 24.00, 16.00, 31.00, 5.00, 20.00, 14.00, 17.00, 15.00, 16.00, + 19.00, 13.00, 4.00, 21.00, 20.00, 29.00, 10.00, 22.00, 19.00, 24.00, 29.00, 14.00, 10.00, 15.00, 18.00, 7.00, 28.00, 17.00, 7.00, 2.00, + 1.00, 19.00, 17.00, 23.00, 31.00, 13.00, 20.00, 36.00, 17.00, 27.00, 28.00, 18.00, 20.00, 29.00, 17.00, 23.00, 24.00, 23.00, 26.00, 17.00, + 9.00, 26.00, 16.00, 18.00, 10.00, 28.00, 32.00, 20.00, 19.00, 14.00, 22.00, 23.00, 13.00, 22.00, 14.00, 7.00, 20.00, 10.00, 25.00, 9.00, + 7.00, 2.00, 31.00, 16.00, 16.00, 22.00, 5.00, 15.00, 26.00, 23.00, 10.00, 18.00, 32.00, 24.00, 15.00, 30.00, 16.00, 13.00, 15.00, 7.00, + 11.00, 6.00, 21.00, 14.00, 25.00, 21.00, 11.00, 16.00, 14.00, 26.00, 25.00, 15.00, 22.00, 24.00, 4.00, 19.00, 14.00, 26.00, 22.00, 17.00, + 13.00, 14.00, 7.00, 32.00, 20.00, 33.00, 13.00, 7.00, 29.00, 8.00, 26.00, 6.00, 9.00, 13.00, 22.00, 23.00, 8.00, 22.00, 22.00, 10.00, + 24.00, 2.00, 17.00, 9.00, 22.00, 30.00, 24.00, 33.00, 25.00, 17.00, 23.00, 9.00, 13.00, 15.00, 23.00, 10.00, 1.00, 22.00, 17.00, 10.00, + 32.00, 24.00, 26.00, 4.00, 15.00, 0.00, 27.00, 23.00, 28.00, 23.00, 30.00, 7.00, 16.00, 33.00, 20.00, 14.00, 23.00, 14.00, 20.00, 14.00, + 7.00, 25.00, 24.00, 12.00, 29.00, 16.00, 17.00, 20.00, 29.00, 16.00, 13.00, 18.00, 26.00, 18.00, 18.00, 17.00, 13.00, 29.00, 14.00, 17.00, + 24.00, 16.00, 21.00, 14.00, 26.00, 9.00, 11.00, 28.00, 25.00, 15.00, 15.00, 12.00, 6.00, 14.00, 27.00, 14.00, 24.00, 18.00, 18.00, 14.00, + 32.00, 21.00, 26.00, 13.00, 6.00, 24.00, 22.00, 27.00, 17.00, 26.00, 19.00, 21.00, 19.00, 9.00, 21.00, 25.00, 17.00, 27.00, 15.00, 18.00 +}; + diff --git a/benchmarks/mt-vvadd/mt-vvadd.c b/benchmarks/mt-vvadd/mt-vvadd.c new file mode 100644 index 0000000..497b9bb --- /dev/null +++ b/benchmarks/mt-vvadd/mt-vvadd.c @@ -0,0 +1,165 @@ +//************************************************************************** +// Vector-vector add benchmark +//-------------------------------------------------------------------------- +// Author : Andrew Waterman +// TA : Christopher Celio +// Student : +// +// This benchmark adds two vectors and writes the results to a +// third vector. The input data (and reference data) should be +// generated using the vvadd_gendata.pl perl script and dumped +// to a file named dataset.h + +// to print out arrays, etc. +//#define DEBUG + +//-------------------------------------------------------------------------- +// Includes + +#include +#include +#include + + +//-------------------------------------------------------------------------- +// Input/Reference Data + +typedef float data_t; +#include "dataset.h" + + +//-------------------------------------------------------------------------- +// Basic Utilities and Multi-thread Support + +__thread unsigned long coreid; +unsigned long ncores; + +#include "util.h" + +#define stringify_1(s) #s +#define stringify(s) stringify_1(s) +#define stats(code) do { \ + unsigned long _c = -rdcycle(), _i = -rdinstret(); \ + code; \ + _c += rdcycle(), _i += rdinstret(); \ + if (coreid == 0) \ + printf("%s: %ld cycles, %ld.%ld cycles/iter, %ld.%ld CPI\n", \ + stringify(code), _c, _c/DATA_SIZE, 10*_c/DATA_SIZE%10, _c/_i, 10*_c/_i%10); \ + } while(0) + + +//-------------------------------------------------------------------------- +// Helper functions + +void printArray( char name[], int n, data_t arr[] ) +{ + int i; + if (coreid != 0) + return; + + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " %4ld ", (long) arr[i] ); + printf( "\n" ); +} + +void __attribute__((noinline)) verify(size_t n, const data_t* test, const data_t* correct) +{ + if (coreid != 0) + return; + + size_t i; + for (i = 0; i < n; i++) + { + if (test[i] != correct[i]) + { + printf("FAILED test[%d]= %4ld, correct[%d]= %4ld\n", + i, (long) test[i], i, (long)correct[i]); + exit(-1); + } + } + + return; +} + +//-------------------------------------------------------------------------- +// vvadd function + +//perform in-place vvadd +void __attribute__((noinline)) vvadd(size_t n, data_t* __restrict__ x, const data_t* __restrict__ y) +{ + size_t i; + + // interleave accesses + for (i = coreid; i < n; i+=ncores) + { + x[i] = x[i] + y[i]; + } +} + +void __attribute__((noinline)) vvadd_opt(size_t n, data_t* __restrict__ x, const data_t* __restrict__ y) +{ + // ***************************** // + // **** ADD YOUR CODE HERE ***** // + // ***************************** // +} + +//-------------------------------------------------------------------------- +// Main +// +// all threads start executing thread_entry(). Use their "coreid" to +// differentiate between threads (each thread is running on a separate core). + +void thread_entry(int cid, int nc) +{ + coreid = cid; + ncores = nc; + + // static allocates data in the binary, which is visible to both threads + static data_t results_data[DATA_SIZE]; + + // because we're going to perform an in-place vvadd (and we're going to run + // it a couple of times) let's copy the input data to a temporary results + // array + + size_t i; + if (coreid == 0) + { + for (i = 0; i < DATA_SIZE; i++) + results_data[i] = input1_data[i]; + } + + + // Execute the provided, terrible vvadd + barrier(); + stats(vvadd(DATA_SIZE, results_data, input2_data); barrier()); + + + // verify + verify(DATA_SIZE, results_data, verify_data); + + // reset results from the first trial + if (coreid == 0) + { + for (i=0; i < DATA_SIZE; i++) + results_data[i] = input1_data[i]; + } + barrier(); + + + // Execute your faster vvadd + barrier(); + stats(vvadd_opt(DATA_SIZE, results_data, input2_data); barrier()); + +#ifdef DEBUG + printArray("results: ", DATA_SIZE, results_data); + printArray("verify : ", DATA_SIZE, verify_data); +#endif + + // verify + verify(DATA_SIZE, results_data, verify_data); + barrier(); + + exit(0); +} + diff --git a/benchmarks/mt-vvadd/vvadd_gendata.pl b/benchmarks/mt-vvadd/vvadd_gendata.pl new file mode 100755 index 0000000..a9fceac --- /dev/null +++ b/benchmarks/mt-vvadd/vvadd_gendata.pl @@ -0,0 +1,139 @@ +#!/usr/bin/perl -w +#========================================================================== +# vvadd_gendata.pl +# +# Author : Christopher Batten (cbatten@mit.edu) +# Date : April 29, 2005 +# +(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm; +# +# Simple script which creates an input data set and the reference data +# for the vvadd benchmark. +# +ENDMSG + +use strict "vars"; +use warnings; +no warnings("once"); +use Getopt::Long; + +#-------------------------------------------------------------------------- +# Command line processing +#-------------------------------------------------------------------------- + +our %opts; + +sub usage() +{ + + print "\n"; + print " Usage: vvadd_gendata.pl [options] \n"; + print "\n"; + print " Options:\n"; + print " --help print this message\n"; + print " --size size of input data [1000]\n"; + print " --seed random seed [1]\n"; + print "$usageMsg"; + + exit(); +} + +sub processCommandLine() +{ + + $opts{"help"} = 0; + $opts{"size"} = 1000; + $opts{"seed"} = 1; + Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage(); + $opts{"help"} and usage(); + +} + +#-------------------------------------------------------------------------- +# Helper Functions +#-------------------------------------------------------------------------- + +sub printArray +{ + my $arrayName = $_[0]; + my $arrayRef = $_[1]; + + my $numCols = 20; + my $arrayLen = scalar(@{$arrayRef}); + + print "static data_t ".$arrayName."[DATA_SIZE] = \n"; + print "{\n"; + + if ( $arrayLen <= $numCols ) { + print " "; + for ( my $i = 0; $i < $arrayLen; $i++ ) { + print sprintf("%3.2f",$arrayRef->[$i]); + if ( $i != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + else { + my $numRows = int($arrayLen/$numCols); + for ( my $j = 0; $j < $numRows; $j++ ) { + print " "; + for ( my $i = 0; $i < $numCols; $i++ ) { + my $index = $j*$numCols + $i; + print sprintf("%3.2f",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + if ( $arrayLen > ($numRows*$numCols) ) { + print " "; + for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) { + my $index = $numCols*$numRows + $i; + print sprintf("%3.2f",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + } + + print "};\n\n"; +} + +#-------------------------------------------------------------------------- +# Main +#-------------------------------------------------------------------------- + +sub main() +{ + + processCommandLine(); + srand($opts{"seed"}); + + my @values1; + my @values2; + my @sum; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + my $value1 = int(rand(19)); + my $value2 = int(rand(19)); + push( @values1, $value1 ); + push( @values2, $value2 ); + push( @sum, $value1 + $value2 ); + } + + + print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n"; + printArray( "input1_data", \@values1 ); + printArray( "input2_data", \@values2 ); + printArray( "verify_data", \@sum ); + +} + +main(); + diff --git a/benchmarks/multiply/bmark.mk b/benchmarks/multiply/bmark.mk new file mode 100644 index 0000000..d6114a1 --- /dev/null +++ b/benchmarks/multiply/bmark.mk @@ -0,0 +1,30 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +multiply_c_src = \ + multiply_main.c \ + multiply.c \ + +multiply_riscv_src = \ + crt.S \ + +multiply_c_objs = $(patsubst %.c, %.o, $(multiply_c_src)) +multiply_riscv_objs = $(patsubst %.S, %.o, $(multiply_riscv_src)) + +multiply_host_bin = multiply.host +$(multiply_host_bin): $(multiply_c_src) + $(HOST_COMP) $^ -o $(multiply_host_bin) + +multiply_riscv_bin = multiply.riscv +$(multiply_riscv_bin): $(multiply_c_objs) $(multiply_riscv_objs) + $(RISCV_LINK) $(multiply_c_objs) $(multiply_riscv_objs) -o $(multiply_riscv_bin) + +junk += $(multiply_c_objs) $(multiply_riscv_objs) \ + $(multiply_host_bin) $(multiply_riscv_bin) diff --git a/benchmarks/multiply/dataset1.h b/benchmarks/multiply/dataset1.h new file mode 100644 index 0000000..292ad7f --- /dev/null +++ b/benchmarks/multiply/dataset1.h @@ -0,0 +1,30 @@ + +#define DATA_SIZE 100 + +int input_data1[DATA_SIZE] = +{ + 41, 454, 833, 335, 564, 1, 187, 989, 749, 365, 350, 572, 132, 64, 949, 153, 584, 216, 805, 140, + 621, 210, 6, 572, 931, 339, 890, 593, 392, 898, 694, 228, 961, 12, 110, 883, 116, 750, 296, 646, + 426, 500, 314, 436, 659, 701, 774, 812, 319, 981, 678, 150, 875, 696, 376, 564, 474, 272, 938, 258, + 539, 647, 569, 509, 203, 88, 280, 703, 759, 669, 606, 375, 511, 551, 657, 936, 195, 592, 81, 569, + 267, 952, 229, 800, 337, 584, 944, 643, 902, 368, 241, 489, 913, 328, 826, 313, 933, 592, 985, 388 +}; + +int input_data2[DATA_SIZE] = +{ + 195, 543, 960, 649, 566, 979, 350, 997, 649, 814, 657, 79, 181, 208, 111, 998, 859, 629, 65, 847, + 288, 704, 349, 997, 141, 253, 905, 715, 886, 430, 264, 415, 576, 538, 979, 700, 761, 4, 241, 494, + 478, 100, 499, 864, 403, 693, 222, 416, 444, 296, 721, 285, 676, 620, 317, 78, 224, 351, 937, 540, + 288, 646, 119, 169, 615, 527, 606, 289, 389, 796, 351, 801, 455, 720, 278, 758, 367, 745, 358, 92, + 584, 989, 62, 271, 985, 853, 403, 788, 346, 531, 517, 222, 559, 461, 908, 241, 775, 358, 255, 332 +}; + +int verify_data[DATA_SIZE] = +{ + 7995, 246522, 799680, 217415, 319224, 979, 65450, 986033, 486101, 297110, 229950, 45188, 23892, 13312, 105339, 152694, 501656, 135864, 52325, 118580, + 178848, 147840, 2094, 570284, 131271, 85767, 805450, 423995, 347312, 386140, 183216, 94620, 553536, 6456, 107690, 618100, 88276, 3000, 71336, 319124, + 203628, 50000, 156686, 376704, 265577, 485793, 171828, 337792, 141636, 290376, 488838, 42750, 591500, 431520, 119192, 43992, 106176, 95472, 878906, 139320, + 155232, 417962, 67711, 86021, 124845, 46376, 169680, 203167, 295251, 532524, 212706, 300375, 232505, 396720, 182646, 709488, 71565, 441040, 28998, 52348, + 155928, 941528, 14198, 216800, 331945, 498152, 380432, 506684, 312092, 195408, 124597, 108558, 510367, 151208, 750008, 75433, 723075, 211936, 251175, 128816 +}; + diff --git a/benchmarks/multiply/multiply.c b/benchmarks/multiply/multiply.c new file mode 100644 index 0000000..98b279b --- /dev/null +++ b/benchmarks/multiply/multiply.c @@ -0,0 +1,22 @@ +// ************************************************************************* +// multiply function (c version) +// ------------------------------------------------------------------------- + +int multiply( int x, int y ) +{ + + int i; + int result = 0; + + for (i = 0; i < 32; i++) { + if ((x & 0x1) == 1) + result = result + y; + + x = x >> 1; + y = y << 1; + } + + return result; + +} + diff --git a/benchmarks/multiply/multiply.h b/benchmarks/multiply/multiply.h new file mode 100644 index 0000000..6d27795 --- /dev/null +++ b/benchmarks/multiply/multiply.h @@ -0,0 +1,9 @@ +//************************************************************************** +// Software multiply function +//-------------------------------------------------------------------------- + +// Simple C version +int multiply(int x, int y); + +// Simple assembly version +int multiply_asm(int x, int y); diff --git a/benchmarks/multiply/multiply_gendata.pl b/benchmarks/multiply/multiply_gendata.pl new file mode 100755 index 0000000..b8d8ed5 --- /dev/null +++ b/benchmarks/multiply/multiply_gendata.pl @@ -0,0 +1,142 @@ +#!/usr/bin/perl -w +#========================================================================== +# multiply_gendata.pl +# +# Author : Christopher Batten (cbatten@mit.edu) +# Date : May 9, 2005 +# +(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm; +# +# Simple script which creates an input data set and the reference data +# for the multiply benchmark. +# +ENDMSG + +use strict "vars"; +use warnings; +no warnings("once"); +use Getopt::Long; + +#-------------------------------------------------------------------------- +# Command line processing +#-------------------------------------------------------------------------- + +our %opts; + +sub usage() +{ + + print "\n"; + print " Usage: multiply_gendata.pl [options] \n"; + print "\n"; + print " Options:\n"; + print " --help print this message\n"; + print " --size size of input data [750]\n"; + print " --seed random seed [1]\n"; + print "$usageMsg"; + + exit(); +} + +sub processCommandLine() +{ + + $opts{"help"} = 0; + $opts{"size"} = 750; + $opts{"seed"} = 1; + Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage(); + $opts{"help"} and usage(); + +} + +#-------------------------------------------------------------------------- +# Helper Functions +#-------------------------------------------------------------------------- + +sub printArray +{ + my $arrayName = $_[0]; + my $arrayRef = $_[1]; + + my $numCols = 20; + my $arrayLen = scalar(@{$arrayRef}); + + print "int ".$arrayName."[DATA_SIZE] = \n"; + print "{\n"; + + if ( $arrayLen <= $numCols ) { + print " "; + for ( my $i = 0; $i < $arrayLen; $i++ ) { + print sprintf("%3d",$arrayRef->[$i]); + if ( $i != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + else { + my $numRows = int($arrayLen/$numCols); + for ( my $j = 0; $j < $numRows; $j++ ) { + print " "; + for ( my $i = 0; $i < $numCols; $i++ ) { + my $index = $j*$numCols + $i; + print sprintf("%3d",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + if ( $arrayLen > ($numRows*$numCols) ) { + print " "; + for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) { + my $index = $numCols*$numRows + $i; + print sprintf("%3d",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + } + + print "};\n\n"; +} + +#-------------------------------------------------------------------------- +# Main +#-------------------------------------------------------------------------- + +sub main() +{ + + processCommandLine(); + srand($opts{"seed"}); + + my @values1; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + push( @values1, int(rand(999)) ); + } + + my @values2; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + push( @values2, int(rand(999)) ); + } + + my @multiply; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + $multiply[$i] = $values1[$i] * $values2[$i]; + } + + print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n"; + printArray( "input_data1", \@values1 ); + printArray( "input_data2", \@values2 ); + printArray( "verify_data", \@multiply ); + +} + +main(); + diff --git a/benchmarks/multiply/multiply_main.c b/benchmarks/multiply/multiply_main.c new file mode 100644 index 0000000..fcb6b27 --- /dev/null +++ b/benchmarks/multiply/multiply_main.c @@ -0,0 +1,147 @@ +// ************************************************************************* +// multiply filter bencmark +// ------------------------------------------------------------------------- +// +// This benchmark tests the software multiply implemenation. The +// input data (and reference data) should be generated using the +// multiply_gendata.pl perl script and dumped to a file named +// dataset1.h You should not change anything except the +// HOST_DEBUG and VERIFY macros for your timing run. + +#include "multiply.h" + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set VERIFY to 1 if you want the program to check that the sort +// function returns the right answer. When you are doing your +// benchmarking you should set this to 0 so that the verification +// is not included in your timing. + +#ifndef VERIFY +#define VERIFY 1 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +//-------------------------------------------------------------------------- +// Input/Reference Data + +#include "dataset1.h" + +//-------------------------------------------------------------------------- +// Helper functions + +int verify( int n, int test[], int correct[] ) +{ + int i; + for ( i = 0; i < n; i++ ) { + if ( test[i] != correct[i] ) { + return 2; + } + } + return 1; +} + +#if HOST_DEBUG +void printArray( char name[], int n, int arr[] ) +{ + int i; + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " %3d ", arr[i] ); + printf( "\n" ); +} +#endif + +void finishTest( int toHostValue ) +{ +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + asm( "mtpcr %0, cr30" : : "r" (toHostValue) ); + while ( 1 ) { } +#endif +} + +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +//-------------------------------------------------------------------------- +// Main + +int main( int argc, char* argv[] ) +{ + int i; + int results_data[DATA_SIZE]; + + // Output the input arrays + +#if HOST_DEBUG + printArray( "input1", DATA_SIZE, input_data1 ); + printArray( "input2", DATA_SIZE, input_data2 ); + printArray( "verify", DATA_SIZE, verify_data ); +#endif + +#if ( !HOST_DEBUG && PREALLOCATE ) + for (i = 0; i < DATA_SIZE; i++) + { + results_data[i] = multiply( input_data1[i], input_data2[i] ); + } +#endif + +#if HOST_DEBUG + for (i = 0; i < DATA_SIZE; i++) + { + results_data[i] = multiply( input_data1[i], input_data2[i] ); + } +#else + setStats(1); + for (i = 0; i < DATA_SIZE; i++) + { + results_data[i] = multiply( input_data1[i], input_data2[i] ); + } + setStats(0); +#endif + + // Print out the results + +#if HOST_DEBUG + printArray( "results", DATA_SIZE, results_data ); +#endif + + // Check the results + + finishTest(verify( DATA_SIZE, results_data, verify_data )); + +} diff --git a/benchmarks/qsort/bmark.mk b/benchmarks/qsort/bmark.mk new file mode 100644 index 0000000..cdc0545 --- /dev/null +++ b/benchmarks/qsort/bmark.mk @@ -0,0 +1,29 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +qsort_c_src = \ + qsort_main.c \ + +qsort_riscv_src = \ + crt.S \ + +qsort_c_objs = $(patsubst %.c, %.o, $(qsort_c_src)) +qsort_riscv_objs = $(patsubst %.S, %.o, $(qsort_riscv_src)) + +qsort_host_bin = qsort.host +$(qsort_host_bin) : $(qsort_c_src) + $(HOST_COMP) $^ -o $(qsort_host_bin) + +qsort_riscv_bin = qsort.riscv +$(qsort_riscv_bin) : $(qsort_c_objs) $(qsort_riscv_objs) + $(RISCV_LINK) $(qsort_c_objs) $(qsort_riscv_objs) -o $(qsort_riscv_bin) + +junk += $(qsort_c_objs) $(qsort_riscv_objs) \ + $(qsort_host_bin) $(qsort_riscv_bin) diff --git a/benchmarks/qsort/dataset1.h b/benchmarks/qsort/dataset1.h new file mode 100644 index 0000000..c4d99e2 --- /dev/null +++ b/benchmarks/qsort/dataset1.h @@ -0,0 +1,37 @@ + +#define DATA_SIZE 250 + +int input_data[DATA_SIZE] = +{ + 41, 454, 833, 335, 564, 1, 187, 989, 749, 365, 350, 572, 132, 64, 949, 153, 584, 216, 805, 140, + 621, 210, 6, 572, 931, 339, 890, 593, 392, 898, 694, 228, 961, 12, 110, 883, 116, 750, 296, 646, + 426, 500, 314, 436, 659, 701, 774, 812, 319, 981, 678, 150, 875, 696, 376, 564, 474, 272, 938, 258, + 539, 647, 569, 509, 203, 88, 280, 703, 759, 669, 606, 375, 511, 551, 657, 936, 195, 592, 81, 569, + 267, 952, 229, 800, 337, 584, 944, 643, 902, 368, 241, 489, 913, 328, 826, 313, 933, 592, 985, 388, + 195, 543, 960, 649, 566, 979, 350, 997, 649, 814, 657, 79, 181, 208, 111, 998, 859, 629, 65, 847, + 288, 704, 349, 997, 141, 253, 905, 715, 886, 430, 264, 415, 576, 538, 979, 700, 761, 4, 241, 494, + 478, 100, 499, 864, 403, 693, 222, 416, 444, 296, 721, 285, 676, 620, 317, 78, 224, 351, 937, 540, + 288, 646, 119, 169, 615, 527, 606, 289, 389, 796, 351, 801, 455, 720, 278, 758, 367, 745, 358, 92, + 584, 989, 62, 271, 985, 853, 403, 788, 346, 531, 517, 222, 559, 461, 908, 241, 775, 358, 255, 332, + 778, 684, 598, 740, 143, 446, 33, 311, 125, 743, 941, 557, 933, 479, 799, 557, 553, 925, 431, 796, + 648, 357, 952, 891, 287, 666, 19, 514, 49, 557, 86, 870, 95, 853, 441, 440, 587, 61, 614, 678, + 382, 396, 280, 9, 808, 17, 971, 170, 819, 291 +}; + +int verify_data[DATA_SIZE] = +{ + 1, 4, 6, 9, 12, 17, 19, 33, 41, 49, 61, 62, 64, 65, 78, 79, 81, 86, 88, 92, + 95, 100, 110, 111, 116, 119, 125, 132, 140, 141, 143, 150, 153, 169, 170, 181, 187, 195, 195, 203, + 208, 210, 216, 222, 222, 224, 228, 229, 241, 241, 241, 253, 255, 258, 264, 267, 271, 272, 278, 280, + 280, 285, 287, 288, 288, 289, 291, 296, 296, 311, 313, 314, 317, 319, 328, 332, 335, 337, 339, 346, + 349, 350, 350, 351, 351, 357, 358, 358, 365, 367, 368, 375, 376, 382, 388, 389, 392, 396, 403, 403, + 415, 416, 426, 430, 431, 436, 440, 441, 444, 446, 454, 455, 461, 474, 478, 479, 489, 494, 499, 500, + 509, 511, 514, 517, 527, 531, 538, 539, 540, 543, 551, 553, 557, 557, 557, 559, 564, 564, 566, 569, + 569, 572, 572, 576, 584, 584, 584, 587, 592, 592, 593, 598, 606, 606, 614, 615, 620, 621, 629, 643, + 646, 646, 647, 648, 649, 649, 657, 657, 659, 666, 669, 676, 678, 678, 684, 693, 694, 696, 700, 701, + 703, 704, 715, 720, 721, 740, 743, 745, 749, 750, 758, 759, 761, 774, 775, 778, 788, 796, 796, 799, + 800, 801, 805, 808, 812, 814, 819, 826, 833, 847, 853, 853, 859, 864, 870, 875, 883, 886, 890, 891, + 898, 902, 905, 908, 913, 925, 931, 933, 933, 936, 937, 938, 941, 944, 949, 952, 952, 960, 961, 971, + 979, 979, 981, 985, 985, 989, 989, 997, 997, 998 +}; + diff --git a/benchmarks/qsort/qsort_gendata.pl b/benchmarks/qsort/qsort_gendata.pl new file mode 100755 index 0000000..0a1af61 --- /dev/null +++ b/benchmarks/qsort/qsort_gendata.pl @@ -0,0 +1,132 @@ +#!/usr/bin/perl -w +#========================================================================== +# qsort_gendata.pl +# +# Author : Christopher Batten (cbatten@mit.edu) +# Date : April 29, 2005 +# +(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm; +# +# Simple script which creates an input data set and the reference data +# for the qsort benchmark. +# +ENDMSG + +use strict "vars"; +use warnings; +no warnings("once"); +use Getopt::Long; + +#-------------------------------------------------------------------------- +# Command line processing +#-------------------------------------------------------------------------- + +our %opts; + +sub usage() +{ + + print "\n"; + print " Usage: qsort_gendata.pl [options] \n"; + print "\n"; + print " Options:\n"; + print " --help print this message\n"; + print " --size size of input data [250]\n"; + print " --seed random seed [1]\n"; + print "$usageMsg"; + + exit(); +} + +sub processCommandLine() +{ + + $opts{"help"} = 0; + $opts{"size"} = 250; + $opts{"seed"} = 1; + Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage(); + $opts{"help"} and usage(); + +} + +#-------------------------------------------------------------------------- +# Helper Functions +#-------------------------------------------------------------------------- + +sub printArray +{ + my $arrayName = $_[0]; + my $arrayRef = $_[1]; + + my $numCols = 20; + my $arrayLen = scalar(@{$arrayRef}); + + print "int ".$arrayName."[DATA_SIZE] = \n"; + print "{\n"; + + if ( $arrayLen <= $numCols ) { + print " "; + for ( my $i = 0; $i < $arrayLen; $i++ ) { + print sprintf("%3d",$arrayRef->[$i]); + if ( $i != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + else { + my $numRows = int($arrayLen/$numCols); + for ( my $j = 0; $j < $numRows; $j++ ) { + print " "; + for ( my $i = 0; $i < $numCols; $i++ ) { + my $index = $j*$numCols + $i; + print sprintf("%3d",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + if ( $arrayLen > ($numRows*$numCols) ) { + print " "; + for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) { + my $index = $numCols*$numRows + $i; + print sprintf("%3d",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + } + + print "};\n\n"; +} + +#-------------------------------------------------------------------------- +# Main +#-------------------------------------------------------------------------- + +sub main() +{ + + processCommandLine(); + srand($opts{"seed"}); + + my @values; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + push( @values, int(rand(999)) ); + } + my @sorted = sort { $a <=> $b } @values; + + print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n"; + printArray( "input_data", \@values ); + printArray( "verify_data", \@sorted ); + +} + +main(); + diff --git a/benchmarks/qsort/qsort_main.c b/benchmarks/qsort/qsort_main.c new file mode 100644 index 0000000..6de1613 --- /dev/null +++ b/benchmarks/qsort/qsort_main.c @@ -0,0 +1,239 @@ +//************************************************************************** +// Quicksort benchmark +//-------------------------------------------------------------------------- +// +// This benchmark uses quicksort to sort an array of integers. The +// implementation is largely adapted from Numerical Recipes for C. The +// input data (and reference data) should be generated using the +// qsort_gendata.pl perl script and dumped to a file named +// dataset1.h The smips-gcc toolchain does not support system calls +// so printf's can only be used on a host system, not on the smips +// processor simulator itself. You should not change anything except +// the HOST_DEBUG and PREALLOCATE macros for your timing run. + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +// The INSERTION_THRESHOLD is the size of the subarray when the +// algorithm switches to using an insertion sort instead of +// quick sort. + +#define INSERTION_THRESHOLD 7 + +// NSTACK is the required auxiliary storage. +// It must be at least 2*lg(DATA_SIZE) + +#define NSTACK 50 + +// Swap macro for swapping two values. + +#define SWAP(a,b) temp=(a);(a)=(b);(b)=temp; + +//-------------------------------------------------------------------------- +// Input/Reference Data + +#include "dataset1.h" + +//-------------------------------------------------------------------------- +// Helper functions + +int verify( int n, int test[], int correct[] ) +{ + int i; + for ( i = 0; i < n; i++ ) { + if ( test[i] != correct[i] ) { + return 2; + } + } + return 1; +} + +#if HOST_DEBUG +void printArray( char name[], int n, int arr[] ) +{ + int i; + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " %3d ", arr[i] ); + printf( "\n" ); +} +#endif + +void finishTest( int toHostValue ) +{ +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + asm( "mtpcr %0, cr30" : : "r" (toHostValue) ); + while ( 1 ) { } +#endif +} + +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +//-------------------------------------------------------------------------- +// Quicksort function + +void sort( int n, int arr[] ) +{ + int i,j,k; + int ir = n; + int l = 1; + int jstack = 0; + int a, temp; + + int istack[NSTACK]; + + for (;;) { + +#if HOST_DEBUG + printArray( "", n, arr ); +#endif + + // Insertion sort when subarray small enough. + if ( ir-l < INSERTION_THRESHOLD ) { + + for ( j = l+1; j <= ir; j++ ) { + a = arr[j-1]; + for ( i = j-1; i >= l; i-- ) { + if ( arr[i-1] <= a ) break; + arr[i] = arr[i-1]; + } + arr[i] = a; + } + + if ( jstack == 0 ) break; + + // Pop stack and begin a new round of partitioning. + ir = istack[jstack--]; + l = istack[jstack--]; + + } + else { + + // Choose median of left, center, and right elements as + // partitioning element a. Also rearrange so that a[l-1] <= a[l] <= a[ir-]. + + k = (l+ir) >> 1; + SWAP(arr[k-1],arr[l]) + if ( arr[l-1] > arr[ir-1] ) { + SWAP(arr[l-1],arr[ir-1]) + } + if ( arr[l] > arr[ir-1] ) { + SWAP(arr[l],arr[ir-1]) + } + if ( arr[l-1] > arr[l] ) { + SWAP(arr[l-1],arr[l]) + } + + // Initialize pointers for partitioning. + i = l+1; + j = ir; + + // Partitioning element. + a = arr[l]; + + for (;;) { // Beginning of innermost loop. + do i++; while (arr[i-1] < a); // Scan up to find element > a. + do j--; while (arr[j-1] > a); // Scan down to find element < a. + if (j < i) break; // Pointers crossed. Partitioning complete. + SWAP(arr[i-1],arr[j-1]); // Exchange elements. + } // End of innermost loop. + + // Insert partitioning element. + arr[l] = arr[j-1]; + arr[j-1] = a; + jstack += 2; + + // Push pointers to larger subarray on stack, + // process smaller subarray immediately. + +#if HOST_DEBUG + if ( jstack > NSTACK ) { printf("NSTACK too small in sort.\n"); exit(1); } +#endif + + if ( ir-i+1 >= j-l ) { + istack[jstack] = ir; + istack[jstack-1] = i; + ir = j-1; + } + else { + istack[jstack] = j-1; + istack[jstack-1] = l; + l = i; + } + } + + } + +} + +//-------------------------------------------------------------------------- +// Main + +int main( int argc, char* argv[] ) +{ + + // Output the input array + +#if HOST_DEBUG + printArray( "input", DATA_SIZE, input_data ); + printArray( "verify", DATA_SIZE, verify_data ); +#endif + + // If needed we preallocate everything in the caches + +#if PREALLOCATE + sort( DATA_SIZE, input_data ); +#endif + + // Do the sort + + setStats(1); + sort( DATA_SIZE, input_data ); + setStats(0); + + // Print out the results + +#if HOST_DEBUG + printArray( "test", DATA_SIZE, input_data ); +#endif + + // Check the results + + finishTest(verify( DATA_SIZE, input_data, verify_data )); + +} diff --git a/benchmarks/readme.txt b/benchmarks/readme.txt new file mode 100644 index 0000000..a14780f --- /dev/null +++ b/benchmarks/readme.txt @@ -0,0 +1,55 @@ +************************************************************************* +Benchmarks for RISCV Processor +------------------------------------------------------------------------- + +The benchmarks make use of the RISCV C compiler toolchain. You will need +to include a bmark.mk makefile fragment in each benchmark directory. The +fragment should include the object files and a rule to actually link +these object files into an executable. There are a couple important +points to make about the toolchain. + + + The toolchain sets the stack pointer to memory address 0x20000 so your + main memory _must_ be larger than 0x20000 bytes or else the stack will + get wrapped around and overwrite program data. + + + The stack grows down from 0x20000 and your program is loaded at 0x1000. + If you have a very large program and have lots of very big arrays + declared on the stack your stack could overwrite your program. Be aware. + + + You cannot use standard clib functions (like memcopy or strcat). You + cannot use system calls and thus cannot use printf. + + + You cannot access the simulated command line - ie you cannot use argc + and argv within main. + + + You may have to increase the timeout check in your test harness to + allow longer programs to run (you can do this from the command line + option +max-cycles with the standard test harness) + + + The compiler loads the program at 0x1000. It does not insert exception + setup code. So if you are careful with what C you use it will only + generate code in the riscv lab1 subset. If you use multiplies, shorts, + and chars it could generate mul, lh, and lb instructions. Be aware. + + + You can write assembly in C - you need to do this to write tohost to 1 + to indicate when the benchmark is done. Look at the example + benchmarks to see how this is done. You can find more information + about how to write assembly in C here: + http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html + + + If you look at the example benchmarks you will see that I have two + important macros HOST_DEBUG and VERIFY. Use HOST_DEBUG to compile the + benchmark on your host workstation (ie use standard gcc on Athena/Linux + box) and then debug the benchmark. Since you are using standard gcc you + can use printf's to make sure that your benchmark actually works before + trying it out on your RISCV processor. + + + Debugging C compiled code on the RISCV processor is a real pain. It is + hard to associate the assembly with the C code and there is no + debugger. So if you encounter a bug in your processor when running a C + benchmark you can try to debug it, but you might have better luck + adding more assembly tests to your test suite. + + + To avoid having the compiler try and use a global pointer (ie using + register 28 to point to a space where small global variables are + stored) you need to use the -G 0 command line option. diff --git a/benchmarks/spmv/bmark.mk b/benchmarks/spmv/bmark.mk new file mode 100644 index 0000000..5ab9cc0 --- /dev/null +++ b/benchmarks/spmv/bmark.mk @@ -0,0 +1,29 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +spmv_c_src = \ + spmv_main.c \ + +spmv_riscv_src = \ + crt.S \ + +spmv_c_objs = $(patsubst %.c, %.o, $(spmv_c_src)) +spmv_riscv_objs = $(patsubst %.S, %.o, $(spmv_riscv_src)) + +spmv_host_bin = spmv.host +$(spmv_host_bin) : $(spmv_c_src) + $(HOST_COMP) $^ -o $(spmv_host_bin) + +spmv_riscv_bin = spmv.riscv +$(spmv_riscv_bin) : $(spmv_c_objs) $(spmv_riscv_objs) + $(RISCV_LINK) $(spmv_c_objs) $(spmv_riscv_objs) -o $(spmv_riscv_bin) + +junk += $(spmv_c_objs) $(spmv_riscv_objs) \ + $(spmv_host_bin) $(spmv_riscv_bin) diff --git a/benchmarks/spmv/dataset1.h b/benchmarks/spmv/dataset1.h new file mode 100644 index 0000000..ebdf7ff --- /dev/null +++ b/benchmarks/spmv/dataset1.h @@ -0,0 +1,23022 @@ +#define R 1000 +#define C 1000 +#define NNZ 10004 +const double val[10004] = { + 658, + 279, + 587, + 255, + 359, + 844, + 905, + 456, + 897, + 837, + 652, + 398, + 885, + 21, + 669, + 738, + 365, + 928, + 713, + 771, + 536, + 987, + 917, + 823, + 544, + 40, + 80, + 636, + 263, + 929, + 757, + 677, + 151, + 500, + 875, + 720, + 205, + 292, + 859, + 980, + 97, + 608, + 813, + 840, + 397, + 765, + 294, + 718, + 751, + 7, + 482, + 166, + 653, + 172, + 187, + 79, + 228, + 857, + 540, + 760, + 509, + 190, + 396, + 765, + 37, + 85, + 866, + 981, + 999, + 793, + 921, + 664, + 208, + 856, + 528, + 782, + 318, + 170, + 521, + 691, + 726, + 996, + 947, + 326, + 825, + 77, + 823, + 752, + 266, + 834, + 196, + 58, + 430, + 764, + 807, + 568, + 665, + 583, + 178, + 250, + 273, + 654, + 487, + 504, + 729, + 338, + 866, + 981, + 852, + 842, + 785, + 13, + 588, + 44, + 432, + 408, + 374, + 761, + 653, + 752, + 684, + 6, + 357, + 703, + 447, + 966, + 457, + 738, + 646, + 646, + 217, + 522, + 839, + 417, + 506, + 801, + 233, + 929, + 487, + 353, + 660, + 751, + 738, + 512, + 566, + 130, + 61, + 128, + 698, + 467, + 362, + 867, + 639, + 289, + 371, + 427, + 650, + 16, + 878, + 967, + 369, + 517, + 161, + 330, + 294, + 396, + 606, + 638, + 171, + 602, + 531, + 14, + 968, + 15, + 193, + 225, + 863, + 171, + 254, + 714, + 256, + 873, + 353, + 35, + 910, + 849, + 658, + 546, + 389, + 239, + 355, + 540, + 494, + 968, + 319, + 590, + 608, + 445, + 806, + 51, + 117, + 401, + 314, + 280, + 334, + 44, + 17, + 107, + 108, + 650, + 807, + 385, + 748, + 942, + 719, + 110, + 630, + 559, + 717, + 375, + 963, + 45, + 403, + 476, + 408, + 732, + 87, + 874, + 635, + 119, + 190, + 949, + 777, + 201, + 503, + 658, + 777, + 564, + 830, + 122, + 929, + 68, + 11, + 354, + 395, + 213, + 766, + 40, + 995, + 577, + 514, + 568, + 56, + 439, + 91, + 148, + 612, + 717, + 157, + 538, + 682, + 190, + 571, + 847, + 275, + 190, + 824, + 985, + 29, + 426, + 173, + 898, + 297, + 156, + 936, + 1, + 455, + 812, + 173, + 131, + 376, + 947, + 596, + 783, + 800, + 361, + 798, + 598, + 710, + 86, + 149, + 457, + 129, + 437, + 352, + 933, + 320, + 709, + 167, + 793, + 46, + 49, + 305, + 704, + 577, + 855, + 336, + 978, + 206, + 662, + 230, + 93, + 898, + 368, + 422, + 689, + 351, + 87, + 465, + 576, + 33, + 884, + 675, + 548, + 116, + 730, + 385, + 483, + 340, + 809, + 938, + 342, + 576, + 887, + 479, + 455, + 820, + 521, + 320, + 488, + 506, + 591, + 901, + 505, + 525, + 5, + 133, + 705, + 561, + 285, + 95, + 918, + 410, + 578, + 347, + 375, + 735, + 624, + 491, + 494, + 931, + 655, + 819, + 883, + 328, + 527, + 194, + 580, + 584, + 837, + 700, + 681, + 249, + 643, + 958, + 363, + 316, + 397, + 638, + 261, + 459, + 960, + 636, + 458, + 84, + 797, + 696, + 782, + 831, + 419, + 393, + 649, + 312, + 811, + 703, + 70, + 688, + 285, + 39, + 617, + 935, + 495, + 392, + 143, + 734, + 166, + 406, + 464, + 732, + 709, + 379, + 143, + 527, + 514, + 709, + 130, + 965, + 632, + 448, + 836, + 62, + 567, + 600, + 520, + 519, + 16, + 394, + 705, + 438, + 548, + 696, + 140, + 573, + 509, + 968, + 935, + 165, + 868, + 577, + 451, + 865, + 304, + 777, + 828, + 147, + 704, + 821, + 641, + 783, + 376, + 757, + 391, + 170, + 592, + 235, + 920, + 846, + 683, + 249, + 697, + 253, + 386, + 244, + 889, + 607, + 768, + 88, + 836, + 259, + 945, + 33, + 352, + 70, + 83, + 996, + 791, + 18, + 599, + 488, + 43, + 582, + 993, + 692, + 841, + 558, + 530, + 350, + 187, + 295, + 215, + 869, + 593, + 385, + 722, + 724, + 282, + 681, + 534, + 788, + 836, + 378, + 825, + 93, + 539, + 120, + 794, + 384, + 798, + 505, + 833, + 27, + 181, + 951, + 966, + 498, + 375, + 22, + 545, + 62, + 816, + 119, + 712, + 813, + 783, + 655, + 832, + 143, + 501, + 519, + 43, + 760, + 17, + 896, + 96, + 390, + 121, + 458, + 736, + 649, + 227, + 778, + 283, + 657, + 434, + 214, + 123, + 929, + 548, + 206, + 993, + 463, + 824, + 369, + 260, + 868, + 645, + 857, + 184, + 198, + 349, + 652, + 522, + 23, + 208, + 968, + 290, + 770, + 109, + 978, + 513, + 298, + 675, + 306, + 866, + 927, + 822, + 495, + 653, + 134, + 702, + 147, + 366, + 947, + 65, + 586, + 412, + 638, + 760, + 541, + 118, + 551, + 574, + 85, + 736, + 999, + 917, + 478, + 35, + 629, + 963, + 898, + 826, + 113, + 298, + 606, + 568, + 152, + 926, + 277, + 984, + 549, + 279, + 839, + 348, + 672, + 278, + 94, + 455, + 590, + 843, + 85, + 222, + 901, + 621, + 30, + 880, + 914, + 27, + 974, + 399, + 873, + 968, + 870, + 479, + 696, + 964, + 929, + 499, + 121, + 812, + 933, + 799, + 506, + 412, + 712, + 791, + 426, + 835, + 488, + 910, + 522, + 332, + 967, + 380, + 61, + 5, + 282, + 119, + 22, + 136, + 436, + 730, + 341, + 687, + 371, + 19, + 893, + 20, + 327, + 221, + 221, + 966, + 354, + 198, + 985, + 56, + 305, + 691, + 980, + 12, + 790, + 64, + 484, + 621, + 214, + 332, + 898, + 898, + 318, + 416, + 445, + 350, + 317, + 336, + 714, + 788, + 541, + 890, + 42, + 111, + 596, + 164, + 424, + 448, + 666, + 362, + 429, + 617, + 910, + 917, + 970, + 526, + 321, + 551, + 481, + 83, + 46, + 146, + 569, + 856, + 85, + 192, + 724, + 378, + 299, + 13, + 422, + 411, + 552, + 569, + 100, + 849, + 484, + 906, + 47, + 532, + 742, + 415, + 228, + 897, + 715, + 807, + 329, + 244, + 312, + 903, + 758, + 34, + 172, + 18, + 917, + 700, + 108, + 611, + 567, + 616, + 572, + 174, + 925, + 553, + 903, + 268, + 544, + 998, + 708, + 133, + 717, + 584, + 517, + 608, + 680, + 597, + 316, + 470, + 764, + 530, + 221, + 405, + 133, + 406, + 506, + 56, + 458, + 721, + 935, + 356, + 130, + 99, + 395, + 117, + 34, + 881, + 231, + 214, + 248, + 458, + 246, + 632, + 471, + 279, + 385, + 594, + 855, + 305, + 30, + 542, + 144, + 509, + 548, + 364, + 171, + 386, + 382, + 616, + 997, + 28, + 361, + 855, + 449, + 992, + 956, + 439, + 569, + 383, + 523, + 852, + 337, + 112, + 24, + 902, + 352, + 542, + 231, + 664, + 411, + 457, + 572, + 52, + 760, + 88, + 907, + 345, + 284, + 636, + 219, + 975, + 713, + 231, + 888, + 49, + 624, + 179, + 579, + 401, + 694, + 984, + 905, + 673, + 414, + 773, + 165, + 349, + 436, + 128, + 186, + 487, + 17, + 552, + 833, + 98, + 424, + 791, + 220, + 352, + 75, + 470, + 405, + 679, + 939, + 792, + 653, + 142, + 226, + 208, + 629, + 429, + 55, + 455, + 362, + 210, + 765, + 693, + 113, + 656, + 824, + 441, + 191, + 50, + 957, + 99, + 27, + 582, + 461, + 279, + 299, + 492, + 678, + 452, + 640, + 349, + 758, + 298, + 903, + 361, + 333, + 339, + 60, + 824, + 773, + 184, + 621, + 66, + 49, + 228, + 608, + 523, + 591, + 533, + 234, + 566, + 291, + 646, + 93, + 42, + 810, + 154, + 846, + 426, + 32, + 828, + 360, + 917, + 182, + 50, + 40, + 182, + 19, + 127, + 614, + 951, + 662, + 591, + 140, + 110, + 685, + 549, + 6, + 346, + 766, + 689, + 743, + 414, + 135, + 61, + 548, + 363, + 915, + 462, + 526, + 405, + 524, + 192, + 754, + 796, + 616, + 98, + 341, + 786, + 778, + 929, + 6, + 388, + 293, + 513, + 148, + 298, + 311, + 29, + 456, + 960, + 560, + 895, + 121, + 511, + 141, + 732, + 762, + 774, + 261, + 287, + 314, + 801, + 320, + 173, + 616, + 356, + 783, + 256, + 129, + 513, + 212, + 293, + 168, + 813, + 279, + 65, + 784, + 360, + 921, + 320, + 177, + 923, + 385, + 142, + 380, + 772, + 929, + 718, + 277, + 61, + 620, + 575, + 772, + 356, + 414, + 775, + 392, + 523, + 760, + 192, + 905, + 606, + 134, + 695, + 784, + 540, + 63, + 939, + 941, + 887, + 217, + 290, + 893, + 206, + 662, + 63, + 102, + 74, + 943, + 288, + 8, + 254, + 131, + 420, + 841, + 79, + 139, + 362, + 221, + 915, + 6, + 28, + 417, + 846, + 996, + 794, + 522, + 391, + 513, + 715, + 87, + 449, + 801, + 823, + 16, + 485, + 874, + 8, + 601, + 885, + 146, + 886, + 318, + 235, + 390, + 561, + 869, + 640, + 860, + 433, + 651, + 145, + 149, + 682, + 612, + 580, + 946, + 572, + 155, + 736, + 898, + 774, + 81, + 882, + 286, + 362, + 982, + 788, + 658, + 452, + 889, + 688, + 384, + 948, + 342, + 402, + 777, + 403, + 547, + 123, + 187, + 394, + 470, + 978, + 234, + 461, + 127, + 349, + 476, + 927, + 837, + 997, + 494, + 167, + 920, + 911, + 84, + 432, + 339, + 87, + 841, + 535, + 972, + 671, + 395, + 445, + 681, + 494, + 737, + 492, + 96, + 84, + 261, + 871, + 91, + 696, + 960, + 346, + 430, + 796, + 326, + 272, + 982, + 25, + 927, + 923, + 528, + 924, + 215, + 789, + 691, + 898, + 811, + 189, + 284, + 856, + 200, + 278, + 436, + 354, + 114, + 978, + 648, + 797, + 437, + 916, + 220, + 449, + 740, + 179, + 484, + 470, + 332, + 178, + 65, + 807, + 860, + 180, + 421, + 148, + 563, + 253, + 691, + 121, + 837, + 851, + 341, + 948, + 563, + 635, + 780, + 148, + 567, + 713, + 118, + 877, + 505, + 519, + 975, + 504, + 745, + 190, + 958, + 134, + 898, + 723, + 546, + 781, + 46, + 760, + 530, + 572, + 163, + 227, + 886, + 408, + 586, + 4, + 901, + 233, + 753, + 720, + 203, + 575, + 748, + 443, + 207, + 838, + 492, + 290, + 223, + 256, + 715, + 830, + 432, + 97, + 99, + 477, + 725, + 574, + 91, + 746, + 731, + 615, + 629, + 437, + 320, + 843, + 559, + 13, + 902, + 779, + 564, + 689, + 207, + 599, + 726, + 598, + 606, + 148, + 58, + 115, + 536, + 319, + 279, + 944, + 485, + 699, + 948, + 13, + 895, + 766, + 582, + 559, + 998, + 250, + 788, + 869, + 877, + 23, + 647, + 488, + 164, + 845, + 344, + 545, + 307, + 991, + 0, + 805, + 152, + 412, + 534, + 323, + 614, + 415, + 865, + 847, + 210, + 743, + 122, + 943, + 594, + 320, + 268, + 154, + 253, + 816, + 347, + 768, + 953, + 982, + 606, + 131, + 813, + 92, + 339, + 5, + 707, + 517, + 526, + 469, + 537, + 89, + 141, + 537, + 557, + 190, + 659, + 87, + 659, + 401, + 367, + 414, + 460, + 34, + 96, + 895, + 740, + 694, + 352, + 537, + 592, + 877, + 137, + 922, + 915, + 99, + 216, + 969, + 716, + 44, + 869, + 856, + 853, + 352, + 556, + 216, + 426, + 231, + 259, + 172, + 67, + 694, + 488, + 311, + 712, + 767, + 279, + 962, + 265, + 615, + 141, + 454, + 711, + 384, + 452, + 135, + 90, + 391, + 787, + 665, + 528, + 296, + 824, + 820, + 455, + 885, + 301, + 155, + 647, + 6, + 973, + 627, + 663, + 922, + 969, + 799, + 698, + 523, + 404, + 784, + 422, + 128, + 103, + 233, + 601, + 812, + 281, + 600, + 336, + 11, + 743, + 288, + 925, + 181, + 228, + 508, + 308, + 3, + 141, + 711, + 602, + 71, + 868, + 255, + 307, + 24, + 862, + 567, + 134, + 74, + 755, + 947, + 111, + 812, + 42, + 295, + 650, + 859, + 78, + 128, + 462, + 308, + 290, + 372, + 166, + 111, + 364, + 469, + 591, + 127, + 56, + 840, + 758, + 781, + 756, + 548, + 658, + 412, + 851, + 134, + 233, + 432, + 257, + 138, + 210, + 184, + 986, + 51, + 806, + 442, + 711, + 243, + 571, + 861, + 550, + 111, + 798, + 138, + 316, + 746, + 549, + 276, + 458, + 866, + 335, + 334, + 178, + 191, + 473, + 452, + 764, + 487, + 525, + 273, + 457, + 902, + 888, + 519, + 203, + 891, + 497, + 998, + 535, + 382, + 673, + 787, + 112, + 846, + 836, + 898, + 681, + 607, + 546, + 863, + 639, + 896, + 281, + 845, + 305, + 410, + 835, + 985, + 245, + 781, + 208, + 337, + 248, + 205, + 264, + 198, + 305, + 665, + 351, + 609, + 186, + 444, + 589, + 130, + 292, + 668, + 617, + 611, + 111, + 80, + 9, + 267, + 275, + 135, + 201, + 926, + 789, + 835, + 221, + 290, + 297, + 93, + 437, + 892, + 921, + 994, + 748, + 321, + 23, + 394, + 725, + 377, + 581, + 57, + 219, + 461, + 54, + 183, + 506, + 889, + 920, + 714, + 639, + 836, + 585, + 787, + 929, + 597, + 307, + 678, + 35, + 296, + 46, + 459, + 368, + 342, + 200, + 609, + 265, + 11, + 315, + 10, + 29, + 32, + 339, + 250, + 974, + 736, + 834, + 281, + 332, + 656, + 530, + 384, + 96, + 544, + 775, + 208, + 375, + 230, + 31, + 589, + 385, + 130, + 718, + 82, + 909, + 267, + 482, + 503, + 875, + 824, + 488, + 837, + 757, + 19, + 121, + 129, + 531, + 712, + 76, + 183, + 137, + 764, + 617, + 846, + 64, + 65, + 775, + 593, + 526, + 53, + 923, + 142, + 330, + 153, + 199, + 71, + 584, + 423, + 770, + 318, + 965, + 493, + 953, + 238, + 416, + 471, + 978, + 436, + 501, + 505, + 264, + 789, + 199, + 241, + 800, + 168, + 34, + 291, + 399, + 972, + 890, + 462, + 670, + 628, + 19, + 204, + 99, + 751, + 742, + 231, + 397, + 5, + 204, + 886, + 763, + 706, + 218, + 775, + 730, + 231, + 425, + 118, + 778, + 886, + 537, + 364, + 691, + 19, + 114, + 195, + 665, + 675, + 359, + 653, + 185, + 76, + 351, + 221, + 695, + 147, + 1, + 109, + 790, + 749, + 299, + 358, + 11, + 581, + 511, + 614, + 950, + 916, + 923, + 764, + 245, + 487, + 508, + 471, + 71, + 482, + 614, + 660, + 834, + 875, + 433, + 470, + 650, + 753, + 828, + 360, + 551, + 946, + 215, + 358, + 689, + 468, + 280, + 98, + 363, + 451, + 20, + 842, + 913, + 105, + 575, + 798, + 199, + 612, + 778, + 959, + 295, + 322, + 760, + 963, + 854, + 191, + 629, + 165, + 420, + 127, + 515, + 858, + 783, + 487, + 499, + 534, + 451, + 373, + 116, + 973, + 576, + 184, + 587, + 765, + 975, + 945, + 960, + 801, + 802, + 793, + 32, + 608, + 312, + 533, + 916, + 92, + 625, + 661, + 374, + 967, + 332, + 554, + 259, + 838, + 475, + 765, + 833, + 74, + 39, + 780, + 446, + 132, + 270, + 583, + 378, + 677, + 805, + 921, + 723, + 624, + 67, + 434, + 875, + 847, + 149, + 881, + 104, + 729, + 327, + 239, + 791, + 22, + 717, + 647, + 118, + 353, + 791, + 129, + 253, + 60, + 938, + 533, + 408, + 994, + 849, + 789, + 764, + 797, + 687, + 892, + 203, + 880, + 903, + 946, + 294, + 830, + 698, + 297, + 478, + 305, + 452, + 258, + 30, + 799, + 756, + 793, + 937, + 775, + 14, + 383, + 276, + 481, + 215, + 317, + 879, + 52, + 628, + 654, + 429, + 753, + 848, + 606, + 629, + 748, + 832, + 335, + 733, + 90, + 396, + 690, + 482, + 54, + 12, + 306, + 535, + 750, + 116, + 524, + 383, + 475, + 214, + 178, + 784, + 798, + 563, + 935, + 806, + 949, + 53, + 694, + 273, + 124, + 284, + 619, + 45, + 521, + 715, + 851, + 132, + 424, + 438, + 319, + 538, + 981, + 802, + 986, + 340, + 600, + 353, + 980, + 637, + 505, + 17, + 280, + 855, + 237, + 432, + 184, + 955, + 538, + 935, + 480, + 421, + 580, + 423, + 928, + 926, + 930, + 732, + 210, + 351, + 346, + 469, + 100, + 288, + 353, + 788, + 232, + 130, + 79, + 360, + 870, + 439, + 47, + 661, + 595, + 636, + 52, + 389, + 986, + 159, + 454, + 317, + 961, + 915, + 76, + 342, + 895, + 53, + 396, + 15, + 66, + 139, + 310, + 636, + 549, + 440, + 926, + 132, + 734, + 726, + 696, + 332, + 229, + 896, + 486, + 316, + 840, + 403, + 557, + 963, + 67, + 401, + 318, + 13, + 109, + 745, + 296, + 653, + 711, + 718, + 2, + 951, + 853, + 130, + 22, + 879, + 878, + 759, + 466, + 520, + 25, + 403, + 952, + 914, + 29, + 133, + 156, + 467, + 435, + 896, + 78, + 488, + 55, + 739, + 861, + 521, + 904, + 498, + 748, + 703, + 489, + 21, + 377, + 322, + 248, + 818, + 176, + 531, + 564, + 1, + 694, + 362, + 876, + 165, + 881, + 325, + 475, + 810, + 181, + 30, + 455, + 255, + 673, + 320, + 600, + 602, + 568, + 974, + 350, + 826, + 212, + 504, + 91, + 21, + 317, + 275, + 775, + 422, + 278, + 795, + 826, + 818, + 377, + 295, + 165, + 496, + 753, + 425, + 554, + 243, + 964, + 169, + 281, + 109, + 884, + 334, + 692, + 641, + 411, + 352, + 66, + 765, + 196, + 508, + 696, + 866, + 369, + 725, + 838, + 82, + 62, + 300, + 637, + 29, + 108, + 859, + 222, + 768, + 442, + 891, + 38, + 523, + 158, + 856, + 949, + 852, + 145, + 630, + 686, + 109, + 577, + 371, + 673, + 807, + 224, + 169, + 148, + 890, + 329, + 653, + 720, + 898, + 771, + 65, + 712, + 735, + 606, + 578, + 836, + 17, + 498, + 31, + 275, + 54, + 494, + 831, + 255, + 266, + 574, + 693, + 418, + 226, + 351, + 867, + 287, + 717, + 708, + 104, + 131, + 863, + 474, + 600, + 323, + 235, + 80, + 710, + 719, + 924, + 168, + 168, + 979, + 24, + 755, + 935, + 78, + 386, + 41, + 546, + 155, + 306, + 366, + 814, + 445, + 883, + 504, + 332, + 920, + 265, + 484, + 591, + 98, + 981, + 576, + 392, + 905, + 927, + 715, + 264, + 598, + 847, + 753, + 329, + 350, + 983, + 179, + 993, + 810, + 809, + 155, + 508, + 564, + 896, + 733, + 734, + 714, + 637, + 560, + 186, + 751, + 601, + 636, + 361, + 916, + 10, + 542, + 258, + 286, + 756, + 471, + 858, + 97, + 373, + 699, + 1, + 707, + 260, + 900, + 145, + 979, + 143, + 487, + 427, + 863, + 472, + 638, + 672, + 309, + 980, + 332, + 480, + 26, + 184, + 40, + 723, + 102, + 856, + 785, + 298, + 816, + 525, + 160, + 897, + 421, + 697, + 122, + 571, + 372, + 138, + 892, + 370, + 805, + 754, + 113, + 993, + 448, + 471, + 423, + 96, + 331, + 419, + 144, + 172, + 987, + 170, + 788, + 400, + 346, + 139, + 676, + 380, + 257, + 350, + 89, + 592, + 501, + 664, + 19, + 957, + 462, + 302, + 430, + 880, + 869, + 99, + 70, + 356, + 931, + 751, + 43, + 531, + 790, + 559, + 455, + 64, + 846, + 139, + 685, + 876, + 166, + 361, + 28, + 876, + 223, + 147, + 928, + 619, + 734, + 870, + 738, + 393, + 293, + 722, + 301, + 936, + 566, + 57, + 881, + 398, + 796, + 134, + 566, + 932, + 756, + 860, + 638, + 546, + 33, + 144, + 29, + 628, + 254, + 764, + 604, + 357, + 987, + 552, + 400, + 663, + 874, + 727, + 586, + 988, + 684, + 867, + 343, + 733, + 349, + 534, + 976, + 708, + 998, + 871, + 564, + 271, + 105, + 397, + 40, + 884, + 62, + 43, + 361, + 451, + 188, + 520, + 953, + 709, + 796, + 522, + 365, + 263, + 807, + 14, + 439, + 395, + 800, + 614, + 831, + 675, + 532, + 95, + 332, + 538, + 318, + 526, + 1, + 689, + 111, + 487, + 370, + 203, + 211, + 642, + 549, + 158, + 206, + 298, + 846, + 87, + 717, + 363, + 83, + 200, + 769, + 504, + 670, + 536, + 349, + 294, + 441, + 239, + 721, + 400, + 355, + 212, + 120, + 623, + 664, + 94, + 116, + 126, + 904, + 947, + 938, + 152, + 542, + 464, + 735, + 926, + 112, + 590, + 1, + 209, + 102, + 237, + 258, + 552, + 427, + 808, + 319, + 631, + 769, + 884, + 24, + 132, + 697, + 878, + 344, + 335, + 391, + 384, + 27, + 533, + 900, + 96, + 279, + 121, + 998, + 558, + 987, + 848, + 426, + 191, + 925, + 623, + 850, + 163, + 184, + 819, + 881, + 279, + 850, + 517, + 178, + 727, + 603, + 152, + 657, + 412, + 17, + 120, + 241, + 718, + 785, + 921, + 237, + 982, + 936, + 745, + 810, + 507, + 207, + 267, + 17, + 967, + 133, + 73, + 627, + 20, + 158, + 69, + 829, + 769, + 457, + 436, + 986, + 723, + 248, + 784, + 704, + 146, + 408, + 0, + 170, + 209, + 720, + 958, + 149, + 321, + 919, + 924, + 223, + 35, + 326, + 196, + 513, + 992, + 884, + 467, + 877, + 695, + 432, + 281, + 722, + 633, + 209, + 616, + 140, + 93, + 274, + 31, + 401, + 971, + 177, + 946, + 782, + 271, + 934, + 159, + 416, + 861, + 9, + 607, + 415, + 747, + 444, + 487, + 701, + 191, + 88, + 850, + 580, + 93, + 59, + 309, + 477, + 613, + 974, + 126, + 348, + 256, + 573, + 578, + 865, + 805, + 280, + 90, + 858, + 924, + 455, + 681, + 307, + 581, + 714, + 156, + 224, + 534, + 198, + 63, + 489, + 144, + 123, + 288, + 500, + 221, + 618, + 674, + 233, + 440, + 788, + 569, + 70, + 472, + 166, + 12, + 979, + 722, + 929, + 108, + 736, + 666, + 525, + 631, + 554, + 287, + 742, + 65, + 324, + 248, + 710, + 489, + 834, + 199, + 338, + 851, + 793, + 960, + 761, + 383, + 891, + 973, + 943, + 853, + 422, + 178, + 600, + 890, + 732, + 384, + 431, + 476, + 237, + 104, + 622, + 839, + 904, + 805, + 512, + 57, + 17, + 630, + 378, + 32, + 996, + 247, + 209, + 254, + 119, + 396, + 565, + 630, + 782, + 633, + 138, + 318, + 112, + 545, + 743, + 616, + 663, + 89, + 367, + 495, + 845, + 127, + 597, + 434, + 129, + 692, + 109, + 168, + 953, + 668, + 590, + 177, + 578, + 46, + 707, + 413, + 115, + 788, + 513, + 243, + 935, + 953, + 58, + 584, + 64, + 569, + 367, + 978, + 249, + 290, + 125, + 183, + 852, + 485, + 847, + 895, + 835, + 25, + 289, + 995, + 226, + 156, + 980, + 520, + 656, + 255, + 37, + 852, + 719, + 493, + 473, + 900, + 417, + 647, + 363, + 759, + 778, + 735, + 349, + 627, + 525, + 255, + 13, + 58, + 399, + 222, + 70, + 304, + 663, + 158, + 152, + 788, + 103, + 693, + 274, + 873, + 116, + 837, + 876, + 367, + 272, + 778, + 65, + 363, + 625, + 696, + 809, + 16, + 491, + 615, + 196, + 88, + 0, + 204, + 418, + 203, + 952, + 205, + 240, + 962, + 899, + 872, + 222, + 961, + 363, + 920, + 659, + 935, + 943, + 198, + 385, + 475, + 298, + 936, + 22, + 204, + 947, + 776, + 911, + 581, + 661, + 340, + 433, + 188, + 622, + 117, + 154, + 150, + 388, + 214, + 513, + 625, + 875, + 779, + 262, + 972, + 396, + 803, + 396, + 991, + 976, + 900, + 387, + 371, + 522, + 162, + 234, + 733, + 314, + 331, + 666, + 44, + 205, + 66, + 422, + 780, + 978, + 661, + 775, + 647, + 511, + 670, + 515, + 88, + 714, + 579, + 133, + 499, + 837, + 506, + 904, + 172, + 248, + 476, + 836, + 898, + 514, + 396, + 852, + 568, + 706, + 533, + 54, + 72, + 167, + 493, + 809, + 588, + 792, + 34, + 325, + 827, + 878, + 440, + 708, + 348, + 589, + 708, + 271, + 577, + 857, + 999, + 547, + 579, + 502, + 298, + 330, + 790, + 687, + 99, + 245, + 721, + 264, + 826, + 487, + 501, + 783, + 194, + 469, + 991, + 653, + 87, + 946, + 556, + 707, + 104, + 879, + 160, + 15, + 1, + 95, + 323, + 870, + 521, + 897, + 840, + 699, + 410, + 751, + 42, + 342, + 802, + 547, + 862, + 168, + 5, + 561, + 488, + 170, + 237, + 655, + 179, + 909, + 847, + 536, + 360, + 44, + 371, + 9, + 473, + 253, + 400, + 563, + 683, + 471, + 625, + 823, + 414, + 590, + 312, + 407, + 971, + 929, + 614, + 705, + 249, + 69, + 348, + 527, + 915, + 978, + 728, + 593, + 641, + 627, + 144, + 653, + 818, + 763, + 116, + 676, + 611, + 451, + 203, + 589, + 62, + 984, + 165, + 631, + 42, + 873, + 56, + 256, + 459, + 134, + 722, + 235, + 798, + 291, + 977, + 646, + 36, + 156, + 546, + 113, + 96, + 964, + 156, + 570, + 366, + 718, + 816, + 726, + 385, + 188, + 184, + 154, + 921, + 821, + 329, + 928, + 176, + 688, + 942, + 204, + 240, + 423, + 498, + 422, + 115, + 696, + 1, + 850, + 309, + 733, + 628, + 595, + 930, + 467, + 888, + 638, + 448, + 895, + 10, + 938, + 848, + 116, + 193, + 390, + 415, + 330, + 359, + 115, + 371, + 432, + 229, + 264, + 141, + 162, + 491, + 397, + 2, + 141, + 761, + 471, + 68, + 55, + 628, + 593, + 891, + 84, + 808, + 740, + 196, + 196, + 511, + 901, + 324, + 464, + 627, + 461, + 900, + 995, + 118, + 486, + 960, + 709, + 451, + 432, + 997, + 785, + 480, + 20, + 351, + 25, + 955, + 40, + 788, + 56, + 254, + 329, + 601, + 293, + 704, + 639, + 743, + 983, + 177, + 722, + 193, + 708, + 34, + 202, + 364, + 404, + 487, + 436, + 867, + 906, + 442, + 472, + 718, + 610, + 366, + 991, + 639, + 821, + 604, + 618, + 538, + 266, + 781, + 958, + 542, + 744, + 116, + 604, + 835, + 310, + 847, + 277, + 138, + 979, + 930, + 962, + 3, + 641, + 976, + 673, + 928, + 851, + 456, + 963, + 604, + 336, + 360, + 467, + 374, + 536, + 56, + 729, + 272, + 563, + 205, + 301, + 583, + 329, + 632, + 151, + 678, + 100, + 234, + 74, + 315, + 289, + 759, + 313, + 854, + 558, + 997, + 905, + 186, + 261, + 863, + 607, + 41, + 70, + 234, + 147, + 448, + 619, + 179, + 65, + 716, + 309, + 858, + 408, + 143, + 61, + 760, + 308, + 115, + 116, + 233, + 598, + 170, + 675, + 117, + 147, + 511, + 935, + 857, + 761, + 397, + 692, + 940, + 606, + 235, + 50, + 297, + 219, + 216, + 501, + 489, + 22, + 792, + 878, + 722, + 293, + 667, + 71, + 663, + 870, + 294, + 596, + 885, + 140, + 169, + 325, + 8, + 107, + 780, + 536, + 320, + 652, + 975, + 155, + 371, + 901, + 716, + 175, + 240, + 296, + 355, + 416, + 277, + 187, + 178, + 977, + 254, + 679, + 799, + 428, + 123, + 66, + 195, + 143, + 700, + 648, + 653, + 570, + 363, + 942, + 352, + 981, + 175, + 815, + 618, + 479, + 760, + 663, + 298, + 944, + 716, + 925, + 796, + 312, + 509, + 365, + 165, + 945, + 52, + 787, + 270, + 663, + 358, + 452, + 103, + 809, + 345, + 62, + 545, + 863, + 116, + 952, + 951, + 810, + 297, + 884, + 386, + 683, + 991, + 161, + 48, + 267, + 672, + 558, + 977, + 2, + 827, + 848, + 293, + 860, + 247, + 564, + 141, + 285, + 134, + 736, + 604, + 789, + 441, + 723, + 714, + 911, + 957, + 597, + 510, + 547, + 274, + 761, + 684, + 747, + 652, + 536, + 114, + 555, + 176, + 743, + 923, + 442, + 629, + 984, + 703, + 957, + 620, + 822, + 47, + 186, + 669, + 17, + 168, + 377, + 271, + 562, + 420, + 799, + 820, + 73, + 439, + 884, + 919, + 306, + 164, + 749, + 123, + 830, + 461, + 452, + 353, + 589, + 305, + 907, + 949, + 288, + 733, + 975, + 454, + 821, + 394, + 329, + 776, + 69, + 134, + 808, + 888, + 663, + 594, + 378, + 691, + 175, + 951, + 234, + 635, + 969, + 838, + 443, + 447, + 399, + 563, + 442, + 750, + 523, + 909, + 889, + 768, + 390, + 61, + 896, + 865, + 534, + 72, + 558, + 267, + 678, + 930, + 662, + 655, + 15, + 153, + 885, + 631, + 724, + 475, + 919, + 691, + 260, + 925, + 49, + 798, + 761, + 314, + 497, + 116, + 789, + 548, + 1, + 258, + 388, + 137, + 467, + 706, + 580, + 717, + 110, + 290, + 513, + 408, + 639, + 72, + 629, + 772, + 67, + 460, + 612, + 46, + 88, + 330, + 790, + 854, + 708, + 610, + 334, + 180, + 901, + 718, + 647, + 281, + 135, + 80, + 583, + 591, + 828, + 405, + 843, + 30, + 709, + 657, + 329, + 53, + 351, + 336, + 445, + 249, + 761, + 14, + 187, + 628, + 154, + 381, + 915, + 589, + 911, + 849, + 515, + 39, + 58, + 17, + 790, + 825, + 446, + 99, + 674, + 155, + 407, + 324, + 888, + 447, + 662, + 324, + 588, + 659, + 898, + 234, + 12, + 418, + 514, + 833, + 149, + 241, + 655, + 350, + 256, + 869, + 127, + 629, + 236, + 334, + 940, + 175, + 685, + 224, + 243, + 866, + 979, + 495, + 375, + 525, + 869, + 524, + 894, + 919, + 4, + 184, + 348, + 75, + 892, + 379, + 899, + 177, + 709, + 762, + 356, + 612, + 992, + 723, + 47, + 227, + 317, + 542, + 703, + 279, + 969, + 946, + 473, + 208, + 60, + 872, + 674, + 116, + 360, + 616, + 976, + 253, + 862, + 119, + 649, + 710, + 851, + 690, + 448, + 714, + 152, + 489, + 62, + 833, + 207, + 594, + 100, + 375, + 9, + 497, + 111, + 442, + 116, + 818, + 749, + 177, + 898, + 403, + 243, + 228, + 741, + 680, + 393, + 292, + 726, + 628, + 149, + 127, + 525, + 320, + 404, + 831, + 842, + 852, + 367, + 849, + 66, + 448, + 978, + 941, + 165, + 565, + 960, + 631, + 220, + 220, + 154, + 584, + 841, + 386, + 582, + 233, + 22, + 608, + 508, + 454, + 503, + 267, + 660, + 899, + 404, + 660, + 451, + 86, + 966, + 694, + 133, + 320, + 811, + 966, + 556, + 377, + 653, + 244, + 718, + 255, + 748, + 6, + 237, + 11, + 668, + 411, + 351, + 360, + 833, + 91, + 414, + 264, + 447, + 816, + 962, + 197, + 774, + 504, + 426, + 161, + 42, + 714, + 130, + 699, + 64, + 307, + 15, + 719, + 917, + 452, + 573, + 184, + 297, + 10, + 249, + 628, + 440, + 761, + 170, + 588, + 537, + 318, + 130, + 207, + 376, + 696, + 203, + 202, + 790, + 737, + 133, + 966, + 24, + 127, + 820, + 109, + 53, + 185, + 38, + 946, + 96, + 352, + 529, + 349, + 678, + 309, + 51, + 680, + 881, + 489, + 940, + 962, + 163, + 900, + 797, + 461, + 431, + 973, + 204, + 597, + 681, + 483, + 903, + 351, + 885, + 646, + 358, + 891, + 564, + 405, + 989, + 656, + 628, + 749, + 23, + 243, + 407, + 178, + 22, + 132, + 883, + 365, + 471, + 941, + 762, + 226, + 403, + 87, + 231, + 589, + 543, + 346, + 737, + 817, + 261, + 857, + 869, + 996, + 27, + 280, + 595, + 538, + 113, + 628, + 587, + 677, + 641, + 421, + 176, + 262, + 399, + 786, + 970, + 330, + 936, + 633, + 690, + 156, + 855, + 313, + 550, + 707, + 201, + 910, + 556, + 248, + 34, + 432, + 547, + 622, + 737, + 233, + 941, + 694, + 526, + 409, + 458, + 133, + 900, + 248, + 670, + 109, + 802, + 295, + 233, + 117, + 923, + 139, + 855, + 382, + 757, + 399, + 462, + 115, + 447, + 444, + 53, + 235, + 163, + 232, + 333, + 335, + 219, + 625, + 95, + 674, + 879, + 204, + 460, + 370, + 829, + 943, + 420, + 10, + 538, + 863, + 694, + 537, + 124, + 406, + 294, + 131, + 306, + 420, + 12, + 385, + 107, + 33, + 153, + 815, + 899, + 989, + 845, + 875, + 772, + 172, + 308, + 285, + 1, + 721, + 487, + 495, + 310, + 222, + 950, + 874, + 211, + 837, + 723, + 834, + 407, + 327, + 658, + 647, + 1, + 278, + 524, + 266, + 906, + 312, + 955, + 632, + 631, + 515, + 440, + 334, + 122, + 559, + 72, + 785, + 431, + 621, + 61, + 584, + 588, + 594, + 16, + 217, + 50, + 831, + 188, + 52, + 393, + 993, + 495, + 848, + 480, + 456, + 370, + 424, + 777, + 718, + 39, + 186, + 466, + 773, + 185, + 508, + 464, + 989, + 135, + 971, + 470, + 682, + 443, + 97, + 124, + 838, + 135, + 186, + 427, + 544, + 719, + 411, + 244, + 64, + 273, + 568, + 160, + 173, + 273, + 185, + 826, + 238, + 841, + 840, + 553, + 33, + 758, + 873, + 162, + 707, + 158, + 166, + 714, + 461, + 573, + 566, + 256, + 903, + 798, + 242, + 561, + 763, + 334, + 164, + 781, + 73, + 309, + 228, + 71, + 643, + 774, + 672, + 507, + 676, + 406, + 695, + 623, + 993, + 729, + 898, + 324, + 420, + 903, + 599, + 622, + 129, + 694, + 716, + 742, + 632, + 89, + 740, + 417, + 606, + 494, + 697, + 697, + 655, + 30, + 87, + 617, + 604, + 101, + 537, + 566, + 828, + 969, + 570, + 993, + 883, + 127, + 625, + 985, + 804, + 553, + 874, + 758, + 396, + 875, + 133, + 224, + 853, + 877, + 710, + 782, + 155, + 923, + 416, + 794, + 663, + 200, + 30, + 689, + 77, + 218, + 632, + 849, + 60, + 270, + 446, + 419, + 697, + 980, + 892, + 935, + 24, + 717, + 178, + 471, + 497, + 209, + 743, + 284, + 3, + 813, + 234, + 76, + 527, + 145, + 684, + 742, + 500, + 832, + 533, + 780, + 226, + 800, + 897, + 102, + 309, + 994, + 775, + 888, + 944, + 243, + 54, + 17, + 107, + 929, + 52, + 244, + 843, + 553, + 701, + 236, + 53, + 909, + 972, + 753, + 927, + 796, + 81, + 679, + 394, + 649, + 991, + 973, + 903, + 797, + 321, + 763, + 37, + 991, + 544, + 268, + 236, + 10, + 923, + 443, + 394, + 720, + 76, + 434, + 280, + 314, + 91, + 934, + 848, + 217, + 697, + 646, + 53, + 647, + 723, + 154, + 894, + 943, + 217, + 641, + 64, + 987, + 58, + 98, + 191, + 819, + 510, + 708, + 33, + 747, + 400, + 513, + 360, + 526, + 173, + 733, + 234, + 759, + 525, + 485, + 463, + 382, + 261, + 826, + 870, + 999, + 655, + 564, + 947, + 334, + 479, + 963, + 641, + 647, + 554, + 497, + 688, + 818, + 941, + 20, + 235, + 523, + 847, + 527, + 290, + 535, + 244, + 312, + 703, + 779, + 768, + 732, + 734, + 759, + 228, + 671, + 245, + 304, + 191, + 808, + 502, + 219, + 948, + 24, + 398, + 268, + 540, + 243, + 691, + 966, + 768, + 631, + 38, + 446, + 446, + 697, + 82, + 824, + 893, + 696, + 553, + 563, + 502, + 25, + 34, + 648, + 753, + 857, + 8, + 341, + 801, + 913, + 802, + 177, + 805, + 155, + 242, + 920, + 148, + 139, + 517, + 413, + 252, + 225, + 766, + 663, + 767, + 179, + 615, + 212, + 299, + 424, + 125, + 155, + 717, + 263, + 174, + 390, + 849, + 645, + 242, + 572, + 768, + 821, + 739, + 12, + 398, + 617, + 875, + 957, + 14, + 791, + 633, + 539, + 221, + 80, + 487, + 467, + 88, + 234, + 770, + 816, + 947, + 220, + 967, + 942, + 344, + 993, + 79, + 388, + 415, + 886, + 335, + 967, + 560, + 486, + 606, + 49, + 114, + 582, + 891, + 544, + 623, + 858, + 875, + 986, + 486, + 549, + 196, + 198, + 108, + 152, + 545, + 430, + 569, + 122, + 123, + 386, + 163, + 269, + 400, + 774, + 65, + 689, + 802, + 35, + 629, + 738, + 662, + 930, + 494, + 45, + 816, + 412, + 401, + 728, + 336, + 584, + 876, + 14, + 27, + 12, + 224, + 482, + 304, + 852, + 352, + 163, + 300, + 545, + 554, + 958, + 621, + 872, + 192, + 450, + 400, + 195, + 339, + 916, + 344, + 341, + 814, + 450, + 292, + 783, + 818, + 573, + 187, + 992, + 219, + 103, + 894, + 857, + 262, + 204, + 570, + 30, + 293, + 454, + 72, + 568, + 273, + 112, + 923, + 247, + 251, + 780, + 590, + 349, + 311, + 856, + 583, + 566, + 965, + 74, + 260, + 523, + 413, + 892, + 640, + 718, + 646, + 244, + 2, + 440, + 492, + 906, + 619, + 94, + 124, + 732, + 250, + 906, + 669, + 903, + 885, + 494, + 972, + 619, + 414, + 627, + 131, + 249, + 528, + 447, + 992, + 345, + 940, + 765, + 238, + 131, + 900, + 327, + 554, + 975, + 547, + 630, + 428, + 673, + 144, + 690, + 200, + 148, + 405, + 29, + 680, + 559, + 896, + 321, + 736, + 540, + 197, + 154, + 373, + 221, + 78, + 134, + 443, + 514, + 40, + 577, + 529, + 205, + 83, + 366, + 475, + 703, + 166, + 31, + 340, + 803, + 940, + 181, + 134, + 520, + 159, + 99, + 168, + 404, + 343, + 317, + 298, + 715, + 303, + 990, + 32, + 999, + 653, + 151, + 913, + 449, + 884, + 571, + 139, + 806, + 296, + 375, + 476, + 206, + 45, + 991, + 607, + 5, + 851, + 283, + 642, + 396, + 370, + 25, + 24, + 418, + 679, + 469, + 607, + 355, + 600, + 83, + 32, + 787, + 834, + 972, + 351, + 948, + 356, + 270, + 606, + 322, + 279, + 966, + 138, + 832, + 428, + 306, + 889, + 828, + 34, + 449, + 879, + 205, + 227, + 67, + 132, + 845, + 506, + 317, + 867, + 353, + 804, + 532, + 41, + 157, + 400, + 691, + 424, + 812, + 523, + 232, + 584, + 885, + 556, + 504, + 985, + 322, + 969, + 371, + 391, + 98, + 941, + 26, + 178, + 774, + 463, + 997, + 240, + 265, + 783, + 393, + 970, + 984, + 767, + 198, + 352, + 641, + 75, + 295, + 130, + 103, + 967, + 755, + 140, + 35, + 36, + 632, + 140, + 31, + 343, + 311, + 875, + 957, + 214, + 594, + 102, + 708, + 704, + 42, + 385, + 66, + 207, + 462, + 7, + 629, + 996, + 45, + 239, + 67, + 320, + 572, + 870, + 745, + 491, + 347, + 526, + 400, + 699, + 754, + 976, + 956, + 954, + 794, + 539, + 303, + 659, + 358, + 240, + 499, + 659, + 623, + 633, + 84, + 969, + 47, + 38, + 147, + 473, + 237, + 108, + 223, + 587, + 983, + 835, + 709, + 650, + 654, + 290, + 457, + 508, + 179, + 41, + 861, + 141, + 415, + 338, + 134, + 768, + 896, + 332, + 774, + 619, + 168, + 326, + 995, + 974, + 888, + 405, + 863, + 48, + 321, + 634, + 321, + 270, + 859, + 323, + 320, + 737, + 558, + 628, + 600, + 523, + 806, + 90, + 149, + 997, + 588, + 708, + 940, + 616, + 975, + 302, + 113, + 670, + 369, + 987, + 171, + 900, + 669, + 758, + 668, + 439, + 111, + 749, + 85, + 423, + 868, + 299, + 854, + 861, + 512, + 673, + 594, + 180, + 719, + 880, + 377, + 927, + 123, + 93, + 351, + 135, + 116, + 681, + 353, + 159, + 981, + 788, + 232, + 670, + 43, + 414, + 383, + 448, + 113, + 401, + 103, + 514, + 158, + 22, + 537, + 72, + 392, + 763, + 35, + 420, + 434, + 526, + 732, + 53, + 193, + 681, + 185, + 586, + 476, + 362, + 274, + 409, + 658, + 165, + 767, + 233, + 389, + 776, + 179, + 432, + 84, + 27, + 691, + 946, + 470, + 906, + 144, + 423, + 226, + 616, + 247, + 503, + 52, + 921, + 450, + 596, + 634, + 189, + 640, + 812, + 892, + 964, + 903, + 866, + 914, + 506, + 858, + 104, + 335, + 545, + 557, + 515, + 707, + 797, + 965, + 331, + 927, + 376, + 757, + 886, + 154, + 827, + 675, + 744, + 712, + 717, + 977, + 168, + 49, + 739, + 407, + 50, + 224, + 180, + 317, + 364, + 594, + 696, + 318, + 336, + 734, + 293, + 497, + 469, + 988, + 653, + 241, + 114, + 982, + 927, + 708, + 609, + 851, + 256, + 225, + 51, + 194, + 14, + 282, + 557, + 892, + 905, + 457, + 759, + 466, + 622, + 351, + 245, + 5, + 449, + 80, + 548, + 213, + 711, + 458, + 106, + 713, + 94, + 587, + 650, + 853, + 41, + 578, + 515, + 946, + 3, + 758, + 437, + 935, + 967, + 284, + 783, + 525, + 306, + 820, + 175, + 216, + 350, + 866, + 535, + 369, + 843, + 642, + 848, + 648, + 44, + 796, + 390, + 983, + 292, + 352, + 992, + 122, + 715, + 123, + 2, + 83, + 193, + 711, + 329, + 242, + 453, + 600, + 770, + 969, + 90, + 259, + 71, + 253, + 311, + 865, + 679, + 120, + 409, + 329, + 113, + 636, + 784, + 548, + 5, + 162, + 555, + 82, + 479, + 168, + 984, + 802, + 681, + 497, + 996, + 382, + 339, + 55, + 947, + 117, + 162, + 275, + 493, + 410, + 234, + 69, + 54, + 817, + 985, + 639, + 479, + 362, + 394, + 939, + 494, + 462, + 642, + 301, + 983, + 350, + 923, + 244, + 565, + 587, + 811, + 130, + 2, + 249, + 56, + 722, + 814, + 940, + 346, + 233, + 575, + 764, + 917, + 981, + 350, + 589, + 969, + 834, + 506, + 623, + 448, + 515, + 715, + 397, + 395, + 174, + 196, + 337, + 713, + 560, + 686, + 836, + 837, + 544, + 582, + 586, + 883, + 968, + 810, + 164, + 568, + 109, + 333, + 703, + 3, + 719, + 500, + 530, + 11, + 628, + 164, + 246, + 446, + 472, + 883, + 142, + 978, + 127, + 127, + 837, + 156, + 66, + 142, + 382, + 852, + 608, + 956, + 287, + 553, + 284, + 347, + 23, + 358, + 964, + 746, + 894, + 32, + 258, + 788, + 404, + 75, + 587, + 955, + 593, + 640, + 828, + 977, + 428, + 189, + 421, + 587, + 31, + 41, + 718, + 490, + 535, + 330, + 589, + 256, + 762, + 629, + 586, + 916, + 745, + 353, + 114, + 385, + 517, + 1, + 279, + 673, + 638, + 516, + 273, + 953, + 822, + 323, + 973, + 946, + 715, + 414, + 811, + 28, + 804, + 139, + 254, + 110, + 811, + 684, + 405, + 174, + 97, + 444, + 222, + 329, + 911, + 670, + 642, + 424, + 24, + 129, + 772, + 432, + 372, + 124, + 43, + 396, + 319, + 386, + 934, + 153, + 697, + 562, + 375, + 838, + 510, + 574, + 8, + 870, + 677, + 326, + 410, + 19, + 510, + 433, + 893, + 768, + 853, + 775, + 994, + 851, + 611, + 885, + 212, + 885, + 411, + 597, + 36, + 951, + 482, + 530, + 572, + 492, + 583, + 749, + 579, + 293, + 315, + 783, + 31, + 789, + 298, + 772, + 697, + 113, + 87, + 624, + 402, + 939, + 214, + 569, + 92, + 324, + 338, + 680, + 627, + 979, + 679, + 685, + 954, + 247, + 130, + 718, + 993, + 444, + 692, + 459, + 652, + 877, + 733, + 689, + 848, + 63, + 325, + 90, + 638, + 494, + 278, + 454, + 490, + 807, + 30, + 904, + 133, + 648, + 201, + 990, + 662, + 647, + 987, + 94, + 103, + 886, + 386, + 578, + 667, + 536, + 754, + 56, + 382, + 963, + 506, + 825, + 173, + 850, + 635, + 796, + 229, + 893, + 785, + 30, + 143, + 375, + 306, + 367, + 888, + 996, + 908, + 332, + 239, + 925, + 603, + 189, + 160, + 738, + 16, + 403, + 222, + 546, + 469, + 416, + 29, + 914, + 212, + 666, + 260, + 352, + 592, + 389, + 793, + 834, + 43, + 260, + 583, + 984, + 590, + 508, + 347, + 115, + 199, + 309, + 508, + 400, + 669, + 110, + 201, + 5, + 575, + 500, + 292, + 759, + 898, + 671, + 612, + 438, + 33, + 561, + 560, + 205, + 719, + 987, + 263, + 313, + 144, + 189, + 429, + 366, + 229, + 618, + 384, + 865, + 278, + 926, + 329, + 869, + 930, + 789, + 925, + 797, + 554, + 442, + 595, + 979, + 276, + 72, + 960, + 883, + 436, + 816, + 70, + 631, + 956, + 704, + 691, + 775, + 67, + 196, + 246, + 324, + 260, + 252, + 68, + 442, + 493, + 266, + 873, + 264, + 920, + 686, + 970, + 661, + 807, + 496, + 214, + 225, + 80, + 505, + 837, + 965, + 360, + 494, + 233, + 584, + 268, + 618, + 633, + 894, + 994, + 110, + 917, + 711, + 214, + 832, + 291, + 354, + 961, + 142, + 343, + 548, + 803, + 661, + 706, + 969, + 201, + 938, + 706, + 438, + 922, + 228, + 775, + 736, + 91, + 948, + 581, + 564, + 370, + 995, + 653, + 252, + 872, + 70, + 990, + 323, + 392, + 48, + 737, + 957, + 660, + 405, + 290, + 886, + 550, + 86, + 426, + 678, + 908, + 325, + 65, + 845, + 933, + 918, + 393, + 504, + 272, + 785, + 526, + 480, + 331, + 400, + 514, + 940, + 121, + 9, + 965, + 907, + 165, + 521, + 825, + 40, + 251, + 227, + 739, + 370, + 606, + 572, + 70, + 118, + 684, + 236, + 809, + 947, + 221, + 588, + 369, + 826, + 554, + 206, + 353, + 168, + 995, + 549, + 733, + 42, + 297, + 346, + 495, + 684, + 266, + 672, + 400, + 150, + 178, + 45, + 40, + 723, + 527, + 349, + 985, + 279, + 965, + 668, + 29, + 684, + 447, + 152, + 241, + 801, + 335, + 777, + 601, + 968, + 997, + 614, + 762, + 586, + 540, + 429, + 174, + 626, + 770, + 855, + 522, + 250, + 846, + 878, + 412, + 566, + 995, + 715, + 880, + 819, + 67, + 152, + 154, + 331, + 191, + 879, + 869, + 201, + 642, + 229, + 298, + 251, + 182, + 871, + 757, + 905, + 462, + 7, + 9, + 896, + 234, + 51, + 579, + 603, + 265, + 850, + 203, + 62, + 577, + 812, + 511, + 816, + 498, + 805, + 35, + 358, + 144, + 77, + 731, + 198, + 647, + 679, + 697, + 766, + 553, + 980, + 49, + 337, + 803, + 387, + 593, + 459, + 286, + 352, + 798, + 154, + 888, + 494, + 914, + 961, + 547, + 154, + 802, + 889, + 726, + 638, + 740, + 710, + 263, + 126, + 509, + 220, + 626, + 650, + 40, + 821, + 979, + 240, + 371, + 936, + 7, + 926, + 252, + 142, + 200, + 1, + 801, + 252, + 208, + 605, + 516, + 777, + 997, + 370, + 869, + 523, + 651, + 799, + 321, + 938, + 575, + 397, + 289, + 704, + 359, + 99, + 245, + 635, + 79, + 849, + 375, + 753, + 806, + 315, + 21, + 871, + 991, + 828, + 942, + 478, + 651, + 532, + 357, + 482, + 76, + 536, + 603, + 8, + 941, + 541, + 639, + 924, + 709, + 648, + 169, + 84, + 810, + 836, + 724, + 997, + 346, + 945, + 961, + 296, + 708, + 790, + 640, + 0, + 829, + 692, + 178, + 258, + 727, + 958, + 490, + 169, + 612, + 232, + 33, + 526, + 776, + 947, + 161, + 697, + 20, + 930, + 57, + 630, + 359, + 716, + 247, + 214, + 839, + 662, + 141, + 401, + 157, + 436, + 98, + 173, + 390, + 620, + 608, + 14, + 518, + 880, + 749, + 218, + 704, + 902, + 131, + 663, + 288, + 797, + 171, + 316, + 89, + 806, + 367, + 513, + 666, + 917, + 660, + 891, + 835, + 610, + 822, + 88, + 765, + 760, + 69, + 579, + 16, + 202, + 470, + 973, + 542, + 21, + 853, + 905, + 108, + 62, + 285, + 313, + 337, + 488, + 546, + 482, + 575, + 385, + 997, + 73, + 919, + 939, + 503, + 888, + 345, + 666, + 425, + 722, + 864, + 831, + 432, + 542, + 196, + 536, + 582, + 275, + 489, + 793, + 835, + 457, + 645, + 275, + 499, + 7, + 759, + 959, + 400, + 983, + 387, + 768, + 928, + 858, + 938, + 938, + 258, + 457, + 166, + 547, + 954, + 505, + 483, + 868, + 556, + 994, + 752, + 163, + 301, + 340, + 445, + 641, + 436, + 439, + 935, + 91, + 736, + 277, + 895, + 935, + 139, + 582, + 208, + 309, + 468, + 784, + 847, + 991, + 571, + 561, + 573, + 143, + 181, + 99, + 232, + 691, + 567, + 634, + 352, + 775, + 39, + 173, + 877, + 688, + 845, + 102, + 565, + 760, + 585, + 920, + 979, + 563, + 839, + 324, + 987, + 541, + 557, + 904, + 658, + 830, + 141, + 77, + 955, + 19, + 357, + 939, + 324, + 793, + 604, + 731, + 535, + 848, + 527, + 392, + 804, + 771, + 202, + 955, + 996, + 904, + 290, + 762, + 368, + 552, + 30, + 277, + 784, + 204, + 446, + 829, + 367, + 857, + 180, + 880, + 148, + 946, + 447, + 309, + 315, + 858, + 231, + 664, + 490, + 946, + 242, + 443, + 448, + 309, + 869, + 650, + 431, + 141, + 990, + 745, + 850, + 593, + 62, + 580, + 690, + 158, + 28, + 98, + 371, + 567, + 309, + 647, + 651, + 602, + 647, + 949, + 938, + 848, + 612, + 239, + 812, + 521, + 37, + 121, + 756, + 674, + 948, + 735, + 779, + 668, + 515, + 320, + 142, + 154, + 266, + 582, + 941, + 887, + 171, + 277, + 392, + 489, + 603, + 654, + 492, + 670, + 313, + 768, + 51, + 545, + 424, + 497, + 834, + 457, + 577, + 798, + 243, + 695, + 722, + 429, + 691, + 209, + 363, + 179, + 302, + 152, + 647, + 743, + 158, + 234, + 127, + 993, + 971, + 477, + 26, + 345, + 84, + 737, + 585, + 496, + 220, + 465, + 126, + 125, + 991, + 870, + 645, + 502, + 531, + 63, + 347, + 616, + 580, + 96, + 315, + 286, + 264, + 230, + 432, + 274, + 537, + 733, + 708, + 931, + 224, + 871, + 886, + 843, + 727, + 249, + 306, + 691, + 887, + 763, + 899, + 717, + 480, + 411, + 124, + 990, + 895, + 767, + 252, + 398, + 713, + 893, + 935, + 773, + 998, + 625, + 849, + 380, + 761, + 627, + 125, + 541, + 108, + 177, + 508, + 824, + 640, + 320, + 809, + 788, + 513, + 115, + 65, + 270, + 584, + 422, + 17, + 840, + 587, + 778, + 703, + 433, + 399, + 92, + 570, + 325, + 22, + 452, + 950, + 105, + 459, + 671, + 7, + 357, + 713, + 106, + 871, + 94, + 404, + 948, + 530, + 631, + 679, + 806, + 774, + 371, + 124, + 529, + 513, + 26, + 859, + 172, + 331, + 566, + 434, + 1, + 970, + 56, + 18, + 411, + 123, + 316, + 194, + 574, + 190, + 302, + 548, + 643, + 635, + 871, + 630, + 207, + 193, + 984, + 963, + 623, + 742, + 257, + 336, + 153, + 792, + 967, + 235, + 506, + 401, + 408, + 45, + 648, + 153, + 364, + 320, + 619, + 949, + 354, + 243, + 437, + 646, + 675, + 74, + 658, + 781, + 24, + 282, + 902, + 530, + 403, + 499, + 962, + 787, + 980, + 815, + 163, + 921, + 355, + 375, + 103, + 223, + 556, + 860, + 636, + 420, + 212, + 690, + 559, + 39, + 222, + 201, + 70, + 282, + 83, + 53, + 83, + 520, + 716, + 286, + 149, + 456, + 277, + 130, + 500, + 379, + 495, + 485, + 729, + 922, + 762, + 59, + 880, + 432, + 6, + 500, + 19, + 982, + 612, + 22, + 812, + 278, + 222, + 897, + 854, + 360, + 719, + 923, + 264, + 120, + 760, + 427, + 520, + 304, + 800, + 411, + 720, + 729, + 399, + 207, + 336, + 917, + 368, + 763, + 560, + 568, + 609, + 361, + 359, + 253, + 672, + 742, + 141, + 397, + 292, + 262, + 881, + 258, + 564, + 566, + 72, + 633, + 920, + 904, + 419, + 990, + 10, + 812, + 547, + 545, + 232, + 129, + 284, + 975, + 178, + 483, + 75, + 780, + 562, + 910, + 277, + 107, + 836, + 912, + 638, + 896, + 204, + 861, + 507, + 604, + 103, + 868, + 644, + 496, + 215, + 215, + 553, + 645, + 398, + 752, + 352, + 984, + 6, + 846, + 49, + 811, + 354, + 263, + 286, + 518, + 269, + 639, + 74, + 637, + 917, + 15, + 244, + 539, + 595, + 545, + 856, + 68, + 354, + 968, + 10, + 256, + 106, + 124, + 864, + 595, + 936, + 194, + 956, + 201, + 612, + 603, + 546, + 703, + 582, + 139, + 436, + 716, + 605, + 65, + 832, + 103, + 742, + 511, + 26, + 122, + 309, + 599, + 251, + 324, + 507, + 125, + 294, + 877, + 45, + 956, + 27, + 330, + 36, + 80, + 298, + 272, + 438, + 243, + 437, + 741, + 121, + 507, + 674, + 194, + 263, + 440, + 772, + 93, + 3, + 139, + 173, + 594, + 174, + 770, + 954, + 393, + 549, + 33, + 435, + 836, + 75, + 842, + 469, + 887, + 919, + 901, + 326, + 898, + 346, + 314, + 389, + 818, + 663, + 371, + 843, + 363, + 959, + 215, + 802, + 218, + 776, + 153, + 648, + 150, + 257, + 31, + 711, + 335, + 516, + 582, + 317, + 999, + 393, + 435, + 371, + 926, + 507, + 933, + 925, + 825, + 554, + 870, + 845, + 194, + 588, + 423, + 819, + 698, + 312, + 107, + 541, + 443, + 833, + 20, + 79, + 147, + 331, + 986, + 784, + 130, + 261, + 714, + 537, + 500, + 363, + 259, + 122, + 506, + 550, + 204, + 466, + 763, + 650, + 360, + 826, + 385, + 189, + 836, + 807, + 862, + 943, + 431, + 547, + 300, + 682, + 336, + 71, + 467, + 871, + 6, + 207, + 214, + 482, + 128, + 42, + 151, + 788, + 597, + 644, + 217, + 507, + 653, + 330, + 660, + 696, + 287, + 513, + 506, + 124, + 348, + 195, + 344, + 480, + 112, + 839, + 497, + 751, + 689, + 579, + 820, + 490, + 903, + 809, + 790, + 409, + 684, + 708, + 538, + 177, + 77, + 702, + 997, + 846, + 958, + 767, + 174, + 206, + 236, + 340, + 66, + 495, + 364, + 833, + 710, + 598, + 889, + 36, + 413, + 485, + 27, + 824, + 138, + 864, + 146, + 890, + 855, + 133, + 57, + 788, + 755, + 597, + 256, + 76, + 75, + 795, + 970, + 384, + 463, + 528, + 142, + 232, + 973, + 961, + 696, + 231, + 251, + 918, + 383, + 264, + 229, + 103, + 610, + 505, + 311, + 725, + 203, + 414, + 53, + 258, + 973, + 293, + 254, + 782, + 26, + 490, + 190, + 927, + 341, + 479, + 858, + 804, + 463, + 457, + 47, + 718, + 205, + 521, + 107, + 171, + 414, + 845, + 941, + 865, + 778, + 315, + 513, + 236, + 669, + 681, + 187, + 964, + 875, + 548, + 869, + 157, + 782, + 876, + 820, + 436, + 595, + 304, + 452, + 667, + 827, + 803, + 227, + 466, + 253, + 874, + 43, + 987, + 416, + 64, + 529, + 943, + 471, + 753, + 259, + 81, + 693, + 231, + 159, + 143, + 399, + 492, + 510, + 257, + 825, + 557, + 263, + 536, + 200, + 71, + 744, + 132, + 231, + 842, + 159, + 49, + 302, + 806, + 870, + 999, + 580, + 941, + 437, + 261, + 861, + 423, + 929, + 994, + 534, + 396, + 315, + 783, + 765, + 930, + 644, + 756, + 462, + 195, + 564, + 22, + 384, + 521, + 730, + 505, + 63, + 457, + 709, + 976, + 314, + 282, + 864, + 118, + 724, + 440, + 316, + 776, + 848, + 506, + 48, + 233, + 789, + 380, + 580, + 889, + 81, + 697, + 763, + 59, + 234, + 408, + 647, + 306, + 431, + 170, + 942, + 7, + 854, + 406, + 217, + 257, + 654, + 945, + 846, + 874, + 436, + 621, + 787, + 538, + 556, + 245, + 891, + 675, + 141, + 746, + 646, + 56, + 919, + 717, + 816, + 234, + 712, + 458, + 339, + 680, + 705, + 485, + 616, + 610, + 208, + 251, + 273, + 242, + 151, + 560, + 362, + 520, + 417, + 760, + 758, + 89, + 229, + 964, + 150, + 683, + 851, + 620, + 180, + 304, + 339, + 923, + 78, + 12, + 253, + 307, + 854, + 692, + 339, + 854, + 773, + 925, + 938, + 926, + 680, + 358, + 592, + 522, + 3, + 916, + 431, + 61, + 649, + 448, + 463, + 508, + 758, + 646, + 122, + 644, + 508, + 85, + 945, + 934, + 473, + 86, + 380, + 856, + 26, + 642, + 831, + 889, + 592, + 669, + 896, + 665, + 897, + 497, + 740, + 987, + 530, + 217, + 945, + 800, + 104, + 267, + 558, + 688, + 806, + 944, + 79, + 119, + 416, + 715, + 389, + 267, + 333, + 579, + 882, + 278, + 972, + 767, + 890, + 412, + 110, + 525, + 605, + 273, + 857, + 312, + 841, + 312, + 76, + 596, + 956, + 484, + 30, + 230, + 319, + 789, + 586, + 44, + 341, + 434, + 565, + 238, + 907, + 581, + 719, + 944, + 19, + 447, + 599, + 966, + 776, + 472, + 393, + 179, + 350, + 59, + 291, + 317, + 585, + 868, + 750, + 464, + 35, + 79, + 888, + 245, + 972, + 150, + 190, + 511, + 785, + 79, + 726, + 51, + 655, + 456, + 474, + 441, + 257, + 664, + 257, + 683, + 70, + 763, + 743, + 208, + 190, + 857, + 693, + 574, + 626, + 411, + 484, + 434, + 507, + 779, + 306, + 549, + 778, + 512, + 343, + 549, + 679, + 259, + 793, + 492, + 966, + 281, + 787, + 858, + 419, + 580, + 588, + 626, + 166, + 360, + 780, + 747, + 249, + 856, + 305, + 861, + 383, + 938, + 520, + 78, + 311, + 334, + 592, + 8, + 629, + 606, + 623, + 217, + 466, + 378, + 856, + 551, + 458, + 243, + 484, + 294, + 587, + 953, + 749, + 287, + 733, + 796, + 498, + 534, + 989, + 379, + 804, + 560, + 971, + 333, + 384, + 367, + 292, + 898, + 277, + 508, + 58, + 636, + 37, + 312, + 742, + 879, + 536, + 239, + 240, + 730, + 3, + 593, + 301, + 66, + 144, + 62, + 248, + 634, + 863, + 14, + 579, + 120, + 250, + 322, + 964, + 447, + 727, + 322, + 765, + 268, + 206, + 364, + 515, + 471, + 858, + 438, + 840, + 968, + 13, + 264, + 388, + 75, + 163, + 137, + 999, + 866, + 153, + 356, + 193, + 854, + 718, + 606, + 730, + 162, + 431, + 375, + 917, + 548, + 825, + 99, + 271, + 0, + 303, + 228, + 894, + 370, + 644, + 38, + 532, + 512, + 546, + 303, + 923, + 170, + 489, + 40, + 82, + 479, + 971, + 452, + 637, + 557, + 940, + 132, + 908, + 268, + 774, + 932, + 786, + 976, + 491, + 710, + 197, + 554, + 532, + 265, + 909, + 18, + 758, + 213, + 45, + 698, + 180, + 990, + 471, + 610, + 575, + 659, + 412, + 595, + 275, + 498, + 713, + 306, + 259, + 1, + 253, + 316, + 357, + 155, + 55, + 520, + 687, + 350, + 644, + 974, + 945, + 277, + 654, + 850, + 412, + 847, + 384, + 820, + 512, + 979, + 21, + 823, + 299, + 93, + 793, + 204, + 925, + 130, + 103, + 314, + 105, + 564, + 762, + 524, + 478, + 178, + 807, + 56, + 916, + 711, + 511, + 111, + 865, + 110, + 195, + 982, + 171, + 631, + 960, + 640, + 584, + 600, + 770, + 669, + 649, + 51, + 212, + 828, + 973, + 448, + 101, + 856, + 801, + 679, + 694, + 242, + 334, + 620, + 160, + 667, + 891, + 791, + 659, + 107, + 865, + 126, + 882, + 675, + 726, + 234, + 346, + 875, + 88, + 115, + 592, + 729, + 299, + 177, + 210, + 456, + 766, + 928, + 837, + 417, + 856, + 631, + 142, + 640, + 848, + 805, + 989, + 509, + 106, + 440, + 276, + 581, + 117, + 187, + 565, + 620, + 433, + 475, + 873, + 626, + 342, + 455, + 373, + 767, + 855, + 866, + 942, + 108, + 117, + 799, + 85, + 936, + 665, + 975, + 750, + 35, + 769, + 889, + 610, + 210, + 220, + 359, + 981, + 728, + 649, + 0, + 826, + 950, + 120, + 648, + 58, + 383, + 436, + 737, + 11, + 714, + 424, + 251, + 301, + 204, + 287, + 183, + 472, + 265, + 120, + 780, + 369, + 695, + 758, + 740, + 107, + 831, + 93, + 535, + 306, + 777, + 976, + 562, + 59, + 956, + 304, + 83, + 576, + 399, + 999, + 899, + 824, + 350, + 635, + 896, + 802, + 332, + 421, + 878, + 433, + 193, + 353, + 802, + 683, + 456, + 88, + 211, + 132, + 432, + 354, + 421, + 616, + 53, + 231, + 915, + 510, + 106, + 28, + 32, + 600, + 461, + 131, + 594, + 678, + 744, + 674, + 620, + 290, + 535, + 534, + 543, + 62, + 971, + 905, + 180, + 10, + 234, + 166, + 272, + 73, + 128, + 437, + 613, + 291, + 638, + 610, + 225, + 630, + 309, + 112, + 868, + 557, + 439, + 355, + 555, + 579, + 443, + 843, + 20, + 464, + 987, + 284, + 302, + 450, + 355, + 83, + 407, + 711, + 752, + 187, + 249, + 807, + 883, + 924, + 858, + 110, + 409, + 189, + 998, + 439, + 120, + 321, + 875, + 140, + 640, + 285, + 561, + 873, + 371, + 73, + 4, + 169, + 771, + 413, + 447, + 985, + 206, + 635, + 943, + 960, + 240, + 554, + 209, + 576, + 254, + 163, + 977, + 846, + 610, + 596, + 920, + 524, + 608, + 402, + 249, + 624, + 180, + 875, + 240, + 670, + 421, + 1, + 911, + 505, + 474, + 979, + 623, + 678, + 952, + 909, + 751, + 241, + 269, + 968, + 396, + 641, + 516, + 965, + 406, + 54, + 853, + 346, + 650, + 787, + 400, + 175, + 929, + 662, + 870, + 170, + 468, + 173, + 620, + 318, + 170, + 995, + 525, + 138, + 520, + 151, + 851, + 30, + 596, + 605, + 802, + 449, + 174, + 518, + 633, + 293, + 652, + 779, + 606, + 444, + 472, + 359, + 204, + 308, + 104, + 274, + 707, + 638, + 193, + 577, + 125, + 28, + 537, + 987, + 521, + 80, + 56, + 111, + 589, + 81, + 794, + 377, + 36, + 680, + 476, + 227, + 778, + 138, + 24, + 752, + 160, + 590, + 855, + 396, + 289, + 142, + 785, + 551, + 696, + 514, + 268, + 536, + 547, + 207, + 943, + 166, + 0, + 959, + 114, + 322, + 906, + 322, + 892, + 960, + 152, + 219, + 944, + 540, + 874, + 965, + 269, + 858, + 681, + 764, + 673, + 30, + 954, + 88, + 521, + 729, + 159, + 275, + 56, + 125, + 755, + 556, + 505, + 72, + 919, + 180, + 714, + 476, + 557, + 286, + 639, + 983, + 152, + 572, + 584, + 774, + 510, + 716, + 601, + 148, + 732, + 601, + 940, + 969, + 20, + 190, + 364, + 622, + 685, + 61, + 344, + 196, + 7, + 990, + 899, + 252, + 754, + 435, + 284, + 201, + 722, + 552, + 343, + 657, + 969, + 888, + 215, + 691, + 409, + 26, + 814, + 955, + 756, + 555, + 490, + 721, + 618, + 204, + 30, + 599, + 134, + 692, + 978, + 825, + 270, + 841, + 504, + 774, + 525, + 384, + 45, + 973, + 630, + 292, + 407, + 67, + 655, + 51, + 321, + 712, + 920, + 987, + 848, + 722, + 54, + 844, + 881, + 2, + 745, + 543, + 18, + 346, + 886, + 284, + 553, + 327, + 745, + 802, + 253, + 852, + 636, + 390, + 455, + 868, + 740, + 663, + 964, + 729, + 838, + 160, + 466, + 658, + 934, + 788, + 92, + 286, + 175, + 248, + 540, + 880, + 948, + 738, + 221, + 979, + 785, + 992, + 482, + 300, + 55, + 307, + 541, + 695, + 226, + 659, + 648, + 922, + 441, + 203, + 794, + 22, + 970, + 164, + 46, + 259, + 951, + 704, + 886, + 299, + 673, + 173, + 240, + 807, + 719, + 658, + 194, + 357, + 971, + 821, + 711, + 707, + 225, + 482, + 734, + 77, + 917, + 665, + 867, + 755, + 544, + 326, + 524, + 598, + 78, + 244, + 906, + 617, + 928, + 395, + 658, + 732, + 601, + 421, + 359, + 459, + 727, + 409, + 806, + 285, + 943, + 207, + 630, + 752, + 85, + 819, + 81, + 714, + 599, + 44, + 892, + 139, + 813, + 684, + 175, + 718, + 720, + 697, + 401, + 310, + 84, + 666, + 259, + 357, + 939, + 246, + 527, + 856, + 455, + 533, + 717, + 790, + 923, + 962, + 105, + 447, + 598, + 8, + 941, + 409, + 510, + 130, + 823, + 606, + 773, + 511, + 574, + 98, + 731, + 402, + 862, + 752, + 623, + 991, + 46, + 307, + 347, + 826, + 698, + 658, + 35, + 642, + 770, + 293, + 385, + 50, + 470, + 908, + 177, + 919, + 460, + 783, + 812, + 885, + 144, + 408, + 659, + 741, + 639, + 741, + 234, + 361, + 975, + 361, + 934, + 345, + 46, + 370, + 804, + 357, + 22, + 797, + 24, + 698, + 274, + 669, + 711, + 610, + 104, + 699, + 121, + 724, + 99, + 296, + 870, + 786, + 907, + 517, + 300, + 369, + 115, + 987, + 98, + 420, + 792, + 167, + 589, + 81, + 929, + 901, + 444, + 109, + 382, + 693, + 593, + 875, + 545, + 683, + 487, + 631, + 35, + 664, + 35, + 465, + 381, + 502, + 512, + 213, + 325, + 921, + 435, + 368, + 265, + 897, + 888, + 773, + 659, + 636, + 822, + 940, + 704, + 937, + 990, + 380, + 22, + 806, + 443, + 272, + 226, + 75, + 390, + 701, + 604, + 103, + 834, + 836, + 128, + 776, + 390, + 490, + 761, + 481, + 372, + 204, + 99, + 91, + 22, + 808, + 253, + 230, + 576, + 111, + 530, + 569, + 205, + 79, + 723, + 69, + 129, + 157, + 690, + 663, + 960, + 928, + 549, + 861, + 858, + 688, + 269, + 88, + 740, + 156, + 907, + 39, + 916, + 907, + 334, + 924, + 489, + 523, + 243, + 832, + 196, + 238, + 353, + 1, + 7, + 314, + 127, + 188, + 96, + 15, + 805, + 54, + 9, + 827, + 404, + 908, + 152, + 993, + 739, + 18, + 830, + 225, + 119, + 544, + 559, + 312, + 438, + 641, + 301, + 560, + 392, + 365, + 576, + 955, + 898, + 503, + 118, + 601, + 848, + 464, + 83, + 817, + 190, + 930, + 333, + 675, + 660, + 97, + 975, + 412, + 292, + 419, + 456, + 795, + 937, + 793, + 775, + 168, + 22, + 285, + 446, + 516, + 479, + 419, + 80, + 724, + 440, + 812, + 799, + 215, + 257, + 254, + 998, + 103, + 914, + 559, + 536, + 588, + 833, + 464, + 188, + 548, + 869, + 359, + 478, + 711, + 413, + 236, + 826, + 534, + 811, + 997, + 919, + 179, + 790, + 869, + 958, + 428, + 792, + 503, + 118, + 329, + 350, + 240, + 390, + 989, + 365, + 170, + 270, + 362, + 823, + 277, + 978, + 293, + 777, + 833, + 515, + 336, + 976, + 174, + 532, + 206, + 600, + 236, + 270, + 737, + 513, + 511, + 672, + 679, + 854, + 554, + 295, + 755, + 523, + 932, + 750, + 520, + 450, + 535, + 586, + 41, + 2, + 357, + 349, + 195, + 5, + 421, + 165, + 148, + 341, + 548, + 200, + 620, + 554, + 759, + 518, + 145, + 722, + 932, + 586, + 186, + 189, + 713, + 830, + 193, + 436, + 92, + 883, + 115, + 46, + 257, + 114, + 244, + 303, + 658, + 66, + 395, + 469, + 697, + 430, + 317, + 184, + 224, + 362, + 429, + 493, + 506, + 218, + 593, + 279, + 450, + 567, + 823, + 411, + 889, + 871, + 439, + 366, + 693, + 160, + 602, + 813, + 85, + 824, + 224, + 144, + 721, + 540, + 880, + 444, + 222, + 843, + 704, + 285, + 480, + 71, + 556, + 404, + 959, + 31, + 235, + 826, + 228, + 372, + 477, + 993, + 269, + 254, + 432, + 643, + 380, + 81, + 642, + 794, + 462, + 386, + 625, + 787, + 623, + 528, + 718, + 472, + 82, + 225, + 488, + 488, + 382, + 114, + 741, + 356, + 237, + 434, + 915, + 593, + 334, + 875, + 525, + 846, + 418, + 726, + 633, + 9, + 228, + 131, + 198, + 922, + 681, + 218, + 435, + 803, + 310, + 641, + 258, + 90, + 521, + 538, + 971, + 301, + 904, + 31, + 805, + 745, + 702, + 285, + 511, + 591, + 404, + 739, + 157, + 12, + 212, + 69, + 478, + 627, + 720, + 177, + 290, + 417, + 585, + 965, + 881, + 508, + 92, + 443, + 655, + 217, + 758, + 203, + 491, + 497, + 753, + 347, + 582, + 15, + 142, + 301, + 481, + 728, + 242, + 325, + 272, + 127, + 694, + 174, + 851, + 309, + 486, + 520, + 498, + 794, + 155, + 671, + 872, + 698, + 579, + 771, + 665, + 591, + 806, + 984, + 37, + 886, + 580, + 305, + 103, + 585, + 234, + 918, + 62, + 857, + 548, + 295, + 618, + 901, + 12, + 20, + 59, + 291, + 376, + 299, + 339, + 10, + 586, + 540, + 972, + 682, + 473, + 340, + 820, + 752, + 332, + 93, + 973, + 434, + 39, + 526, + 841, + 955, + 270, + 116, + 778, + 140, + 878, + 509, + 760, + 216, + 851, + 836, + 475, + 33, + 884, + 382, + 264, + 324, + 787, + 640, + 793, + 686, + 280, + 115, + 461, + 258, + 5, + 461, + 527, + 672, + 196, + 813, + 585, + 387, + 413, + 339, + 113, + 767, + 564, + 10, + 332, + 500, + 311, + 282, + 143, + 108, + 29, + 966, + 13, + 837, + 241, + 431, + 51, + 564, + 414, + 835, + 855, + 71, + 885, + 990, + 86, + 340, + 225, + 179, + 12, + 795, + 628, + 615, + 167, + 756, + 274, + 154, + 484, + 607, + 155, + 522, + 699, + 407, + 582, + 710, + 535, + 153, + 417, + 349, + 37, + 743, + 966, + 840, + 230, + 83, + 759, + 610, + 31, + 962, + 561, + 19, + 702, + 56, + 838, + 235, + 47, + 393, + 700, + 873, + 548, + 419, + 508, + 320, + 91, + 70, + 693, + 587, + 889, + 716, + 7, + 213, + 628, + 603, + 411, + 351, + 79, + 220, + 823, + 919, + 430, + 423, + 336, + 265, + 161, + 357, + 184, + 821, + 598, + 529, + 663, + 197, + 655, + 620, + 749, + 488, + 130, + 45, + 861, + 912, + 383, + 273, + 357, + 285, + 244, + 860, + 867, + 156, + 540, + 428, + 250, + 383, + 327, + 125, + 170, + 226, + 163, + 295, + 901, + 703, + 992, + 625, + 805, + 143, + 416, + 488, + 83, + 838, + 901, + 832, + 722, + 33, + 565, + 957, + 386, + 255, + 529, + 22, + 385, + 641, + 3, + 975, + 43, + 360, + 374, + 26, + 50, + 513, + 623, + 498, + 962, + 47, + 824, + 955, + 947, + 877, + 718, + 305, + 433, + 838, + 16, + 971, + 56, + 315, + 40, + 251, + 32, + 776, + 910, + 502, + 872, + 404, + 24, + 266, + 655, + 444, + 38, + 433, + 166, + 251, + 737, + 585, + 802, + 879, + 316, + 909, + 85, + 530, + 162, + 819, + 420, + 995, + 655, + 546, + 83, + 666, + 491, + 224, + 436, + 981, + 473, + 206, + 574, + 977, + 573, + 905, + 370, + 928, + 524, + 974, + 177, + 667, + 662, + 121, + 514, + 916, + 830, + 801, + 455, + 43, + 986, + 364, + 479, + 667, + 157, + 546, + 927, + 120, + 882, + 184, + 769, + 480, + 892, + 324, + 822, + 947, + 608, + 704, + 503, + 888, + 28, + 741, + 735, + 189, + 673, + 549, + 13, + 594, + 331, + 965, + 430, + 323, + 625, + 845, + 487, + 704, + 232, + 774, + 239, + 323, + 458, + 415, + 843, + 822, + 500, + 699, + 940, + 198, + 205, + 274, + 723, + 728, + 817, + 307, + 500, + 942, + 294, + 475, + 840, + 245, + 863, + 692, + 884, + 15, + 43, + 589, + 639, + 584, + 66, + 194, + 473, + 487, + 382, + 984, + 855, + 19, + 764, + 751, + 420, + 783, + 774, + 692, + 537, + 467, + 185, + 506, + 348, + 617, + 961, + 109, + 118, + 833, + 725, + 706, + 47, + 641, + 69, + 382, + 892, + 613, + 168, + 546, + 72, + 287, + 658, + 280, + 961, + 11, + 786, + 468, + 65, + 25, + 145, + 746, + 846, + 911, + 574, + 392, + 779, + 746, + 711, + 935, + 796, + 482, + 506, + 772, + 873, + 712, + 546, + 93, + 546, + 28, + 757, + 858, + 313, + 663, + 914, + 858, + 508, + 945, + 912, + 223, + 945, + 200, + 313, + 367, + 309, + 487, + 637, + 824, + 869, + 534, + 699, + 79, + 510, + 860, + 34, + 420, + 255, + 493, + 790, + 310, + 444, + 113, + 719, + 695, + 358, + 148, + 947, + 483, + 821, + 59, + 835, + 434, + 903, + 41, + 634, + 592, + 594, + 150, + 410, + 598, + 14, + 961, + 97, + 942, + 79, + 466, + 17, + 112, + 830, + 751, + 454, + 84, + 374, + 264, + 624, + 963, + 372, + 81, + 536, + 775, + 159, + 372, + 174, + 707, + 399, + 984, + 57, + 648, + 923, + 258, + 417, + 86, + 978, + 982, + 414, + 147, + 403, + 610, + 251, + 571, + 656, + 151, + 156, + 812, + 621, + 669, + 21, + 148, + 31, + 74, + 77, + 49, + 175, + 263, + 527, + 797, + 797, + 775, + 553, + 981, + 898, + 725, + 357, + 116, + 678, + 297, + 357, + 496, + 159, + 750, + 979, + 145, + 331, + 691, + 711, + 921, + 829, + 284, + 217, + 581, + 203, + 124, + 670, + 62, + 544, + 289, + 240, + 308, + 333, + 829, + 758, + 48, + 339, + 468, + 795, + 844, + 212, + 623, + 954, + 946, + 951, + 531, + 119, + 806, + 153, + 382, + 632, + 472, + 665, + 241, + 794, + 786, + 436, + 323, + 840, + 594, + 95, + 175, + 134, + 796, + 940, + 747, + 997, + 360, + 755, + 467, + 711, + 275, + 449, + 291, + 217, + 677, + 446, + 422, + 225, + 302, + 8, + 957, + 836, + 901, + 37, + 919, + 426, + 623, + 94, + 105, + 654, + 752, + 464, + 323, + 877, + 954, + 228, + 375, + 752, + 743, + 349, + 350, + 181, + 532, + 97, + 777, + 935, + 148, + 433, + 153, + 973, + 525, + 131, + 947, + 752, + 692, + 927, + 84, + 270, + 152, + 62, + 676, + 772, + 301, + 542, + 874, + 841, + 976, + 442, + 540, + 397, + 922, + 430, + 729, + 328, + 779, + 624, + 430, + 783, + 852, + 691, + 657, + 553, + 216, + 941, + 965, + 248, + 656, + 952, + 514, + 250, + 890, + 502, + 392, + 951, + 357, + 453, + 744, + 557, + 940, + 738, + 207, + 960, + 612, + 410, + 688, + 517, + 612, + 723, + 773, + 269, + 176, + 305, + 210, + 455, + 178, + 764, + 414, + 918, + 958, + 727, + 54, + 74, + 191, + 371, + 376, + 770, + 275, + 82, + 913, + 527, + 249, + 800, + 675, + 387, + 810, + 388, + 503, + 240, + 491, + 28, + 491, + 110, + 133, + 734, + 720, + 476, + 943, + 315, + 810, + 672, + 761, + 421, + 269, + 449, + 677, + 98, + 912, + 873, + 36, + 313, + 585, + 401, + 35, + 248, + 301, + 668, + 136, + 88, + 514, + 765, + 68, + 160, + 267, + 325, + 663, + 511, + 927, + 524, + 243, + 22, + 126, + 193, + 846, + 233, + 289, + 676, + 783, + 957, + 845, + 673, + 692, + 285, + 763, + 575, + 742, + 791, + 744, + 630, + 650, + 435, + 748, + 128, + 612, + 892, + 729, + 230, + 818, + 271, + 634, + 875, + 930, + 576, + 333, + 589, + 849, + 116, + 143, + 383, + 705, + 321, + 218, + 620, + 142, + 602, + 477, + 31, + 550, + 407, + 552, + 766, + 851, + 17, + 123, + 828, + 678, + 986, + 66, + 629, + 393, + 595, + 319, + 404, + 352, + 95, + 140, + 329, + 357, + 197, + 571, + 46, + 8, + 251, + 628, + 0, + 327, + 965, + 938, + 187, + 95, + 925, + 514, + 566, + 95, + 301, + 153, + 166, + 526, + 648, + 41, + 663, + 145, + 534, + 712, + 452, + 770, + 326, + 518, + 767, + 743, + 726, + 560, + 301, + 198, + 253, + 702, + 177, + 619, + 698, + 645, + 696, + 622, + 686, + 401, + 644, + 124, + 276, + 707, + 746, + 136, + 48, + 275, + 263, + 285, + 301, + 59, + 367, + 802, + 225, + 719, + 334, + 91, + 899, + 836, + 39, + 801, + 797, + 52, + 769, + 941, + 404, + 667, + 842, + 726, + 652, + 538, + 68, + 780, + 305, + 694, + 212, + 208, + 576, + 35, + 505, + 26, + 939, + 402, + 977, + 342, + 4, + 436, + 287, + 861, + 465, + 898, + 593, + 691, + 341, + 595, + 526, + 722, + 464, + 273, + 301, + 51, + 148, + 888, + 16, + 548, + 760, + 252, + 855, + 690, + 754, + 886, + 625, + 404, + 861, + 546, + 558, + 201, + 715, + 800, + 24, + 464, + 763, + 181, + 111, + 42, + 899, + 398, + 995, + 166, + 769, + 737, + 196, + 1, + 99, + 136, + 62, + 335, + 351, + 346, + 289, + 899, + 124, + 607, + 468, + 686, + 775, + 991, + 561, + 335, + 250, + 880, + 252, + 56, + 390, + 363, + 965, + 233, + 98, + 954, + 669, + 596, + 836, + 912, + 645, + 516, + 891, + 340, + 529, + 722, + 391, + 580, + 212, + 501, + 961, + 154, + 117, + 877, + 956, + 245, + 543, + 749, + 229, + 959, + 415, + 3, + 886, + 430, + 294, + 501, + 957, + 218, + 686, + 825, + 508, + 746, + 186, + 624, + 450, + 123, + 310, + 161, + 775, + 581, + 541, + 630, + 788, + 652, + 849, + 101, + 81, + 872, + 316, + 621, + 8, + 17, + 934, + 555, + 326, + 252, + 104, + 720, + 706, + 130, + 364, + 56, + 558, + 83, + 928, + 538, + 227, + 366, + 463, + 527, + 769, + 19, + 815, + 801, + 899, + 72, + 970, + 25, + 993, + 340, + 724, + 765, + 167, + 347, + 803, + 148, + 363, + 967, + 325, + 927, + 588, + 791, + 579, + 647, + 245, + 767, + 522, + 989, + 49, + 619, + 794, + 385, + 865, + 665, + 136, + 426, + 849, + 354, + 982, + 870, + 328, + 181, + 922, + 304, + 822, + 665, + 956, + 324, + 168, + 412, + 785, + 919, + 486, + 340, + 677, + 751, + 646, + 857, + 629, + 108, + 650, + 366, + 931, + 195, + 684, + 498, + 266, + 669, + 73, + 103, + 512, + 456, + 187, + 190, + 356, + 146, + 361, + 597, + 277, + 261, + 993, + 479, + 850, + 883, + 950, + 622, + 192, + 351, + 293, + 375, + 86, + 141, + 824, + 714, + 492, + 48, + 589, + 564, + 266, + 359, + 425, + 75, + 797, + 538, + 550, + 885, + 404, + 863, + 468, + 301, + 321, + 475, + 876, + 916, + 666, + 927, + 31, + 256, + 839, + 177, + 61, + 875, + 23, + 348, + 257, + 939, + 931, + 533, + 473, + 865, + 108, + 130, + 772, + 296, + 768, + 721, + 908, + 108, + 727, + 659, + 811, + 821, + 971, + 652, + 546, + 727, + 678, + 767, + 229, + 606, + 503, + 298, + 186, + 539, + 4, + 203, + 752, + 630, + 179, + 182, + 476, + 366, + 651, + 924, + 38, + 925, + 37, + 177, + 658, + 489, + 816, + 322, + 963, + 928, + 818, + 169, + 602, + 403, + 506, + 127, + 844, + 749, + 674, + 845, + 529, + 865, + 635, + 791, + 776, + 334, + 136, + 342, + 593, + 512, + 660, + 640, + 787, + 139, + 544, + 181, + 43, + 46, + 413, + 337, + 854, + 986, + 815, + 121, + 877, + 294, + 218, + 4, + 136, + 225, + 766, + 992, + 910, + 530, + 646, + 213, + 695, + 271, + 967, + 986, + 628, + 777, + 180, + 866, + 599, + 664, + 46, + 994, + 396, + 56, + 256, + 739, + 481, + 608, + 360, + 134, + 970, + 282, + 898, + 417, + 948, + 956, + 230, + 884, + 748, + 74, + 938, + 224, + 920, + 974, + 475, + 405, + 442, + 630, + 596, + 118, + 398, + 439, + 969, + 188, + 169, + 251, + 630, + 835, + 480, + 557, + 904, + 461, + 371, + 885, + 197, + 305, + 678, + 12, + 663, + 960, + 311, + 877, + 747, + 20, + 271, + 622, + 48, + 621, + 135, + 59, + 179, + 377, + 684, + 861, + 760, + 38, + 780, + 91, + 18, + 23, + 432, + 37, + 443, + 450, + 508, + 193, + 960, + 986, + 761, + 605, + 788, + 86, + 436, + 23, + 581, + 605, + 128, + 84, + 979, + 732, + 230, + 787, + 836, + 261, + 677, + 117, + 292, + 477, + 388, + 20, + 962, + 707, + 979, + 933, + 662, + 112, + 234, + 771, + 167, + 31, + 673, + 42, + 705, + 675, + 151, + 452, + 875, + 655, + 399, + 59, + 702, + 502, + 444, + 892, + 290, + 856, + 53, + 260, + 19, + 221, + 987, + 330, + 80, + 665, + 551, + 377, + 540, + 188, + 920, + 680, + 133, + 77, + 466, + 439, + 258, + 570, + 659, + 56, + 10, + 615, + 504, + 336, + 655, + 720, + 156, + 289, + 354, + 637, + 184, + 853, + 944, + 177, + 973, + 177, + 537, + 934, + 78, + 267, + 209, + 898, + 115, + 986, + 920, + 926, + 393, + 217, + 204, + 312, + 989, + 655, + 214, + 47, + 231, + 278, + 866, + 734, + 707, + 605, + 208, + 232, + 506, + 116, + 383, + 662, + 151, + 92, + 785, + 431, + 614, + 585, + 682, + 781, + 343, + 590, + 458, + 232, + 360, + 187, + 18, + 769, + 704, + 620, + 67, + 109, + 88, + 353, + 401, + 228, + 508, + 406, + 255, + 989, + 151, + 702, + 277, + 376, + 381, + 409, + 932, + 31, + 761, + 783, + 233, + 154, + 871, + 55, + 648, + 5, + 12, + 465, + 96, + 904, + 169, + 325, + 428, + 572, + 47, + 78, + 258, + 525, + 276, + 502, + 972, + 488, + 763, + 798, + 973, + 186, + 490, + 362, + 205, + 154, + 245, + 784, + 493, + 76, + 975, + 459, + 598, + 227, + 161, + 752, + 243, + 858, + 931, + 996, + 543, + 488, + 560, + 240, + 49, + 318, + 374, + 914, + 52, + 693, + 762, + 329, + 691, + 193, + 122, + 925, + 577, + 748, + 236, + 8, + 591, + 640, + 61, + 77, + 295, + 117, + 323, + 732, + 493, + 811, + 67, + 694, + 158, + 589, + 247, + 115, + 184, + 682, + 927, + 918, + 353, + 217, + 904, + 834, + 107, + 728, + 683, + 908, + 596, + 721, + 44, + 412, + 780, + 882, + 682, + 497, + 832, + 559, + 126, + 303, + 100, + 214, + 829, + 344, + 654, + 679, + 336, + 148, + 213, + 982, + 859, + 558, + 855, + 999, + 698, + 38, + 490, + 340, + 846, + 852, + 26, + 942, + 575, + 383, + 1, + 198, + 836, + 570, + 893, + 950, + 7, + 527, + 628, + 753, + 660, + 180, + 354, + 819, + 775, + 271, + 187, + 374, + 532, + 374, + 900 +}; +const int idx[10004] = { + 13, + 111, + 124, + 218, + 316, + 502, + 34, + 119, + 167, + 180, + 186, + 346, + 511, + 543, + 755, + 788, + 833, + 929, + 46, + 109, + 154, + 220, + 248, + 448, + 509, + 517, + 530, + 557, + 639, + 643, + 720, + 137, + 189, + 424, + 480, + 570, + 642, + 849, + 896, + 968, + 117, + 136, + 208, + 248, + 347, + 410, + 433, + 515, + 747, + 144, + 148, + 375, + 405, + 444, + 532, + 788, + 808, + 987, + 110, + 112, + 403, + 415, + 596, + 612, + 669, + 794, + 851, + 80, + 285, + 288, + 433, + 500, + 628, + 982, + 999, + 57, + 237, + 252, + 304, + 469, + 600, + 609, + 621, + 741, + 798, + 251, + 322, + 369, + 374, + 376, + 507, + 623, + 666, + 669, + 677, + 707, + 823, + 919, + 63, + 187, + 266, + 360, + 396, + 439, + 459, + 526, + 623, + 804, + 857, + 881, + 948, + 160, + 165, + 226, + 446, + 538, + 585, + 624, + 866, + 975, + 979, + 18, + 54, + 151, + 180, + 230, + 298, + 480, + 678, + 688, + 696, + 742, + 757, + 889, + 979, + 100, + 245, + 513, + 925, + 162, + 413, + 427, + 588, + 645, + 807, + 853, + 194, + 313, + 339, + 466, + 539, + 581, + 732, + 791, + 832, + 927, + 954, + 962, + 966, + 42, + 45, + 138, + 141, + 239, + 338, + 584, + 696, + 912, + 929, + 269, + 352, + 443, + 463, + 896, + 962, + 60, + 92, + 273, + 568, + 591, + 851, + 38, + 77, + 281, + 362, + 544, + 614, + 651, + 836, + 871, + 873, + 45, + 61, + 140, + 153, + 234, + 439, + 472, + 509, + 588, + 675, + 760, + 777, + 178, + 198, + 248, + 517, + 566, + 679, + 700, + 289, + 455, + 602, + 695, + 711, + 853, + 923, + 179, + 199, + 214, + 280, + 343, + 405, + 435, + 504, + 898, + 910, + 939, + 130, + 219, + 296, + 445, + 508, + 634, + 763, + 918, + 922, + 978, + 87, + 285, + 614, + 667, + 679, + 739, + 834, + 192, + 347, + 549, + 557, + 724, + 764, + 928, + 929, + 976, + 17, + 283, + 413, + 429, + 612, + 683, + 707, + 725, + 743, + 833, + 856, + 165, + 267, + 304, + 361, + 397, + 410, + 570, + 683, + 766, + 788, + 849, + 882, + 885, + 30, + 58, + 221, + 254, + 453, + 457, + 470, + 674, + 687, + 745, + 809, + 819, + 55, + 121, + 231, + 538, + 604, + 718, + 768, + 960, + 71, + 77, + 104, + 186, + 205, + 234, + 456, + 467, + 579, + 682, + 733, + 767, + 947, + 66, + 86, + 157, + 290, + 422, + 441, + 473, + 560, + 607, + 640, + 682, + 888, + 37, + 296, + 439, + 629, + 642, + 733, + 824, + 917, + 969, + 4, + 25, + 580, + 622, + 636, + 666, + 672, + 732, + 802, + 921, + 943, + 130, + 194, + 245, + 273, + 323, + 344, + 603, + 740, + 795, + 974, + 189, + 422, + 445, + 446, + 831, + 905, + 912, + 36, + 60, + 218, + 428, + 455, + 627, + 743, + 796, + 801, + 903, + 136, + 152, + 166, + 352, + 364, + 369, + 382, + 466, + 521, + 577, + 665, + 746, + 910, + 294, + 345, + 445, + 645, + 686, + 718, + 757, + 762, + 796, + 817, + 832, + 836, + 997, + 127, + 258, + 259, + 449, + 541, + 643, + 665, + 756, + 817, + 854, + 870, + 89, + 134, + 188, + 362, + 408, + 531, + 566, + 816, + 127, + 170, + 302, + 336, + 426, + 434, + 601, + 708, + 774, + 780, + 900, + 935, + 377, + 469, + 618, + 650, + 790, + 809, + 78, + 253, + 340, + 382, + 586, + 673, + 684, + 282, + 354, + 363, + 398, + 636, + 655, + 729, + 885, + 911, + 10, + 175, + 195, + 229, + 273, + 339, + 380, + 531, + 660, + 681, + 794, + 800, + 236, + 416, + 646, + 679, + 685, + 885, + 7, + 116, + 299, + 481, + 702, + 747, + 922, + 64, + 153, + 374, + 391, + 532, + 558, + 602, + 655, + 662, + 804, + 847, + 867, + 998, + 45, + 66, + 97, + 106, + 236, + 240, + 247, + 453, + 641, + 646, + 711, + 712, + 715, + 855, + 906, + 923, + 37, + 65, + 122, + 331, + 578, + 589, + 610, + 139, + 293, + 354, + 395, + 430, + 486, + 589, + 614, + 661, + 699, + 846, + 910, + 18, + 53, + 78, + 234, + 296, + 690, + 828, + 923, + 87, + 115, + 156, + 161, + 173, + 201, + 400, + 474, + 501, + 526, + 782, + 861, + 63, + 271, + 427, + 552, + 590, + 657, + 920, + 41, + 194, + 281, + 571, + 640, + 681, + 696, + 301, + 306, + 514, + 553, + 560, + 641, + 683, + 762, + 812, + 818, + 876, + 904, + 932, + 978, + 38, + 62, + 98, + 103, + 370, + 390, + 531, + 559, + 693, + 813, + 924, + 943, + 955, + 973, + 13, + 40, + 62, + 75, + 396, + 419, + 615, + 773, + 968, + 989, + 150, + 183, + 241, + 261, + 407, + 476, + 492, + 524, + 541, + 863, + 994, + 156, + 195, + 197, + 278, + 457, + 467, + 610, + 621, + 956, + 49, + 343, + 454, + 477, + 572, + 600, + 700, + 759, + 804, + 923, + 92, + 194, + 455, + 842, + 968, + 160, + 211, + 461, + 463, + 467, + 622, + 854, + 972, + 333, + 469, + 563, + 571, + 639, + 838, + 977, + 18, + 105, + 133, + 258, + 572, + 720, + 804, + 851, + 930, + 19, + 139, + 158, + 301, + 354, + 407, + 589, + 726, + 846, + 904, + 26, + 54, + 155, + 212, + 216, + 418, + 534, + 647, + 792, + 862, + 889, + 101, + 216, + 228, + 396, + 470, + 473, + 592, + 706, + 799, + 913, + 922, + 98, + 324, + 524, + 672, + 685, + 856, + 213, + 224, + 228, + 300, + 395, + 604, + 631, + 651, + 835, + 944, + 289, + 574, + 613, + 657, + 671, + 748, + 763, + 768, + 815, + 843, + 908, + 74, + 79, + 203, + 218, + 245, + 249, + 390, + 548, + 616, + 804, + 986, + 49, + 196, + 585, + 591, + 608, + 728, + 750, + 810, + 836, + 920, + 980, + 38, + 41, + 93, + 94, + 320, + 360, + 502, + 555, + 729, + 742, + 814, + 984, + 89, + 131, + 499, + 677, + 825, + 846, + 919, + 966, + 17, + 37, + 121, + 168, + 560, + 585, + 691, + 788, + 892, + 925, + 951, + 995, + 13, + 69, + 124, + 229, + 308, + 554, + 643, + 668, + 717, + 747, + 813, + 814, + 864, + 298, + 327, + 386, + 425, + 586, + 600, + 725, + 730, + 832, + 12, + 38, + 94, + 150, + 175, + 501, + 538, + 552, + 571, + 606, + 624, + 650, + 686, + 728, + 157, + 605, + 630, + 713, + 784, + 850, + 954, + 181, + 234, + 610, + 612, + 661, + 663, + 677, + 688, + 726, + 809, + 818, + 67, + 77, + 164, + 193, + 214, + 345, + 352, + 551, + 696, + 919, + 994, + 12, + 311, + 404, + 454, + 473, + 521, + 581, + 651, + 677, + 717, + 850, + 873, + 880, + 892, + 945, + 54, + 138, + 210, + 219, + 248, + 413, + 480, + 491, + 639, + 652, + 773, + 807, + 824, + 962, + 79, + 211, + 499, + 560, + 561, + 759, + 774, + 800, + 865, + 35, + 146, + 619, + 746, + 754, + 81, + 237, + 258, + 388, + 477, + 658, + 704, + 712, + 781, + 109, + 720, + 758, + 98, + 209, + 252, + 311, + 410, + 532, + 611, + 656, + 722, + 772, + 822, + 828, + 912, + 980, + 95, + 107, + 167, + 287, + 289, + 303, + 441, + 446, + 580, + 600, + 630, + 632, + 658, + 682, + 847, + 92, + 137, + 177, + 238, + 262, + 324, + 438, + 479, + 534, + 539, + 689, + 846, + 956, + 962, + 200, + 496, + 521, + 656, + 714, + 785, + 814, + 857, + 184, + 204, + 455, + 702, + 754, + 803, + 887, + 928, + 993, + 42, + 51, + 189, + 204, + 358, + 572, + 601, + 665, + 867, + 71, + 108, + 208, + 243, + 263, + 314, + 359, + 418, + 482, + 556, + 680, + 945, + 958, + 964, + 97, + 200, + 202, + 223, + 230, + 428, + 447, + 537, + 574, + 635, + 663, + 728, + 737, + 858, + 861, + 930, + 71, + 84, + 85, + 196, + 199, + 242, + 513, + 761, + 48, + 98, + 127, + 194, + 233, + 283, + 334, + 420, + 627, + 632, + 931, + 34, + 82, + 176, + 197, + 217, + 235, + 237, + 358, + 462, + 947, + 10, + 178, + 265, + 350, + 396, + 468, + 539, + 586, + 612, + 628, + 644, + 791, + 40, + 234, + 292, + 299, + 375, + 396, + 410, + 429, + 728, + 36, + 360, + 475, + 562, + 962, + 5, + 60, + 169, + 509, + 558, + 594, + 613, + 648, + 654, + 726, + 769, + 773, + 777, + 40, + 49, + 403, + 446, + 524, + 548, + 730, + 774, + 938, + 978, + 997, + 221, + 248, + 407, + 447, + 585, + 756, + 824, + 894, + 972, + 121, + 189, + 364, + 537, + 563, + 179, + 328, + 344, + 692, + 711, + 750, + 760, + 780, + 810, + 929, + 942, + 106, + 336, + 551, + 616, + 640, + 654, + 726, + 890, + 74, + 200, + 233, + 254, + 382, + 396, + 895, + 971, + 283, + 614, + 898, + 87, + 122, + 172, + 255, + 324, + 383, + 498, + 525, + 699, + 817, + 825, + 3, + 41, + 104, + 280, + 399, + 617, + 641, + 769, + 789, + 817, + 891, + 937, + 143, + 175, + 185, + 217, + 222, + 362, + 391, + 465, + 515, + 544, + 818, + 868, + 35, + 44, + 122, + 235, + 345, + 415, + 479, + 569, + 575, + 740, + 765, + 867, + 967, + 78, + 107, + 265, + 358, + 524, + 646, + 716, + 720, + 840, + 76, + 77, + 353, + 406, + 533, + 648, + 726, + 733, + 906, + 979, + 65, + 133, + 182, + 187, + 191, + 424, + 430, + 520, + 674, + 776, + 945, + 975, + 18, + 242, + 393, + 458, + 468, + 530, + 599, + 717, + 933, + 278, + 297, + 465, + 476, + 579, + 591, + 633, + 643, + 937, + 271, + 481, + 618, + 890, + 5, + 126, + 171, + 192, + 209, + 259, + 367, + 840, + 861, + 6, + 26, + 47, + 90, + 225, + 239, + 385, + 577, + 782, + 795, + 797, + 893, + 76, + 82, + 309, + 348, + 450, + 583, + 677, + 696, + 752, + 785, + 800, + 991, + 2, + 191, + 211, + 279, + 280, + 556, + 591, + 774, + 785, + 822, + 913, + 34, + 117, + 159, + 204, + 266, + 418, + 547, + 565, + 962, + 992, + 33, + 72, + 140, + 141, + 157, + 254, + 513, + 558, + 643, + 695, + 779, + 791, + 882, + 978, + 13, + 53, + 65, + 479, + 513, + 674, + 687, + 711, + 785, + 811, + 830, + 4, + 5, + 9, + 34, + 77, + 137, + 265, + 270, + 542, + 552, + 622, + 632, + 634, + 647, + 783, + 895, + 951, + 995, + 89, + 113, + 174, + 225, + 231, + 258, + 294, + 347, + 383, + 414, + 444, + 463, + 467, + 493, + 535, + 612, + 688, + 107, + 111, + 213, + 238, + 494, + 555, + 572, + 676, + 40, + 50, + 59, + 119, + 291, + 365, + 416, + 565, + 607, + 613, + 631, + 902, + 908, + 998, + 63, + 495, + 534, + 581, + 601, + 694, + 719, + 731, + 790, + 969, + 176, + 262, + 481, + 545, + 694, + 737, + 853, + 202, + 267, + 269, + 302, + 466, + 727, + 786, + 816, + 858, + 923, + 14, + 241, + 387, + 416, + 468, + 501, + 513, + 599, + 48, + 157, + 318, + 426, + 589, + 632, + 871, + 882, + 87, + 444, + 486, + 558, + 618, + 773, + 794, + 73, + 116, + 199, + 229, + 233, + 255, + 360, + 400, + 425, + 468, + 474, + 540, + 589, + 786, + 834, + 868, + 888, + 85, + 112, + 162, + 185, + 316, + 331, + 346, + 410, + 611, + 729, + 798, + 863, + 234, + 591, + 637, + 933, + 8, + 12, + 32, + 43, + 101, + 339, + 436, + 708, + 88, + 111, + 115, + 790, + 841, + 935, + 976, + 12, + 175, + 245, + 447, + 449, + 548, + 581, + 652, + 743, + 763, + 773, + 776, + 828, + 951, + 58, + 62, + 68, + 277, + 297, + 401, + 418, + 460, + 482, + 561, + 656, + 734, + 812, + 818, + 837, + 861, + 118, + 192, + 254, + 267, + 270, + 276, + 347, + 463, + 509, + 514, + 714, + 717, + 788, + 905, + 924, + 100, + 256, + 334, + 335, + 465, + 627, + 803, + 815, + 884, + 996, + 15, + 140, + 172, + 197, + 227, + 300, + 310, + 466, + 530, + 560, + 567, + 784, + 860, + 15, + 108, + 132, + 188, + 310, + 621, + 838, + 839, + 988, + 8, + 130, + 289, + 462, + 472, + 549, + 557, + 561, + 643, + 753, + 755, + 841, + 955, + 40, + 325, + 334, + 371, + 375, + 417, + 573, + 872, + 921, + 989, + 25, + 94, + 138, + 217, + 312, + 370, + 528, + 585, + 603, + 630, + 729, + 803, + 810, + 73, + 424, + 570, + 624, + 630, + 642, + 671, + 697, + 873, + 935, + 987, + 94, + 174, + 318, + 415, + 507, + 516, + 676, + 779, + 821, + 941, + 973, + 73, + 78, + 97, + 148, + 237, + 269, + 293, + 304, + 483, + 575, + 591, + 916, + 64, + 228, + 238, + 269, + 287, + 400, + 633, + 749, + 114, + 173, + 311, + 400, + 454, + 634, + 644, + 726, + 731, + 860, + 921, + 224, + 262, + 367, + 401, + 504, + 589, + 630, + 727, + 848, + 161, + 392, + 401, + 410, + 530, + 548, + 787, + 894, + 989, + 121, + 372, + 437, + 676, + 929, + 976, + 980, + 111, + 365, + 706, + 954, + 82, + 379, + 563, + 728, + 949, + 124, + 227, + 540, + 671, + 767, + 861, + 484, + 678, + 840, + 864, + 916, + 304, + 348, + 502, + 599, + 617, + 657, + 82, + 149, + 163, + 216, + 229, + 449, + 612, + 620, + 636, + 673, + 679, + 756, + 802, + 859, + 953, + 142, + 176, + 215, + 273, + 335, + 415, + 586, + 658, + 682, + 764, + 865, + 896, + 923, + 76, + 283, + 284, + 464, + 481, + 588, + 625, + 742, + 790, + 947, + 119, + 186, + 309, + 320, + 404, + 407, + 440, + 496, + 692, + 853, + 884, + 901, + 980, + 990, + 345, + 493, + 503, + 691, + 738, + 743, + 890, + 929, + 993, + 998, + 45, + 272, + 313, + 350, + 384, + 452, + 499, + 569, + 248, + 346, + 515, + 676, + 751, + 755, + 775, + 778, + 17, + 491, + 522, + 538, + 622, + 672, + 919, + 961, + 54, + 126, + 207, + 301, + 375, + 447, + 500, + 599, + 651, + 683, + 890, + 947, + 93, + 317, + 482, + 656, + 774, + 865, + 904, + 96, + 224, + 260, + 313, + 340, + 372, + 410, + 437, + 452, + 511, + 512, + 718, + 911, + 77, + 100, + 176, + 232, + 418, + 661, + 689, + 805, + 956, + 51, + 262, + 280, + 352, + 380, + 413, + 461, + 538, + 616, + 769, + 783, + 821, + 855, + 946, + 956, + 73, + 169, + 238, + 246, + 319, + 391, + 392, + 669, + 769, + 770, + 786, + 946, + 415, + 453, + 590, + 628, + 630, + 684, + 852, + 52, + 258, + 318, + 322, + 535, + 545, + 561, + 610, + 621, + 662, + 687, + 839, + 87, + 98, + 181, + 269, + 454, + 666, + 667, + 684, + 891, + 142, + 270, + 300, + 396, + 398, + 443, + 652, + 677, + 821, + 0, + 77, + 85, + 163, + 180, + 281, + 470, + 491, + 665, + 694, + 760, + 899, + 992, + 32, + 51, + 73, + 75, + 157, + 216, + 224, + 301, + 376, + 433, + 536, + 612, + 703, + 11, + 228, + 456, + 471, + 543, + 627, + 650, + 873, + 898, + 144, + 258, + 597, + 796, + 36, + 394, + 486, + 492, + 497, + 681, + 710, + 963, + 522, + 582, + 709, + 769, + 775, + 987, + 80, + 129, + 156, + 281, + 339, + 346, + 402, + 777, + 789, + 812, + 822, + 859, + 108, + 127, + 207, + 293, + 337, + 385, + 415, + 479, + 509, + 539, + 746, + 785, + 929, + 934, + 943, + 27, + 52, + 55, + 67, + 124, + 298, + 381, + 625, + 690, + 741, + 975, + 26, + 112, + 127, + 152, + 225, + 513, + 534, + 672, + 734, + 766, + 968, + 26, + 87, + 123, + 198, + 266, + 279, + 410, + 445, + 612, + 791, + 807, + 946, + 996, + 287, + 417, + 458, + 515, + 562, + 576, + 725, + 750, + 779, + 92, + 136, + 168, + 174, + 213, + 300, + 392, + 541, + 602, + 618, + 729, + 761, + 960, + 2, + 340, + 378, + 414, + 441, + 575, + 632, + 731, + 791, + 870, + 875, + 2, + 176, + 241, + 307, + 436, + 707, + 912, + 929, + 962, + 232, + 300, + 389, + 397, + 400, + 483, + 547, + 628, + 766, + 781, + 783, + 833, + 981, + 193, + 200, + 224, + 681, + 739, + 750, + 25, + 404, + 409, + 420, + 511, + 621, + 623, + 857, + 909, + 144, + 179, + 221, + 223, + 400, + 413, + 483, + 507, + 516, + 609, + 806, + 869, + 995, + 1, + 194, + 270, + 433, + 450, + 549, + 591, + 794, + 872, + 106, + 125, + 136, + 207, + 239, + 432, + 529, + 588, + 634, + 869, + 936, + 61, + 70, + 156, + 171, + 172, + 272, + 582, + 594, + 943, + 310, + 445, + 589, + 752, + 769, + 775, + 778, + 901, + 76, + 130, + 151, + 165, + 236, + 473, + 503, + 558, + 794, + 804, + 945, + 953, + 971, + 2, + 4, + 44, + 150, + 167, + 190, + 209, + 658, + 747, + 934, + 75, + 156, + 315, + 528, + 697, + 760, + 156, + 165, + 232, + 644, + 680, + 686, + 771, + 846, + 100, + 197, + 377, + 497, + 658, + 674, + 685, + 716, + 759, + 890, + 1, + 18, + 104, + 318, + 462, + 643, + 793, + 930, + 999, + 104, + 112, + 141, + 231, + 255, + 414, + 419, + 651, + 754, + 900, + 914, + 965, + 969, + 43, + 275, + 386, + 410, + 419, + 480, + 607, + 649, + 688, + 763, + 850, + 149, + 184, + 326, + 434, + 485, + 599, + 618, + 786, + 915, + 54, + 113, + 195, + 358, + 383, + 489, + 564, + 788, + 840, + 887, + 219, + 232, + 351, + 373, + 691, + 777, + 42, + 58, + 124, + 272, + 297, + 571, + 583, + 590, + 618, + 734, + 867, + 60, + 90, + 174, + 217, + 339, + 423, + 531, + 640, + 707, + 767, + 798, + 896, + 981, + 208, + 304, + 402, + 657, + 959, + 197, + 242, + 348, + 373, + 409, + 449, + 489, + 529, + 545, + 577, + 812, + 844, + 853, + 956, + 114, + 128, + 137, + 254, + 386, + 401, + 424, + 425, + 470, + 509, + 735, + 835, + 872, + 899, + 29, + 49, + 189, + 201, + 495, + 517, + 598, + 669, + 712, + 734, + 794, + 903, + 32, + 34, + 191, + 411, + 499, + 542, + 581, + 593, + 748, + 823, + 878, + 99, + 169, + 439, + 522, + 729, + 879, + 31, + 97, + 195, + 273, + 314, + 496, + 498, + 863, + 55, + 75, + 100, + 153, + 198, + 404, + 459, + 664, + 800, + 877, + 919, + 999, + 97, + 252, + 330, + 477, + 572, + 663, + 687, + 707, + 726, + 778, + 822, + 905, + 909, + 62, + 285, + 353, + 384, + 564, + 578, + 626, + 669, + 34, + 82, + 303, + 585, + 614, + 682, + 816, + 896, + 917, + 971, + 198, + 200, + 255, + 508, + 524, + 640, + 789, + 840, + 855, + 125, + 177, + 277, + 332, + 491, + 513, + 514, + 526, + 619, + 626, + 651, + 730, + 735, + 795, + 999, + 91, + 141, + 279, + 457, + 617, + 717, + 24, + 26, + 255, + 270, + 314, + 333, + 425, + 493, + 518, + 626, + 900, + 943, + 161, + 381, + 386, + 412, + 688, + 795, + 970, + 999, + 51, + 77, + 123, + 193, + 225, + 227, + 340, + 757, + 826, + 901, + 927, + 938, + 972, + 180, + 304, + 358, + 508, + 531, + 997, + 46, + 99, + 182, + 354, + 653, + 661, + 749, + 765, + 766, + 911, + 50, + 320, + 365, + 604, + 720, + 812, + 60, + 91, + 196, + 249, + 492, + 525, + 671, + 681, + 724, + 801, + 813, + 936, + 34, + 221, + 318, + 353, + 490, + 557, + 584, + 640, + 801, + 152, + 253, + 264, + 314, + 567, + 587, + 888, + 898, + 238, + 263, + 269, + 386, + 446, + 578, + 613, + 632, + 853, + 893, + 193, + 311, + 391, + 604, + 638, + 780, + 786, + 890, + 909, + 931, + 25, + 152, + 201, + 221, + 222, + 345, + 358, + 442, + 578, + 622, + 640, + 711, + 748, + 979, + 474, + 479, + 541, + 963, + 193, + 202, + 264, + 365, + 512, + 648, + 992, + 60, + 135, + 327, + 330, + 355, + 400, + 434, + 556, + 561, + 691, + 760, + 810, + 848, + 3, + 25, + 372, + 421, + 555, + 618, + 678, + 723, + 790, + 850, + 876, + 947, + 47, + 179, + 253, + 284, + 588, + 608, + 615, + 688, + 732, + 746, + 753, + 923, + 997, + 70, + 197, + 212, + 281, + 360, + 588, + 897, + 994, + 140, + 146, + 209, + 212, + 321, + 427, + 581, + 736, + 744, + 755, + 848, + 913, + 15, + 183, + 733, + 792, + 804, + 848, + 854, + 6, + 13, + 42, + 187, + 211, + 465, + 567, + 741, + 755, + 858, + 955, + 36, + 56, + 131, + 213, + 352, + 377, + 393, + 405, + 520, + 543, + 729, + 826, + 865, + 42, + 66, + 80, + 116, + 322, + 463, + 768, + 866, + 981, + 105, + 252, + 513, + 613, + 652, + 788, + 199, + 245, + 609, + 673, + 703, + 770, + 863, + 868, + 34, + 432, + 522, + 571, + 641, + 649, + 804, + 842, + 934, + 24, + 25, + 88, + 322, + 369, + 423, + 598, + 632, + 675, + 711, + 969, + 161, + 274, + 320, + 377, + 434, + 705, + 749, + 753, + 850, + 881, + 134, + 158, + 235, + 245, + 346, + 383, + 422, + 425, + 594, + 598, + 735, + 750, + 876, + 988, + 144, + 183, + 191, + 344, + 460, + 522, + 527, + 529, + 537, + 619, + 711, + 812, + 852, + 901, + 979, + 100, + 143, + 653, + 755, + 759, + 816, + 23, + 161, + 188, + 223, + 266, + 326, + 726, + 750, + 802, + 898, + 998, + 27, + 178, + 242, + 269, + 604, + 870, + 990, + 137, + 350, + 424, + 447, + 553, + 559, + 580, + 624, + 677, + 690, + 751, + 894, + 922, + 995, + 41, + 147, + 178, + 272, + 357, + 361, + 415, + 782, + 891, + 124, + 149, + 194, + 473, + 542, + 687, + 758, + 776, + 852, + 935, + 33, + 63, + 420, + 25, + 54, + 134, + 169, + 216, + 217, + 315, + 367, + 378, + 452, + 535, + 549, + 598, + 624, + 683, + 731, + 882, + 893, + 203, + 277, + 470, + 676, + 686, + 688, + 711, + 805, + 880, + 943, + 74, + 139, + 158, + 190, + 216, + 295, + 380, + 431, + 436, + 445, + 514, + 683, + 713, + 807, + 809, + 820, + 845, + 897, + 991, + 46, + 227, + 290, + 462, + 672, + 901, + 10, + 76, + 108, + 110, + 111, + 160, + 168, + 257, + 453, + 533, + 739, + 746, + 764, + 846, + 946, + 999, + 36, + 136, + 311, + 392, + 724, + 908, + 30, + 450, + 495, + 648, + 672, + 726, + 878, + 881, + 984, + 80, + 208, + 329, + 502, + 511, + 515, + 553, + 560, + 694, + 824, + 938, + 70, + 110, + 144, + 183, + 309, + 332, + 337, + 342, + 398, + 591, + 635, + 811, + 842, + 192, + 339, + 449, + 504, + 570, + 594, + 644, + 666, + 692, + 779, + 847, + 32, + 138, + 155, + 279, + 296, + 409, + 427, + 524, + 605, + 837, + 919, + 993, + 38, + 72, + 139, + 173, + 279, + 281, + 285, + 306, + 375, + 390, + 426, + 734, + 909, + 958, + 17, + 61, + 451, + 523, + 573, + 622, + 935, + 16, + 74, + 97, + 139, + 149, + 193, + 268, + 353, + 433, + 475, + 481, + 508, + 752, + 881, + 919, + 9, + 93, + 292, + 406, + 543, + 573, + 610, + 612, + 642, + 855, + 326, + 327, + 428, + 430, + 677, + 781, + 796, + 906, + 918, + 93, + 191, + 206, + 467, + 654, + 704, + 707, + 709, + 813, + 908, + 87, + 212, + 252, + 315, + 586, + 755, + 777, + 801, + 809, + 838, + 982, + 479, + 491, + 499, + 681, + 887, + 996, + 37, + 378, + 408, + 456, + 460, + 493, + 568, + 601, + 616, + 684, + 820, + 866, + 915, + 153, + 186, + 593, + 781, + 878, + 48, + 262, + 320, + 361, + 599, + 696, + 698, + 871, + 17, + 104, + 128, + 142, + 216, + 347, + 468, + 583, + 656, + 737, + 752, + 759, + 767, + 848, + 860, + 885, + 105, + 151, + 173, + 198, + 412, + 467, + 701, + 709, + 967, + 65, + 165, + 315, + 431, + 523, + 562, + 633, + 694, + 780, + 782, + 795, + 943, + 991, + 28, + 125, + 223, + 283, + 384, + 460, + 586, + 589, + 600, + 743, + 754, + 846, + 907, + 983, + 12, + 26, + 94, + 190, + 256, + 282, + 380, + 385, + 450, + 570, + 582, + 669, + 672, + 751, + 804, + 892, + 26, + 167, + 259, + 337, + 409, + 425, + 121, + 133, + 305, + 332, + 408, + 432, + 531, + 582, + 598, + 680, + 716, + 778, + 790, + 907, + 942, + 224, + 240, + 394, + 449, + 489, + 503, + 575, + 594, + 618, + 653, + 711, + 736, + 744, + 821, + 961, + 536, + 603, + 781, + 866, + 901, + 911, + 916, + 970, + 42, + 110, + 186, + 276, + 396, + 565, + 573, + 677, + 738, + 918, + 956, + 965, + 978, + 160, + 191, + 338, + 502, + 572, + 721, + 731, + 45, + 209, + 224, + 226, + 623, + 718, + 721, + 725, + 840, + 953, + 977, + 24, + 77, + 117, + 290, + 941, + 945, + 84, + 200, + 254, + 374, + 591, + 635, + 652, + 765, + 826, + 949, + 104, + 257, + 715, + 162, + 456, + 479, + 892, + 34, + 110, + 142, + 645, + 664, + 840, + 950, + 139, + 313, + 453, + 615, + 792, + 798, + 47, + 133, + 170, + 350, + 605, + 757, + 922, + 940, + 45, + 204, + 274, + 369, + 411, + 809, + 888, + 903, + 969, + 151, + 318, + 354, + 375, + 629, + 758, + 881, + 917, + 972, + 185, + 238, + 397, + 405, + 422, + 450, + 500, + 532, + 625, + 677, + 708, + 755, + 780, + 824, + 845, + 931, + 963, + 975, + 18, + 245, + 447, + 519, + 700, + 21, + 49, + 130, + 133, + 185, + 191, + 388, + 654, + 760, + 812, + 817, + 858, + 906, + 982, + 997, + 209, + 508, + 611, + 691, + 725, + 79, + 232, + 320, + 367, + 481, + 559, + 649, + 656, + 830, + 960, + 40, + 288, + 542, + 644, + 646, + 749, + 827, + 894, + 929, + 956, + 73, + 87, + 215, + 261, + 377, + 517, + 822, + 906, + 997, + 56, + 267, + 276, + 375, + 415, + 528, + 660, + 670, + 892, + 959, + 998, + 999, + 146, + 329, + 331, + 332, + 400, + 510, + 623, + 653, + 822, + 18, + 375, + 394, + 477, + 482, + 596, + 665, + 724, + 847, + 872, + 935, + 40, + 136, + 320, + 332, + 408, + 767, + 975, + 24, + 49, + 156, + 246, + 378, + 578, + 627, + 916, + 965, + 998, + 123, + 285, + 305, + 438, + 476, + 538, + 554, + 773, + 804, + 968, + 4, + 181, + 240, + 411, + 715, + 797, + 802, + 896, + 904, + 985, + 68, + 118, + 185, + 326, + 645, + 690, + 736, + 744, + 961, + 3, + 404, + 437, + 572, + 812, + 902, + 917, + 921, + 180, + 291, + 327, + 328, + 389, + 407, + 408, + 530, + 650, + 727, + 996, + 230, + 313, + 506, + 579, + 593, + 610, + 814, + 832, + 840, + 876, + 951, + 251, + 327, + 353, + 581, + 588, + 711, + 837, + 2, + 60, + 165, + 275, + 291, + 320, + 735, + 796, + 63, + 78, + 165, + 318, + 433, + 439, + 456, + 466, + 529, + 765, + 144, + 221, + 259, + 686, + 793, + 7, + 242, + 265, + 433, + 474, + 664, + 840, + 954, + 95, + 161, + 165, + 209, + 396, + 820, + 947, + 36, + 198, + 262, + 342, + 449, + 482, + 621, + 742, + 756, + 822, + 972, + 145, + 339, + 342, + 479, + 523, + 811, + 916, + 199, + 318, + 323, + 363, + 491, + 496, + 562, + 570, + 612, + 719, + 739, + 836, + 168, + 216, + 252, + 319, + 760, + 841, + 845, + 955, + 144, + 354, + 442, + 443, + 662, + 752, + 936, + 77, + 185, + 315, + 473, + 512, + 596, + 612, + 634, + 900, + 936, + 974, + 166, + 189, + 428, + 498, + 755, + 922, + 23, + 100, + 204, + 534, + 719, + 738, + 854, + 44, + 120, + 273, + 407, + 988, + 50, + 386, + 460, + 472, + 513, + 552, + 811, + 912, + 981, + 995, + 24, + 113, + 129, + 302, + 442, + 512, + 685, + 726, + 966, + 161, + 413, + 491, + 498, + 499, + 543, + 688, + 690, + 809, + 843, + 888, + 564, + 624, + 756, + 815, + 832, + 866, + 932, + 1, + 13, + 26, + 39, + 87, + 176, + 279, + 284, + 317, + 344, + 397, + 442, + 507, + 591, + 663, + 691, + 800, + 803, + 865, + 925, + 987, + 995, + 996, + 315, + 541, + 557, + 664, + 679, + 754, + 808, + 851, + 918, + 0, + 117, + 131, + 262, + 442, + 627, + 702, + 799, + 945, + 281, + 313, + 314, + 384, + 427, + 558, + 669, + 706, + 720, + 721, + 766, + 786, + 840, + 842, + 923, + 58, + 119, + 317, + 411, + 415, + 416, + 680, + 997, + 84, + 442, + 487, + 689, + 811, + 833, + 940, + 22, + 431, + 515, + 598, + 605, + 738, + 876, + 919, + 960, + 980, + 3, + 38, + 130, + 716, + 854, + 885, + 51, + 93, + 141, + 153, + 195, + 258, + 329, + 390, + 497, + 508, + 680, + 863, + 169, + 211, + 335, + 423, + 442, + 479, + 864, + 169, + 239, + 534, + 605, + 708, + 743, + 772, + 814, + 832, + 54, + 110, + 167, + 171, + 290, + 370, + 433, + 652, + 661, + 677, + 710, + 726, + 829, + 902, + 915, + 44, + 88, + 104, + 214, + 313, + 346, + 487, + 555, + 582, + 660, + 674, + 713, + 721, + 762, + 785, + 797, + 986, + 998, + 50, + 143, + 158, + 281, + 488, + 566, + 579, + 584, + 596, + 846, + 876, + 42, + 64, + 71, + 73, + 105, + 170, + 171, + 210, + 276, + 531, + 577, + 699, + 879, + 889, + 925, + 932, + 442, + 447, + 462, + 504, + 530, + 687, + 714, + 838, + 120, + 171, + 280, + 358, + 644, + 735, + 765, + 964, + 988, + 993, + 80, + 352, + 740, + 813, + 999, + 133, + 155, + 192, + 196, + 442, + 456, + 504, + 519, + 530, + 606, + 777, + 916, + 985, + 24, + 42, + 351, + 407, + 504, + 516, + 682, + 879, + 67, + 69, + 145, + 152, + 492, + 515, + 562, + 575, + 658, + 668, + 700, + 722, + 811, + 956, + 18, + 126, + 283, + 289, + 297, + 307, + 337, + 368, + 519, + 615, + 789, + 838, + 876, + 970, + 38, + 137, + 307, + 378, + 436, + 437, + 453, + 520, + 793, + 844, + 893, + 168, + 179, + 230, + 327, + 487, + 662, + 727, + 126, + 320, + 584, + 707, + 864, + 895, + 295, + 309, + 781, + 823, + 988, + 18, + 42, + 151, + 163, + 259, + 324, + 349, + 416, + 521, + 659, + 689, + 912, + 24, + 87, + 201, + 319, + 406, + 434, + 488, + 554, + 576, + 624, + 714, + 851, + 995, + 49, + 142, + 236, + 300, + 416, + 497, + 586, + 708, + 777, + 962, + 969, + 217, + 235, + 279, + 316, + 430, + 491, + 630, + 842, + 907, + 124, + 143, + 180, + 455, + 672, + 695, + 891, + 971, + 90, + 173, + 363, + 410, + 446, + 480, + 528, + 631, + 690, + 777, + 792, + 143, + 187, + 261, + 268, + 292, + 410, + 524, + 557, + 618, + 643, + 656, + 680, + 807, + 812, + 824, + 900, + 2, + 5, + 117, + 216, + 329, + 355, + 400, + 493, + 606, + 631, + 850, + 875, + 947, + 93, + 134, + 172, + 427, + 477, + 508, + 540, + 585, + 878, + 123, + 302, + 594, + 678, + 697, + 747, + 824, + 868, + 965, + 14, + 21, + 178, + 180, + 227, + 281, + 379, + 412, + 417, + 450, + 456, + 465, + 589, + 596, + 736, + 760, + 844, + 13, + 81, + 177, + 276, + 327, + 359, + 623, + 674, + 676, + 3, + 6, + 34, + 144, + 150, + 202, + 219, + 376, + 429, + 539, + 648, + 663, + 885, + 944, + 997, + 31, + 259, + 263, + 291, + 646, + 783, + 820, + 836, + 903, + 929, + 83, + 145, + 193, + 372, + 392, + 422, + 564, + 734, + 740, + 846, + 868, + 945, + 185, + 277, + 325, + 394, + 499, + 649, + 656, + 748, + 841, + 922, + 958, + 19, + 43, + 51, + 96, + 291, + 397, + 680, + 729, + 913, + 943, + 978, + 151, + 179, + 234, + 248, + 358, + 692, + 704, + 778, + 809, + 847, + 850, + 873, + 969, + 242, + 327, + 340, + 552, + 736, + 742, + 837, + 959, + 179, + 216, + 355, + 356, + 443, + 447, + 512, + 515, + 529, + 634, + 786, + 47, + 142, + 203, + 223, + 606, + 623, + 815, + 24, + 37, + 67, + 199, + 272, + 349, + 380, + 512, + 574, + 586, + 743, + 847, + 890, + 897, + 25, + 107, + 347, + 474, + 476, + 621, + 642, + 734, + 755, + 142, + 211, + 273, + 526, + 528, + 602, + 632, + 761, + 765, + 776, + 847, + 112, + 118, + 140, + 153, + 229, + 313, + 448, + 469, + 619, + 627, + 637, + 672, + 751, + 900, + 906, + 297, + 411, + 464, + 497, + 691, + 740, + 886, + 14, + 109, + 125, + 187, + 194, + 241, + 263, + 379, + 552, + 615, + 657, + 670, + 750, + 47, + 133, + 386, + 482, + 517, + 641, + 696, + 734, + 951, + 1, + 101, + 103, + 134, + 205, + 526, + 533, + 538, + 559, + 594, + 680, + 835, + 4, + 224, + 526, + 600, + 769, + 885, + 991, + 2, + 292, + 326, + 380, + 393, + 539, + 798, + 907, + 465, + 641, + 727, + 763, + 794, + 854, + 44, + 92, + 235, + 381, + 420, + 430, + 461, + 538, + 555, + 725, + 756, + 849, + 177, + 180, + 337, + 353, + 540, + 571, + 588, + 706, + 734, + 753, + 776, + 786, + 982, + 999, + 10, + 159, + 258, + 428, + 449, + 505, + 588, + 888, + 998, + 55, + 79, + 95, + 211, + 226, + 432, + 435, + 560, + 563, + 613, + 694, + 806, + 968, + 90, + 165, + 207, + 422, + 439, + 489, + 674, + 693, + 985, + 8, + 111, + 336, + 474, + 489, + 554, + 715, + 742, + 772, + 889, + 906, + 918, + 102, + 197, + 236, + 294, + 345, + 562, + 568, + 697, + 850, + 950, + 113, + 151, + 204, + 226, + 235, + 267, + 302, + 380, + 407, + 499, + 813, + 916, + 956, + 200, + 275, + 403, + 546, + 607, + 697, + 734, + 187, + 211, + 255, + 329, + 359, + 421, + 495, + 555, + 581, + 696, + 961, + 973, + 231, + 318, + 359, + 388, + 422, + 643, + 707, + 932, + 940, + 949, + 3, + 65, + 128, + 134, + 172, + 231, + 349, + 728, + 749, + 757, + 772, + 891, + 150, + 185, + 551, + 599, + 617, + 709, + 816, + 170, + 339, + 406, + 487, + 800, + 887, + 71, + 196, + 209, + 449, + 497, + 517, + 518, + 529, + 629, + 661, + 715, + 869, + 20, + 37, + 96, + 99, + 214, + 273, + 400, + 555, + 917, + 31, + 227, + 228, + 246, + 353, + 379, + 507, + 534, + 590, + 620, + 680, + 734, + 830, + 876, + 955, + 996, + 5, + 361, + 364, + 559, + 699, + 882, + 920, + 11, + 114, + 119, + 154, + 161, + 319, + 467, + 533, + 570, + 787, + 827, + 995, + 23, + 171, + 240, + 254, + 268, + 287, + 455, + 580, + 672, + 726, + 977, + 982, + 203, + 239, + 298, + 407, + 579, + 594, + 610, + 624, + 672, + 756, + 161, + 228, + 437, + 465, + 552, + 861, + 879, + 968, + 987, + 989, + 59, + 79, + 143, + 149, + 166, + 271, + 300, + 411, + 641, + 677, + 757, + 868, + 918, + 994, + 0, + 321, + 340, + 346, + 548, + 788, + 821, + 953, + 59, + 120, + 230, + 344, + 726, + 823, + 850, + 83, + 121, + 201, + 345, + 355, + 369, + 398, + 422, + 507, + 527, + 554, + 599, + 712, + 735, + 874, + 900, + 28, + 40, + 149, + 243, + 344, + 494, + 759, + 902, + 979, + 9, + 168, + 493, + 610, + 655, + 747, + 806, + 975, + 8, + 29, + 56, + 150, + 177, + 207, + 268, + 364, + 368, + 458, + 473, + 719, + 796, + 862, + 865, + 45, + 52, + 115, + 198, + 285, + 377, + 396, + 548, + 682, + 705, + 807, + 833, + 957, + 36, + 149, + 150, + 278, + 440, + 451, + 558, + 575, + 625, + 630, + 689, + 932, + 953, + 985, + 16, + 106, + 338, + 342, + 667, + 675, + 723, + 745, + 973, + 86, + 175, + 207, + 262, + 385, + 496, + 774, + 33, + 222, + 265, + 295, + 297, + 410, + 412, + 500, + 526, + 595, + 813, + 899, + 87, + 155, + 168, + 505, + 612, + 650, + 753, + 819, + 830, + 103, + 147, + 237, + 278, + 438, + 480, + 490, + 648, + 671, + 748, + 822, + 183, + 246, + 400, + 541, + 582, + 614, + 622, + 745, + 807, + 80, + 137, + 430, + 461, + 541, + 724, + 6, + 142, + 168, + 183, + 196, + 313, + 484, + 594, + 635, + 716, + 803, + 825, + 861, + 972, + 981, + 83, + 164, + 202, + 232, + 270, + 311, + 404, + 431, + 688, + 729, + 867, + 903, + 925, + 69, + 283, + 295, + 363, + 410, + 434, + 457, + 481, + 574, + 578, + 587, + 600, + 664, + 803, + 858, + 76, + 205, + 334, + 441, + 553, + 590, + 944, + 69, + 272, + 486, + 513, + 604, + 749, + 842, + 852, + 954, + 17, + 86, + 115, + 203, + 343, + 355, + 467, + 478, + 629, + 646, + 748, + 811, + 900, + 13, + 25, + 120, + 353, + 608, + 612, + 747, + 766, + 856, + 109, + 234, + 265, + 279, + 325, + 379, + 418, + 464, + 550, + 552, + 571, + 344, + 448, + 517, + 682, + 895, + 173, + 242, + 281, + 314, + 350, + 502, + 518, + 552, + 745, + 19, + 70, + 75, + 80, + 695, + 697, + 793, + 877, + 85, + 189, + 248, + 300, + 417, + 433, + 507, + 936, + 947, + 8, + 351, + 368, + 400, + 450, + 470, + 474, + 501, + 518, + 524, + 558, + 616, + 666, + 712, + 953, + 172, + 398, + 644, + 680, + 785, + 71, + 116, + 288, + 314, + 327, + 488, + 724, + 770, + 858, + 934, + 958, + 67, + 115, + 279, + 654, + 689, + 707, + 752, + 888, + 966, + 208, + 544, + 679, + 719, + 789, + 831, + 49, + 263, + 420, + 433, + 502, + 602, + 651, + 678, + 730, + 756, + 762, + 900, + 100, + 113, + 177, + 198, + 509, + 516, + 596, + 645, + 783, + 939, + 987, + 335, + 429, + 437, + 543, + 566, + 695, + 707, + 747, + 868, + 921, + 0, + 84, + 203, + 215, + 477, + 523, + 526, + 612, + 627, + 766, + 778, + 809, + 126, + 203, + 373, + 590, + 640, + 863, + 871, + 937, + 201, + 221, + 729, + 746, + 772, + 924, + 937, + 964, + 78, + 339, + 406, + 424, + 475, + 679, + 869, + 938, + 64, + 147, + 163, + 171, + 293, + 381, + 390, + 511, + 989, + 63, + 85, + 208, + 335, + 441, + 510, + 566, + 586, + 909, + 935, + 970, + 50, + 100, + 351, + 354, + 397, + 442, + 448, + 580, + 657, + 789, + 836, + 293, + 311, + 456, + 795, + 796, + 799, + 909, + 972, + 984, + 28, + 132, + 226, + 361, + 473, + 493, + 586, + 611, + 676, + 693, + 939, + 948, + 150, + 185, + 269, + 362, + 648, + 650, + 870, + 307, + 330, + 438, + 756, + 852, + 99, + 223, + 285, + 371, + 767, + 912, + 966, + 1, + 3, + 111, + 583, + 733, + 841, + 959, + 977, + 115, + 263, + 283, + 498, + 517, + 534, + 604, + 656, + 661, + 769, + 876, + 974, + 59, + 123, + 291, + 343, + 473, + 565, + 634, + 834, + 898, + 923, + 962, + 75, + 85, + 92, + 125, + 305, + 827, + 836, + 901, + 936, + 28, + 124, + 316, + 541, + 636, + 694, + 929, + 960, + 37, + 69, + 169, + 442, + 491, + 588, + 619, + 643, + 740, + 794, + 939, + 941, + 10, + 43, + 248, + 450, + 812, + 907, + 984, + 271, + 307, + 316, + 533, + 702, + 733, + 752, + 850, + 892, + 919, + 971, + 97, + 132, + 154, + 461, + 633, + 741, + 905, + 940, + 74, + 115, + 118, + 251, + 297, + 344, + 405, + 623, + 655, + 658, + 775, + 801, + 903, + 965, + 53, + 309, + 392, + 643, + 696, + 752, + 764, + 867, + 981, + 64, + 228, + 236, + 301, + 498, + 512, + 536, + 568, + 685, + 865, + 925, + 29, + 371, + 372, + 626, + 760, + 765, + 773, + 813, + 980, + 109, + 177, + 211, + 322, + 370, + 415, + 425, + 514, + 647, + 672, + 767, + 945, + 613, + 720, + 863, + 870, + 886, + 924, + 144, + 233, + 483, + 504, + 811, + 872, + 908, + 921, + 61, + 160, + 350, + 376, + 424, + 602, + 632, + 675, + 682, + 861, + 959, + 380, + 389, + 848, + 7, + 13, + 458, + 629, + 103, + 193, + 231, + 533, + 590, + 598, + 661, + 741, + 880, + 243, + 400, + 505, + 601, + 689, + 965, + 15, + 136, + 200, + 230, + 322, + 419, + 792, + 890, + 3, + 71, + 174, + 189, + 336, + 363, + 371, + 403, + 534, + 743, + 792, + 799, + 867, + 909, + 951, + 57, + 198, + 202, + 334, + 471, + 542, + 709, + 19, + 104, + 156, + 246, + 421, + 450, + 593, + 721, + 866, + 972, + 43, + 185, + 199, + 243, + 255, + 293, + 343, + 395, + 413, + 608, + 749, + 759, + 819, + 160, + 261, + 357, + 728, + 734, + 788, + 849, + 859, + 884, + 915, + 129, + 394, + 592, + 803, + 974, + 57, + 79, + 246, + 528, + 698, + 740, + 909, + 968, + 90, + 204, + 337, + 699, + 926, + 125, + 181, + 251, + 333, + 335, + 439, + 737, + 778, + 905, + 922, + 1, + 22, + 64, + 80, + 304, + 45, + 63, + 99, + 144, + 222, + 274, + 384, + 406, + 447, + 643, + 774, + 784, + 918, + 58, + 110, + 156, + 294, + 436, + 531, + 654, + 742, + 769, + 948, + 153, + 171, + 177, + 389, + 647, + 722, + 781, + 825, + 829, + 854, + 33, + 150, + 194, + 237, + 313, + 314, + 386, + 502, + 645, + 705, + 791, + 833, + 845, + 882, + 916, + 136, + 222, + 275, + 381, + 471, + 859, + 901, + 902, + 917, + 992, + 118, + 319, + 494, + 512, + 812, + 897, + 960, + 35, + 252, + 489, + 565, + 573, + 605, + 684, + 847, + 22, + 396, + 541, + 560, + 589, + 618, + 685, + 771, + 793, + 968, + 53, + 102, + 130, + 434, + 506, + 738, + 759, + 867, + 884, + 886, + 894, + 956, + 95, + 100, + 117, + 215, + 360, + 399, + 416, + 421, + 612, + 692, + 697, + 707, + 815, + 852, + 875, + 892, + 936, + 346, + 380, + 563, + 691, + 718, + 115, + 192, + 309, + 603, + 881, + 888, + 927, + 983, + 182, + 206, + 222, + 295, + 355, + 446, + 672, + 710, + 751, + 85, + 127, + 144, + 267, + 306, + 339, + 372, + 393, + 688, + 739, + 821, + 886, + 894, + 915, + 952, + 169, + 179, + 233, + 316, + 654, + 864, + 988, + 98, + 102, + 153, + 188, + 205, + 245, + 290, + 333, + 901, + 922, + 986, + 988, + 996, + 93, + 390, + 438, + 445, + 539, + 614, + 713, + 800, + 856, + 962, + 101, + 145, + 245, + 546, + 560, + 581, + 598, + 937, + 54, + 148, + 181, + 302, + 592, + 670, + 761, + 287, + 324, + 365, + 464, + 471, + 473, + 487, + 598, + 667, + 741, + 0, + 95, + 183, + 420, + 469, + 648, + 686, + 890, + 902, + 20, + 207, + 397, + 410, + 481, + 545, + 579, + 635, + 689, + 755, + 791, + 850, + 856, + 857, + 998, + 15, + 332, + 481, + 577, + 603, + 635, + 948, + 58, + 135, + 208, + 370, + 469, + 848, + 942, + 946, + 31, + 149, + 153, + 164, + 174, + 329, + 444, + 534, + 548, + 615, + 110, + 137, + 177, + 287, + 699, + 705, + 848, + 197, + 204, + 236, + 382, + 543, + 874, + 984, + 49, + 78, + 163, + 185, + 316, + 355, + 365, + 577, + 667, + 673, + 720, + 722, + 785, + 942, + 10, + 117, + 182, + 218, + 305, + 398, + 471, + 676, + 807, + 839, + 944, + 173, + 182, + 184, + 302, + 340, + 426, + 609, + 693, + 735, + 762, + 873, + 947, + 24, + 85, + 290, + 299, + 499, + 551, + 609, + 648, + 660, + 685, + 11, + 62, + 109, + 185, + 345, + 797, + 843, + 264, + 776, + 824, + 845, + 958, + 49, + 58, + 170, + 367, + 451, + 469, + 654, + 794, + 842, + 877, + 897, + 950, + 4, + 57, + 58, + 61, + 260, + 334, + 494, + 540, + 561, + 636, + 659, + 950, + 68, + 96, + 146, + 167, + 270, + 293, + 401, + 623, + 625, + 668, + 690, + 934, + 946, + 218, + 280, + 309, + 389, + 447, + 492, + 641, + 730, + 786, + 843, + 871, + 970, + 973, + 14, + 93, + 284, + 404, + 666, + 713, + 835, + 183, + 214, + 292, + 563, + 739, + 823, + 876, + 6, + 84, + 543, + 556, + 579, + 855, + 35, + 227, + 327, + 380, + 439, + 712, + 769, + 776, + 46, + 176, + 178, + 192, + 239, + 555, + 703, + 744, + 751, + 813, + 939, + 30, + 89, + 141, + 260, + 268, + 348, + 367, + 374, + 730, + 742, + 766, + 769, + 832, + 99, + 150, + 199, + 229, + 286, + 292, + 344, + 464, + 524, + 558, + 565, + 629, + 716, + 766, + 818, + 867, + 876, + 877, + 881, + 131, + 208, + 312, + 472, + 524, + 565, + 638, + 645, + 655, + 663, + 665, + 713, + 752, + 877, + 958, + 963, + 985, + 993, + 23, + 160, + 240, + 594, + 602, + 663, + 876, + 945, + 961, + 53, + 82, + 159, + 217, + 219, + 270, + 549, + 598, + 742, + 846, + 885, + 628, + 878, + 121, + 210, + 273, + 554, + 555, + 759, + 911, + 913, + 28, + 233, + 269, + 347, + 489, + 592, + 859, + 934, + 952, + 6, + 60, + 79, + 123, + 256, + 279, + 455, + 557, + 727, + 123, + 750, + 906, + 971, + 7, + 26, + 96, + 209, + 464, + 477, + 662, + 693, + 963, + 201, + 427, + 474, + 663, + 728, + 917, + 81, + 102, + 488, + 644, + 802, + 834, + 929, + 987, + 273, + 283, + 459, + 531, + 736, + 918, + 960, + 112, + 182, + 187, + 193, + 311, + 360, + 400, + 517, + 668, + 885, + 888, + 70, + 89, + 130, + 190, + 248, + 262, + 334, + 447, + 451, + 493, + 513, + 531, + 548, + 721, + 891, + 918, + 925, + 968, + 102, + 249, + 396, + 397, + 405, + 473, + 532, + 761, + 869, + 127, + 211, + 234, + 375, + 377, + 513, + 517, + 523, + 526, + 712, + 772, + 848, + 890, + 172, + 264, + 385, + 445, + 461, + 474, + 485, + 537, + 608, + 687, + 735, + 11, + 220, + 328, + 381, + 488, + 690, + 790, + 910, + 969, + 994, + 191, + 284, + 472, + 565, + 584, + 660, + 706, + 715, + 739, + 75, + 78, + 81, + 260, + 372, + 741, + 898, + 910, + 967, + 972, + 108, + 410, + 463, + 923, + 936, + 947, + 961, + 110, + 111, + 160, + 191, + 239, + 735, + 963, + 77, + 267, + 275, + 330, + 357, + 620, + 664, + 699, + 837, + 842, + 42, + 45, + 375, + 384, + 468, + 516, + 521, + 552, + 564, + 700, + 943, + 981, + 36, + 272, + 288, + 442, + 506, + 507, + 533, + 708, + 748, + 834, + 950, + 261, + 275, + 24, + 97, + 124, + 311, + 398, + 504, + 558, + 581, + 653, + 799, + 930, + 988, + 63, + 164, + 260, + 305, + 348, + 372, + 456, + 468, + 667, + 794, + 934, + 956, + 210, + 478, + 533, + 927, + 14, + 89, + 163, + 207, + 356, + 626, + 628, + 658, + 696, + 725, + 731, + 764, + 43, + 58, + 449, + 639, + 894, + 138, + 163, + 290, + 344, + 345, + 386, + 432, + 466, + 614, + 767, + 800, + 831, + 7, + 292, + 314, + 322, + 327, + 518, + 549, + 760, + 981, + 122, + 246, + 297, + 461, + 489, + 502, + 581, + 630, + 746, + 769, + 904, + 0, + 27, + 157, + 259, + 337, + 434, + 504, + 541, + 573, + 781, + 794, + 842, + 928, + 986, + 184, + 244, + 372, + 423, + 482, + 503, + 626, + 644, + 785, + 890, + 47, + 242, + 509, + 671, + 675, + 765, + 884, + 982, + 81, + 84, + 147, + 314, + 456, + 483, + 603, + 670, + 691, + 896, + 928, + 18, + 21, + 75, + 114, + 284, + 513, + 574, + 621, + 630, + 753, + 765, + 896, + 331, + 344, + 358, + 409, + 499, + 678, + 679, + 953, + 90, + 123, + 139, + 150, + 161, + 228, + 296, + 534, + 658, + 707, + 715, + 743, + 757, + 945, + 962, + 993, + 92, + 133, + 147, + 201, + 297, + 363, + 517, + 7, + 80, + 147, + 183, + 328, + 348, + 351, + 594, + 691, + 723, + 735, + 18, + 145, + 216, + 231, + 305, + 364, + 380, + 447, + 589, + 629, + 648, + 727, + 729, + 109, + 132, + 161, + 195, + 408, + 443, + 527, + 748, + 770, + 821, + 928, + 962, + 119, + 298, + 395, + 556, + 728, + 898, + 945, + 10, + 129, + 451, + 490, + 606, + 620, + 662, + 698, + 782, + 813, + 816, + 952, + 69, + 175, + 203, + 306, + 399, + 405, + 707, + 710, + 12, + 107, + 284, + 285, + 448, + 584, + 689, + 818, + 990, + 11, + 105, + 114, + 271, + 305, + 561, + 572, + 626, + 669, + 710, + 72, + 224, + 233, + 276, + 445, + 476, + 613, + 615, + 879, + 244, + 268, + 502, + 512, + 520, + 600, + 671, + 694, + 887, + 987, + 81, + 87, + 378, + 384, + 397, + 423, + 427, + 626, + 630, + 693, + 699, + 726, + 887, + 929, + 967, + 31, + 71, + 326, + 345, + 350, + 422, + 515, + 531, + 630, + 761, + 26, + 33, + 461, + 601, + 627, + 716, + 743, + 975, + 81, + 399, + 489, + 609, + 733, + 741, + 787, + 806, + 874, + 903, + 932, + 988, + 81, + 367, + 406, + 492, + 550, + 561, + 599, + 635, + 756, + 838, + 944, + 958, + 39, + 75, + 102, + 259, + 345, + 376, + 499, + 519, + 548, + 763, + 788, + 857, + 899, + 947, + 948, + 970, + 975, + 26, + 244, + 367, + 408, + 410, + 415, + 669, + 849, + 904, + 912, + 913, + 932, + 84, + 89, + 233, + 297, + 433, + 599, + 818, + 869, + 957, + 194, + 373, + 632, + 651, + 718, + 728, + 827, + 997, + 15, + 45, + 173, + 175, + 229, + 339, + 690, + 714, + 758, + 764, + 824, + 837, + 961, + 211, + 223, + 606, + 623, + 648, + 674, + 684, + 819, + 919, + 207, + 258, + 277, + 280, + 285, + 424, + 429, + 670, + 855, + 867, + 872, + 966, + 0, + 21, + 346, + 560, + 652, + 791, + 911, + 327, + 376, + 387, + 460, + 491, + 496, + 662, + 667, + 745, + 754, + 767, + 974, + 2, + 209, + 210, + 598, + 883, + 930, + 952, + 7, + 90, + 267, + 342, + 368, + 486, + 628, + 698, + 915, + 935, + 2, + 12, + 86, + 209, + 243, + 383, + 449, + 604, + 841, + 967, + 976, + 27, + 31, + 47, + 117, + 424, + 536, + 714, + 745, + 891, + 899, + 950, + 85, + 152, + 210, + 270, + 389, + 551, + 86, + 140, + 202, + 432, + 625, + 885, + 908, + 928, + 43, + 81, + 110, + 227, + 278, + 589, + 613, + 729, + 732, + 743, + 747, + 762, + 784, + 864, + 980, + 57, + 132, + 309, + 313, + 349, + 366, + 494, + 563, + 564, + 604, + 640, + 800, + 935, + 6, + 77, + 201, + 726, + 745, + 772, + 833, + 990, + 33, + 45, + 178, + 335, + 393, + 410, + 498, + 534, + 603, + 626, + 672, + 685, + 740, + 930, + 995, + 118, + 142, + 306, + 373, + 446, + 480, + 802, + 930, + 998, + 184, + 273, + 401, + 444, + 483, + 484, + 526, + 611, + 641, + 666, + 681, + 786, + 899, + 919, + 942, + 31, + 50, + 66, + 68, + 86, + 140, + 229, + 349, + 445, + 588, + 665, + 682, + 686, + 783, + 798, + 900, + 926, + 976, + 261, + 727, + 811, + 125, + 144, + 256, + 377, + 644, + 660, + 752, + 843, + 981, + 982, + 997, + 998, + 296, + 382, + 477, + 479, + 548, + 583, + 676, + 767, + 791, + 25, + 446, + 546, + 585, + 654, + 727, + 804, + 969, + 7, + 53, + 203, + 220, + 247, + 450, + 487, + 503, + 578, + 638, + 657, + 730, + 753, + 792, + 998, + 4, + 87, + 316, + 379, + 840, + 891, + 896, + 902, + 906, + 150, + 361, + 490, + 517, + 533, + 693, + 696, + 791, + 805, + 868, + 944, + 962, + 128, + 154, + 165, + 374, + 573, + 636, + 796, + 44, + 78, + 249, + 341, + 392, + 538, + 569, + 746, + 752, + 858, + 59, + 106, + 357, + 471, + 570, + 680, + 850, + 968, + 984, + 166, + 184, + 216, + 263, + 306, + 660, + 745, + 807, + 207, + 236, + 295, + 302, + 444, + 536, + 603, + 618, + 632, + 938, + 198, + 212, + 293, + 357, + 381, + 384, + 406, + 564, + 763, + 813, + 908, + 922, + 936, + 958, + 54, + 119, + 458, + 459, + 586, + 764, + 810, + 869, + 897, + 168, + 200, + 232, + 274, + 312, + 423, + 434, + 497, + 549, + 618, + 628, + 829, + 842, + 896, + 961, + 105, + 226, + 276, + 292, + 592, + 727, + 818, + 106, + 426, + 459, + 529, + 543, + 544, + 569, + 572, + 600, + 601, + 629, + 641, + 700, + 766, + 793, + 24, + 87, + 89, + 173, + 312, + 617, + 680, + 921, + 960, + 991, + 234, + 289, + 308, + 321, + 364, + 865, + 14, + 76, + 98, + 425, + 656, + 965, + 289, + 435, + 497, + 630, + 695, + 907, + 977, + 41, + 95, + 276, + 584, + 700, + 822, + 829, + 29, + 129, + 183, + 244, + 247, + 258, + 276, + 303, + 337, + 374, + 413, + 424, + 431, + 434, + 507, + 675, + 713, + 827, + 855, + 49, + 81, + 99, + 133, + 163, + 213, + 219, + 425, + 747, + 810, + 997, + 95, + 271, + 454, + 553, + 775, + 796, + 974, + 984, + 439, + 468, + 662, + 799, + 897, + 907, + 936, + 92, + 101, + 119, + 146, + 780, + 915, + 65, + 292, + 373, + 408, + 465, + 564, + 752, + 756, + 818, + 863, + 960, + 124, + 128, + 414, + 811, + 843, + 890, + 134, + 211, + 218, + 271, + 288, + 353, + 612, + 765, + 772, + 825, + 853, + 859, + 910, + 60, + 68, + 327, + 452, + 638, + 642, + 675, + 682, + 692, + 710, + 722, + 732, + 807, + 42, + 93, + 220, + 272, + 284, + 306, + 472, + 635, + 714, + 718, + 61, + 67, + 110, + 362, + 397, + 471, + 667, + 965, + 98, + 180, + 259, + 387, + 400, + 433, + 592, + 725, + 811, + 884, + 975, + 181, + 383, + 497, + 584, + 595, + 634, + 883, + 957, + 386, + 387, + 419, + 538, + 604, + 681, + 780, + 834, + 981, + 113, + 146, + 166, + 224, + 228, + 237, + 249, + 341, + 516, + 569, + 593, + 744, + 819, + 891, + 984, + 23, + 74, + 323, + 540, + 592, + 681, + 733, + 739, + 853, + 19, + 176, + 191, + 580, + 581, + 823, + 930, + 8, + 35, + 97, + 238, + 240, + 264, + 575, + 620, + 649, + 668, + 686, + 713, + 775, + 784, + 900, + 992, + 185, + 448, + 498, + 697, + 709, + 783, + 278, + 279, + 325, + 554, + 667, + 672, + 894, + 925, + 43, + 89, + 172, + 524, + 526, + 735, + 748, + 772, + 778, + 268, + 435, + 528, + 561, + 604, + 708, + 79, + 334, + 401, + 650, + 838, + 841, + 898, + 82, + 112, + 196, + 217, + 229, + 441, + 644, + 101, + 116, + 139, + 398, + 399, + 424, + 493, + 600, + 644, + 659, + 785, + 966, + 983, + 5, + 284, + 315, + 495, + 563, + 566, + 624, + 802, + 986, + 129, + 169, + 325, + 440, + 448, + 706, + 752, + 845, + 863, + 114, + 153, + 277, + 287, + 535, + 588, + 602, + 609, + 736, + 769, + 185, + 272, + 304, + 332, + 569, + 743, + 811, + 54, + 72, + 218, + 292, + 379, + 556, + 638, + 825, + 8, + 60, + 87, + 391, + 421, + 568, + 602, + 644, + 667, + 764, + 797, + 809, + 872, + 900, + 950, + 952, + 178, + 247, + 251, + 412, + 811, + 823, + 897, + 929, + 115, + 129, + 212, + 341, + 352, + 578, + 754, + 920, + 925, + 160, + 429, + 511, + 522, + 709, + 838, + 942, + 12, + 123, + 206, + 214, + 253, + 255, + 264, + 458, + 641, + 679, + 848, + 238, + 309, + 380, + 491, + 565, + 619, + 697, + 750, + 835, + 936, + 957, + 962, + 345, + 380, + 463, + 486, + 547, + 653, + 763, + 787, + 859, + 861, + 940, + 950, + 984, + 164, + 281, + 297, + 344, + 510, + 570, + 580, + 657, + 936, + 984, + 66, + 210, + 590, + 877, + 72, + 85, + 106, + 143, + 148, + 385, + 557, + 627, + 631, + 653, + 724, + 742, + 745, + 800, + 829, + 58, + 179, + 352, + 528, + 658, + 696, + 761, + 763, + 864, + 28, + 34, + 164, + 235, + 712, + 742, + 802, + 919, + 943, + 962, + 64, + 143, + 312, + 336, + 338, + 371, + 381, + 519, + 690, + 811, + 868, + 65, + 374, + 403, + 440, + 508, + 525, + 884, + 26, + 112, + 144, + 218, + 228, + 234, + 254, + 281, + 315, + 455, + 493, + 505, + 598, + 677, + 707, + 948, + 20, + 160, + 165, + 186, + 290, + 353, + 787, + 806, + 904, + 917, + 10, + 67, + 246, + 290, + 560, + 620, + 711, + 724, + 8, + 375, + 410, + 481, + 515, + 663, + 743, + 747, + 967, + 179, + 252, + 256, + 324, + 877, + 885, + 971, + 90, + 306, + 330, + 445, + 728, + 806, + 888, + 287, + 348, + 412, + 500, + 631, + 687, + 726, + 728, + 85, + 238, + 273, + 403, + 532, + 654, + 879, + 23, + 102, + 434, + 437, + 849, + 856, + 17, + 265, + 383, + 547, + 599, + 858, + 995, + 285, + 320, + 553, + 737, + 787, + 894, + 5, + 17, + 89, + 190, + 327, + 418, + 525, + 543, + 587, + 678, + 730, + 835, + 928, + 947, + 13, + 74, + 134, + 303, + 421, + 436, + 475, + 701, + 929, + 156, + 347, + 498, + 698, + 870, + 909, + 4, + 15, + 45, + 73, + 229, + 268, + 345, + 357, + 459, + 500, + 513, + 544, + 620, + 624, + 702, + 959, + 29, + 71, + 163, + 196, + 197, + 416, + 756, + 851, + 890, + 921, + 926, + 65, + 443, + 507, + 514, + 531, + 581, + 649, + 674, + 855, + 861, + 865, + 957, + 35, + 94, + 113, + 505, + 660, + 821, + 208, + 229, + 246, + 324, + 327, + 446, + 470, + 494, + 518, + 526, + 600, + 659, + 886, + 897, + 103, + 402, + 403, + 460, + 541, + 709, + 815, + 816, + 973, + 128, + 236, + 378, + 398, + 561, + 602, + 609, + 659, + 677, + 688, + 741, + 815, + 59, + 82, + 122, + 162, + 233, + 265, + 335, + 407, + 452, + 489, + 495, + 542, + 642, + 696, + 825, + 902, + 262, + 524, + 738, + 166, + 389, + 408, + 564, + 603, + 639, + 942, + 16, + 51, + 87, + 211, + 336, + 371, + 404, + 449, + 538, + 560, + 594, + 612, + 849, + 953, + 23, + 64, + 432, + 559, + 802, + 813, + 874, + 919, + 89, + 341, + 355, + 383, + 509, + 650, + 778, + 972, + 998, + 13, + 208, + 407, + 419, + 465, + 582, + 595, + 825, + 909, + 83, + 110, + 184, + 240, + 362, + 559, + 684, + 815, + 840, + 881, + 269, + 670, + 675, + 680, + 793, + 794, + 804, + 805, + 807, + 830, + 2, + 20, + 491, + 581, + 676, + 9, + 231, + 243, + 294, + 464, + 513, + 544, + 703, + 763, + 813, + 862, + 880, + 943, + 114, + 115, + 131, + 145, + 191, + 357, + 380, + 391, + 394, + 399, + 548, + 651, + 654, + 805, + 82, + 152, + 163, + 241, + 250, + 331, + 430, + 467, + 474, + 536, + 598, + 634, + 722, + 778, + 857, + 951, + 954, + 104, + 131, + 190, + 354, + 475, + 511, + 574, + 656, + 778, + 801, + 902, + 100, + 296, + 462, + 928, + 9, + 231, + 239, + 263, + 311, + 485, + 614, + 713, + 139, + 238, + 307, + 343, + 349, + 395, + 499, + 678, + 821, + 912, + 166, + 181, + 312, + 491, + 520, + 710, + 752, + 871, + 108, + 306, + 511, + 652, + 679, + 777, + 799, + 19, + 23, + 80, + 92, + 261, + 466, + 558, + 606, + 781, + 844, + 941, + 11, + 89, + 94, + 178, + 257, + 381, + 398, + 586, + 610, + 646, + 817, + 903, + 952, + 988, + 107, + 176, + 296, + 332, + 430, + 434, + 531, + 669, + 807, + 888, + 997, + 124, + 246, + 537, + 650, + 786, + 979, + 194, + 535, + 548, + 560, + 566, + 711, + 760, + 930, + 947, + 143, + 151, + 395, + 872, + 981, + 95, + 107, + 380, + 475, + 552, + 597, + 757, + 804, + 810, + 914, + 96, + 210, + 329, + 445, + 516, + 575, + 609, + 690, + 860, + 913, + 963, + 134, + 197, + 307, + 313, + 414, + 465, + 560, + 639, + 780, + 854, + 946, + 103, + 353, + 413, + 532, + 657, + 689, + 904, + 958, + 990, + 43, + 131, + 142, + 217, + 236, + 406, + 597, + 859, + 61, + 153, + 437, + 468, + 586, + 635, + 670, + 701, + 117, + 138, + 237, + 305, + 358, + 528, + 605, + 613, + 628, + 759, + 771, + 836, + 896, + 968, + 988, + 34, + 82, + 347, + 448, + 461, + 575, + 761, + 910, + 977, + 50, + 103, + 173, + 185, + 287, + 308, + 406, + 462, + 671, + 767, + 789, + 890, + 905, + 548, + 562, + 606, + 653, + 692, + 846, + 114, + 170, + 477, + 549, + 607, + 696, + 945, + 130, + 172, + 175, + 319, + 443, + 480, + 869, + 44, + 65, + 111, + 324, + 413, + 474, + 610, + 627, + 642, + 685, + 807, + 824, + 265, + 465, + 558, + 564, + 614, + 628, + 833, + 916, + 942, + 26, + 70, + 136, + 208, + 492, + 641, + 803, + 912, + 914, + 74, + 168, + 198, + 368, + 376, + 558, + 737, + 783, + 816, + 845, + 959, + 126, + 246, + 406, + 444, + 449, + 517, + 579, + 665, + 772, + 789, + 906, + 988, + 189, + 235, + 374, + 387, + 446, + 456, + 554, + 643, + 685, + 826, + 848, + 893, + 944, + 972, + 21, + 134, + 141, + 304, + 360, + 385, + 409, + 498, + 523, + 659, + 8, + 111, + 156, + 256, + 276, + 342, + 449, + 480, + 543, + 686, + 691, + 863, + 205, + 281, + 302, + 375, + 439, + 492, + 605, + 675, + 707, + 741, + 933, + 966, + 971, + 42, + 381, + 569, + 899, + 902, + 980, + 217, + 321, + 374, + 416, + 482, + 560, + 563, + 626, + 677, + 690, + 780, + 788, + 963, + 57, + 58, + 61, + 77, + 110, + 255, + 326, + 389, + 466, + 476, + 557, + 744, + 791, + 846, + 861, + 967, + 980, + 31, + 99, + 213, + 234, + 282, + 362, + 396, + 702, + 861, + 51, + 102, + 209, + 308, + 335, + 408, + 418, + 511, + 567, + 726, + 758, + 899, + 927, + 940, + 992, + 69, + 132, + 185, + 261, + 358, + 396, + 684, + 872, + 986, + 116, + 149, + 204, + 691, + 814, + 892, + 895, + 914, + 916, + 154, + 224, + 243, + 253, + 282, + 368, + 579, + 654, + 661, + 703, + 735, + 868, + 930, + 29, + 164, + 253, + 277, + 290, + 340, + 626, + 765, + 852, + 173, + 203, + 225, + 282, + 415, + 587, + 595, + 643, + 858, + 874, + 83, + 238, + 314, + 462, + 803, + 822, + 960, + 83, + 362, + 467, + 497, + 666, + 748, + 814, + 76, + 210, + 256, + 374, + 538, + 759, + 833, + 881, + 8, + 57, + 74, + 92, + 117, + 142, + 383, + 649, + 738, + 815, + 821, + 836, + 919, + 13, + 18, + 218, + 342, + 474, + 664, + 723, + 827, + 866, + 147, + 153, + 240, + 404, + 557, + 567, + 591, + 656, + 721, + 757, + 822, + 12, + 98, + 205, + 241, + 376, + 394, + 487, + 494, + 823, + 919, + 74, + 272, + 285, + 362, + 575, + 598, + 873, + 880, + 894, + 119, + 221, + 227, + 291, + 338, + 447, + 507, + 541, + 559, + 620, + 721, + 752, + 802, + 819, + 835, + 843, + 849, + 90, + 130, + 258, + 417, + 481, + 576, + 611, + 826, + 859, + 893, + 950, + 321, + 476, + 528, + 664, + 679, + 752, + 789, + 940, + 951, + 51, + 97, + 144, + 274, + 341, + 384, + 466, + 627, + 642, + 682, + 753, + 766, + 140, + 301, + 310, + 340, + 480, + 669, + 793, + 885, + 887, + 917, + 83, + 115, + 188, + 269, + 272, + 418, + 534, + 546, + 746, + 810, + 869, + 109, + 126, + 185, + 245, + 345, + 750, + 759, + 815, + 854, + 492, + 514, + 609, + 647, + 706, + 726, + 760, + 106, + 176, + 289, + 544, + 753, + 861, + 901, + 47, + 145, + 234, + 253, + 308, + 466, + 467, + 826, + 38, + 89, + 147, + 210, + 254, + 270, + 283, + 453, + 607, + 727, + 828, + 874, + 912, + 915, + 921, + 17, + 201, + 303, + 338, + 815, + 880, + 984, + 100, + 296, + 475, + 490, + 567, + 963, + 979, + 72, + 110, + 120, + 308, + 451, + 622, + 670, + 695, + 696, + 720, + 912, + 981, + 23, + 239, + 255, + 344, + 397, + 847, + 950, + 45, + 141, + 311, + 607, + 626, + 877, + 58, + 87, + 106, + 132, + 210, + 232, + 265, + 373, + 447, + 476, + 621, + 887, + 959, + 134, + 135, + 187, + 189, + 345, + 346, + 411, + 603, + 626, + 901, + 21, + 158, + 177, + 263, + 344, + 408, + 458, + 851, + 855, + 856, + 942, + 971, + 978, + 6, + 23, + 129, + 235, + 368, + 400, + 617, + 962, + 311, + 445, + 457, + 530, + 540, + 650, + 722, + 18, + 118, + 176, + 177, + 337, + 350, + 510, + 771, + 787, + 804, + 839, + 193, + 229, + 261, + 434, + 523, + 528, + 553, + 559, + 660, + 673, + 197, + 400, + 436, + 481, + 556, + 566, + 569, + 627, + 642, + 662, + 866, + 101, + 247, + 354, + 423, + 611, + 669, + 714, + 923, + 323, + 447, + 531, + 561, + 668, + 674, + 700, + 816, + 921, + 27, + 243, + 270, + 324, + 341, + 380, + 546, + 594, + 730, + 877, + 889, + 367, + 683, + 847, + 889, + 897, + 166, + 535, + 574, + 680, + 819, + 949, + 185, + 261, + 266, + 637, + 639, + 669, + 836, + 963, + 990, + 72, + 233, + 450, + 675, + 815, + 826, + 996, + 93, + 129, + 278, + 355, + 405, + 422, + 430, + 550, + 585, + 727, + 783, + 795, + 882, + 51, + 79, + 303, + 308, + 311, + 354, + 449, + 469, + 530, + 553, + 572, + 731, + 757, + 900, + 933, + 255, + 359, + 382, + 405, + 426, + 453, + 680, + 727, + 757, + 195, + 287, + 342, + 445, + 687, + 693, + 824, + 875, + 955, + 986, + 29, + 61, + 154, + 200, + 236, + 287, + 359, + 497, + 568, + 761, + 843, + 965, + 140, + 217, + 301, + 459, + 518, + 647, + 698, + 870, + 880, + 24, + 60, + 158, + 202, + 223, + 333, + 477, + 746, + 749, + 826, + 930, + 265, + 431, + 539, + 588, + 610, + 620, + 900, + 901, + 929, + 13, + 117, + 140, + 170, + 287, + 390, + 438, + 580, + 611, + 659, + 806, + 916, + 930, + 940, + 159, + 296, + 467, + 534, + 639, + 679, + 706, + 878, + 989, + 147, + 533, + 545, + 685, + 741, + 846, + 2, + 34, + 251, + 331, + 424, + 440, + 647, + 694, + 733, + 808, + 866, + 929, + 423, + 571, + 667, + 692, + 996, + 74, + 347, + 424, + 565, + 581, + 618, + 638, + 658, + 681, + 833, + 919, + 936, + 965, + 128, + 307, + 357, + 367, + 412, + 468, + 523, + 571, + 616, + 667, + 683, + 57, + 137, + 197, + 337, + 398, + 606, + 781, + 840, + 850, + 864, + 880, + 948, + 115, + 177, + 229, + 265, + 293, + 303, + 479, + 659, + 667, + 813, + 844, + 953, + 22, + 95, + 274, + 308, + 423, + 485, + 608, + 632, + 688, + 820, + 875, + 945, + 952, + 71, + 234, + 248, + 250, + 497, + 951, + 141, + 170, + 236, + 265, + 394, + 471, + 567, + 703, + 854, + 896, + 897, + 37, + 164, + 271, + 395, + 524, + 793, + 943, + 5, + 109, + 156, + 183, + 293, + 349, + 383, + 533, + 679, + 743, + 114, + 138, + 236, + 316, + 334, + 352, + 489, + 569, + 699, + 755, + 904, + 993, + 314, + 489, + 568, + 658, + 736, + 748, + 848, + 156, + 160, + 252, + 472, + 531, + 613, + 687, + 701, + 740, + 767, + 780, + 841, + 882, + 975, + 990, + 47, + 195, + 363, + 506, + 654, + 767, + 792, + 802, + 150, + 204, + 319, + 379, + 455, + 574, + 843, + 869, + 84, + 116, + 190, + 191, + 193, + 268, + 366, + 409, + 579, + 628, + 767, + 794, + 801, + 823, + 887, + 107, + 176, + 361, + 465, + 467, + 647, + 666, + 700, + 708, + 720, + 754, + 784, + 932, + 959, + 66, + 167, + 196, + 213, + 261, + 319, + 330, + 398, + 416, + 534, + 598, + 677, + 787, + 800, + 910, + 961, + 999, + 404, + 411, + 452, + 536, + 786, + 886, + 940, + 84, + 116, + 236, + 334, + 374, + 433, + 701, + 870, + 73, + 184, + 341, + 367, + 412, + 423, + 673, + 678, + 981, + 258, + 269, + 313, + 360, + 423, + 561, + 602, + 854, + 985, + 112, + 227, + 253, + 256, + 326, + 327, + 517, + 624, + 736, + 891, + 38, + 79, + 361, + 369, + 581, + 583, + 700, + 43, + 100, + 329, + 391, + 722, + 926, + 967, + 972, + 82, + 224, + 254, + 366, + 389, + 755, + 756, + 820, + 942, + 54, + 393, + 405, + 464, + 596, + 663, + 864, + 966, + 108, + 297, + 305, + 368, + 832, + 878, + 903, + 918, + 995, + 324, + 797, + 823, + 871, + 298, + 535, + 642, + 720, + 803, + 910, + 961, + 33, + 319, + 442, + 492, + 568, + 803, + 8, + 84, + 197, + 359, + 435, + 791, + 922, + 949, + 969, + 984, + 210, + 220, + 380, + 904, + 949, + 977, + 984, + 22, + 68, + 83, + 190, + 333, + 468, + 648, + 683, + 783, + 807, + 856, + 959, + 54, + 95, + 180, + 213, + 353, + 417, + 721, + 744, + 888, + 331, + 388, + 441, + 951, + 5, + 86, + 132, + 167, + 224, + 366, + 553, + 655, + 812, + 815, + 989, + 33, + 34, + 183, + 239, + 270, + 529, + 811, + 105, + 117, + 126, + 220, + 280, + 315, + 353, + 201, + 294, + 364, + 511, + 521, + 532, + 557, + 744, + 756, + 846, + 173, + 199, + 436, + 511, + 712, + 725, + 27, + 244, + 262, + 274, + 347, + 404, + 486, + 623, + 857, + 858, + 34, + 126, + 217, + 618, + 674, + 813, + 818, + 830, + 876, + 885, + 63, + 134, + 200, + 269, + 427, + 448, + 486, + 646, + 774, + 778, + 928, + 162, + 229, + 251, + 273, + 277, + 281, + 372, + 448, + 563, + 606, + 641, + 845, + 997, + 81, + 93, + 153, + 516, + 592, + 603, + 641, + 706, + 929, + 945, + 17, + 25, + 109, + 140, + 440, + 524, + 803, + 309, + 494, + 513, + 542, + 778, + 809, + 93, + 161, + 360, + 405, + 507, + 556, + 559, + 734, + 881, + 986, + 53, + 238, + 271, + 320, + 367, + 600, + 768, + 940, + 315, + 351, + 521, + 530, + 548, + 549, + 628, + 881, + 909, + 917, + 246, + 296, + 318, + 324, + 339, + 359, + 393, + 511, + 557, + 690, + 696, + 764, + 777, + 810, + 954, + 73, + 337, + 473, + 526, + 601, + 620, + 668, + 689, + 698, + 768, + 782, + 859, + 930, + 937, + 942, + 954, + 162, + 279, + 410, + 454, + 958, + 29, + 36, + 77, + 109, + 139, + 185, + 224, + 270, + 512, + 601, + 657, + 664, + 669, + 683, + 695, + 734, + 947, + 146, + 193, + 464, + 491, + 767, + 771, + 818, + 911, + 947, + 981, + 56, + 102, + 291, + 434, + 527, + 601, + 613, + 646, + 731, + 777, + 3, + 90, + 179, + 196, + 270, + 380, + 458, + 638, + 680, + 854, + 883, + 956, + 72, + 104, + 272, + 518, + 755, + 33, + 387, + 450, + 519, + 528, + 576, + 607, + 637, + 786, + 228, + 298, + 355, + 377, + 414, + 560, + 847, + 853, + 927, + 47, + 191, + 304, + 328, + 371, + 424, + 441, + 555, + 658, + 837, + 902, + 132, + 215, + 252, + 278, + 293, + 339, + 390, + 729, + 754, + 855, + 896, + 11, + 115, + 159, + 173, + 351, + 407, + 412, + 438, + 996, + 87, + 104, + 164, + 212, + 213, + 329, + 419, + 668, + 683, + 847, + 940, + 134, + 245, + 296, + 306, + 346, + 369, + 382, + 417, + 495, + 555, + 578, + 662, + 712, + 844, + 850, + 885, + 988, + 58, + 212, + 347, + 886, + 925, + 60, + 132, + 301, + 377, + 933, + 26, + 38, + 49, + 94, + 176, + 206, + 344, + 416, + 686, + 719, + 734, + 837, + 32, + 160, + 194, + 481, + 567, + 653, + 711, + 813, + 871, + 946, + 980, + 48, + 53, + 124, + 170, + 281, + 370, + 414, + 501, + 938, + 943, + 951, + 115, + 386, + 540, + 583, + 678, + 729, + 901, + 28, + 105, + 153, + 177, + 178, + 443, + 494, + 496, + 591, + 609, + 628, + 683, + 22, + 144, + 185, + 234, + 306, + 323, + 704, + 830, + 838, + 923, + 940, + 29, + 75, + 140, + 393, + 625, + 760, + 916, + 919, + 15, + 109, + 266, + 846, + 107, + 129, + 278, + 279, + 323, + 438, + 461, + 543, + 567, + 648, + 713, + 866, + 908, + 277, + 320, + 390, + 421, + 549, + 564, + 620, + 885, + 935, + 58, + 322, + 330, + 432, + 435, + 517, + 578, + 704, + 941, + 952, + 89, + 172, + 420, + 511, + 542, + 607, + 654, + 921, + 103, + 240, + 287, + 289, + 302, + 324, + 399, + 415, + 657, + 680, + 764, + 781, + 799, + 824, + 835, + 911, + 36, + 148, + 156, + 170, + 241, + 478, + 600, + 672, + 685, + 764, + 936, + 979, + 106, + 285, + 492, + 493, + 834, + 839, + 873, + 948, + 956, + 35, + 50, + 122, + 176, + 261, + 597, + 621, + 628, + 654, + 935, + 190, + 244, + 301, + 337, + 473, + 646, + 886, + 76, + 193, + 213, + 313, + 331, + 356, + 408, + 449, + 511, + 848, + 853, + 876, + 19, + 109, + 168, + 262, + 269, + 320, + 467, + 642, + 650, + 687, + 703, + 921, + 936, + 973, + 43, + 68, + 305, + 395, + 433, + 534, + 746, + 812, + 815, + 986, + 998, + 165, + 240, + 323, + 346, + 459, + 468, + 474, + 650, + 834, + 919, + 991, + 993, + 36, + 40, + 46, + 195, + 331, + 346, + 844, + 852, + 7, + 216, + 248, + 548, + 637, + 733, + 788, + 810, + 909, + 151, + 205, + 248, + 297, + 381, + 501, + 589, + 601, + 610, + 693, + 851, + 211, + 379, + 508, + 770, + 955, + 17, + 216, + 372, + 471, + 804, + 838, + 934, + 977, + 16, + 119, + 332, + 338, + 478, + 628, + 803, + 911, + 8, + 132, + 144, + 169, + 192, + 713, + 748, + 808, + 824, + 13, + 19, + 31, + 78, + 94, + 513, + 561, + 587, + 825, + 953, + 248, + 254, + 470, + 520, + 594, + 634, + 636, + 647, + 830, + 862, + 869, + 17, + 37, + 62, + 138, + 270, + 337, + 449, + 474, + 540, + 566, + 583, + 721, + 929, + 935, + 954, + 221, + 273, + 315, + 397, + 447, + 641, + 725, + 830, + 885, + 928, + 7, + 175, + 188, + 464, + 482, + 493, + 519, + 612, + 615, + 666, + 758, + 807, + 915, + 70, + 133, + 350, + 438, + 479, + 522, + 564, + 893, + 120, + 273, + 384, + 424, + 446, + 447, + 467, + 585, + 633, + 792, + 948, + 997, + 7, + 51, + 151, + 197, + 232, + 348, + 581, + 596, + 628, + 833, + 890, + 32, + 96, + 265, + 272, + 387, + 691, + 694, + 17, + 322, + 369, + 457, + 499, + 611, + 735, + 813, + 885, + 72, + 84, + 130, + 210, + 228, + 334, + 349, + 396, + 443, + 483, + 498, + 508, + 509, + 762, + 105, + 127, + 157, + 198, + 206, + 286, + 298, + 371, + 380, + 516, + 698, + 738, + 837, + 840, + 946, + 982, + 359, + 436, + 687, + 802, + 805, + 950, + 112, + 113, + 141, + 282, + 290, + 524, + 527, + 624, + 642, + 762, + 840, + 858, + 997, + 30, + 257, + 465, + 573, + 605, + 661, + 752, + 783, + 795, + 880, + 907, + 8, + 101, + 145, + 253, + 375, + 459, + 556, + 559, + 584, + 748, + 999, + 50, + 180, + 388, + 638, + 902, + 122, + 192, + 405, + 468, + 486, + 562, + 604, + 841, + 844, + 134, + 197, + 381, + 382, + 414, + 430, + 431, + 655, + 666, + 807, + 958, + 81, + 210, + 496, + 538, + 724, + 903, + 947, + 51, + 118, + 243, + 326, + 537, + 597, + 836, + 966, + 11, + 139, + 147, + 204, + 214, + 269, + 288, + 290, + 304, + 307, + 334, + 451, + 575, + 600, + 661, + 775, + 800, + 969, + 986, + 64, + 206, + 269, + 403, + 461, + 508, + 548, + 581, + 596, + 692, + 777, + 124, + 232, + 312, + 322, + 447, + 498, + 526, + 543, + 656, + 670, + 712, + 751, + 907, + 923, + 71, + 94, + 114, + 148, + 201, + 249, + 293, + 296, + 331, + 336, + 505, + 607, + 768, + 933, + 217, + 260, + 296, + 302, + 311, + 581, + 625, + 655, + 781, + 892, + 926, + 23, + 43, + 100, + 156, + 273, + 337, + 572, + 673, + 741, + 980, + 52, + 156, + 164, + 336, + 373, + 400, + 470, + 951, + 20, + 30, + 73, + 179, + 351, + 566, + 636, + 872, + 883, + 944, + 11, + 62, + 460, + 482, + 486, + 495, + 512, + 651, + 868, + 917, + 997, + 16, + 74, + 417, + 496, + 590, + 639, + 692, + 778, + 781, + 855, + 928, + 930, + 259, + 275, + 477, + 637, + 748, + 807, + 957, + 999, + 38, + 184, + 260, + 266, + 268, + 323, + 391, + 598, + 628, + 881, + 947, + 54, + 62, + 219, + 270, + 471, + 473, + 491, + 673, + 859, + 892, + 947, + 72, + 218, + 309, + 331, + 372, + 573, + 741, + 822, + 825, + 966, + 48, + 200, + 205, + 237, + 261, + 265, + 338, + 353, + 666, + 928, + 967, + 53, + 74, + 259, + 284, + 507, + 615, + 886, + 905, + 955, + 10, + 21, + 44, + 406, + 460, + 684, + 782, + 816, + 826, + 907, + 34, + 189, + 260, + 332, + 356, + 444, + 460, + 758, + 781, + 838, + 842, + 905, + 967, + 6, + 7, + 169, + 220, + 295, + 384, + 399, + 442, + 739, + 922, + 969, + 286, + 300, + 401, + 460, + 503, + 659, + 686, + 727, + 749, + 785, + 974, + 993, + 998, + 183, + 210, + 328, + 450, + 453, + 480, + 496, + 517, + 525, + 549, + 635, + 716, + 732, + 748, + 749, + 832, + 959, + 95, + 107, + 121, + 258, + 326, + 416, + 588, + 654, + 753, + 831, + 34, + 83, + 101, + 181, + 224, + 552, + 623, + 671, + 866, + 983, + 997, + 104, + 129, + 143, + 198, + 213, + 420, + 438, + 612, + 674, + 910, + 943, + 210, + 212, + 218, + 321, + 330, + 455, + 692, + 794, + 839, + 960, + 965, + 17, + 101, + 124, + 395, + 476, + 513, + 514, + 566, + 692, + 846, + 856, + 859, + 862, + 908, + 920, + 947, + 958, + 8, + 200, + 373, + 462, + 556, + 739, + 796, + 932, + 951, + 958, + 44, + 56, + 186, + 262, + 310, + 355, + 380, + 470, + 593, + 714, + 906, + 964, + 989, + 65, + 114, + 195, + 306, + 307, + 355, + 403, + 469, + 513, + 654, + 685, + 800, + 812, + 816, + 825, + 843, + 925, + 3, + 328, + 425, + 486, + 730, + 773, + 789, + 824, + 943, + 966, + 967, + 981, + 984, + 83, + 156, + 311, + 439, + 545, + 565, + 650, + 682, + 769, + 299, + 341, + 409, + 782, + 943, + 5, + 52, + 57, + 123, + 146, + 175, + 409, + 443, + 532, + 989, + 120, + 158, + 430, + 436, + 449, + 640, + 659, + 734, + 749, + 834, + 882, + 911, + 952, + 22, + 226, + 442, + 591, + 879, + 51, + 69, + 86, + 97, + 178, + 263, + 316, + 425, + 534, + 554, + 565, + 888, + 988, + 991, + 24, + 352, + 511, + 522, + 555, + 570, + 603, + 696, + 887, + 960, + 39, + 133, + 260, + 401, + 465, + 526, + 609, + 732, + 131, + 206, + 305, + 669, + 809, + 877, + 986, + 439, + 520, + 567, + 588, + 617, + 712, + 891, + 998, + 274, + 358, + 425, + 495, + 715, + 872, + 918, + 923, + 951, + 980, + 983, + 119, + 123, + 316, + 324, + 349, + 644, + 705, + 718, + 769, + 781, + 795, + 884, + 110, + 133, + 140, + 152, + 157, + 495, + 569, + 608, + 629, + 803, + 827, + 909, + 942, + 9, + 230, + 268, + 423, + 626, + 707, + 724, + 748, + 828, + 996, + 274, + 308, + 436, + 722, + 879, + 213, + 259, + 324, + 329, + 377, + 534, + 588, + 827, + 896, + 149, + 261, + 591, + 597, + 785, + 813, + 883, + 920, + 996, + 10, + 64, + 237, + 417, + 535, + 686, + 709, + 717, + 744, + 41, + 67, + 260, + 370, + 405, + 407, + 520, + 632, + 893, + 955, + 127, + 250, + 336, + 354, + 388, + 474, + 591, + 703, + 805, + 811, + 833, + 871, + 881, + 991, + 994, + 17, + 91, + 113, + 122, + 300, + 301, + 463, + 716, + 741, + 776, + 784, + 906, + 994, + 33, + 57, + 206, + 448, + 520, + 612, + 769, + 834, + 282, + 393, + 441, + 461, + 503, + 796, + 72, + 206, + 304, + 381, + 565, + 723, + 114, + 121, + 130, + 259, + 346, + 386, + 432, + 538, + 575, + 595, + 855, + 945 +}; +const double x[1000] = { + 602, + 730, + 528, + 886, + 890, + 755, + 124, + 435, + 24, + 245, + 112, + 144, + 171, + 746, + 547, + 172, + 905, + 97, + 70, + 133, + 117, + 951, + 783, + 271, + 174, + 263, + 769, + 889, + 920, + 698, + 644, + 138, + 34, + 866, + 831, + 249, + 611, + 672, + 502, + 450, + 225, + 557, + 793, + 244, + 336, + 942, + 604, + 135, + 507, + 328, + 36, + 299, + 769, + 323, + 957, + 171, + 455, + 627, + 701, + 624, + 383, + 354, + 675, + 971, + 562, + 945, + 354, + 90, + 495, + 269, + 684, + 468, + 832, + 38, + 189, + 103, + 509, + 754, + 85, + 70, + 727, + 897, + 441, + 745, + 443, + 561, + 23, + 796, + 104, + 178, + 388, + 178, + 663, + 652, + 533, + 738, + 423, + 500, + 390, + 567, + 834, + 806, + 97, + 517, + 352, + 636, + 158, + 839, + 822, + 68, + 707, + 838, + 778, + 15, + 201, + 364, + 397, + 166, + 372, + 39, + 525, + 360, + 596, + 664, + 606, + 182, + 684, + 147, + 941, + 695, + 815, + 721, + 377, + 215, + 386, + 265, + 598, + 890, + 241, + 302, + 423, + 623, + 610, + 26, + 311, + 887, + 496, + 968, + 549, + 581, + 421, + 638, + 154, + 471, + 768, + 953, + 7, + 906, + 894, + 155, + 687, + 813, + 376, + 463, + 815, + 436, + 817, + 5, + 366, + 412, + 435, + 825, + 437, + 614, + 437, + 14, + 492, + 117, + 610, + 0, + 837, + 665, + 464, + 847, + 513, + 606, + 532, + 503, + 566, + 270, + 559, + 509, + 634, + 339, + 535, + 708, + 663, + 1, + 837, + 508, + 499, + 216, + 758, + 36, + 242, + 351, + 432, + 439, + 562, + 307, + 643, + 498, + 659, + 16, + 265, + 653, + 105, + 527, + 595, + 448, + 832, + 381, + 714, + 533, + 178, + 644, + 455, + 667, + 7, + 378, + 639, + 19, + 50, + 415, + 591, + 827, + 956, + 69, + 712, + 767, + 368, + 552, + 230, + 288, + 146, + 676, + 651, + 333, + 284, + 782, + 283, + 774, + 791, + 451, + 795, + 991, + 618, + 620, + 547, + 769, + 226, + 563, + 117, + 524, + 287, + 615, + 322, + 41, + 582, + 156, + 664, + 261, + 368, + 702, + 25, + 439, + 382, + 123, + 682, + 970, + 511, + 928, + 870, + 453, + 865, + 724, + 255, + 504, + 567, + 105, + 465, + 146, + 349, + 616, + 419, + 389, + 629, + 964, + 482, + 483, + 252, + 183, + 300, + 578, + 255, + 825, + 702, + 650, + 468, + 808, + 939, + 360, + 830, + 281, + 969, + 139, + 488, + 603, + 449, + 731, + 941, + 172, + 643, + 569, + 90, + 966, + 468, + 818, + 249, + 649, + 661, + 661, + 955, + 52, + 17, + 364, + 472, + 854, + 154, + 543, + 110, + 327, + 905, + 715, + 940, + 612, + 248, + 634, + 690, + 326, + 622, + 52, + 935, + 244, + 406, + 604, + 351, + 303, + 268, + 717, + 247, + 475, + 718, + 835, + 885, + 534, + 842, + 942, + 929, + 713, + 786, + 72, + 122, + 443, + 64, + 512, + 38, + 189, + 552, + 935, + 778, + 832, + 569, + 144, + 810, + 634, + 399, + 261, + 918, + 728, + 648, + 340, + 730, + 358, + 496, + 928, + 344, + 929, + 572, + 876, + 667, + 933, + 584, + 122, + 739, + 978, + 37, + 250, + 192, + 113, + 763, + 214, + 852, + 365, + 638, + 570, + 82, + 861, + 448, + 649, + 813, + 950, + 843, + 154, + 527, + 12, + 953, + 153, + 311, + 177, + 490, + 754, + 973, + 511, + 777, + 649, + 605, + 311, + 539, + 133, + 245, + 940, + 717, + 851, + 189, + 905, + 410, + 214, + 170, + 983, + 998, + 404, + 599, + 843, + 41, + 955, + 505, + 916, + 947, + 851, + 397, + 194, + 288, + 781, + 897, + 546, + 305, + 113, + 356, + 454, + 679, + 774, + 314, + 897, + 452, + 169, + 391, + 344, + 880, + 840, + 327, + 404, + 29, + 353, + 688, + 196, + 135, + 860, + 878, + 288, + 523, + 335, + 1, + 680, + 923, + 480, + 108, + 10, + 188, + 165, + 500, + 331, + 668, + 279, + 939, + 797, + 203, + 925, + 768, + 310, + 453, + 213, + 909, + 769, + 136, + 93, + 501, + 926, + 249, + 888, + 591, + 628, + 317, + 668, + 364, + 375, + 951, + 432, + 217, + 765, + 469, + 458, + 25, + 330, + 279, + 734, + 995, + 187, + 150, + 739, + 179, + 551, + 844, + 920, + 871, + 906, + 397, + 540, + 376, + 123, + 233, + 19, + 227, + 109, + 158, + 20, + 11, + 899, + 462, + 655, + 837, + 756, + 930, + 580, + 304, + 655, + 419, + 695, + 319, + 496, + 856, + 575, + 700, + 223, + 793, + 462, + 666, + 274, + 967, + 650, + 287, + 521, + 69, + 898, + 684, + 759, + 31, + 373, + 515, + 56, + 966, + 971, + 836, + 950, + 94, + 647, + 948, + 766, + 988, + 556, + 458, + 415, + 46, + 741, + 519, + 186, + 393, + 409, + 658, + 349, + 833, + 339, + 61, + 250, + 49, + 63, + 503, + 21, + 951, + 809, + 391, + 242, + 739, + 823, + 9, + 548, + 876, + 431, + 920, + 451, + 967, + 291, + 529, + 37, + 133, + 656, + 240, + 981, + 223, + 167, + 458, + 624, + 473, + 570, + 942, + 260, + 808, + 16, + 792, + 699, + 537, + 84, + 906, + 429, + 728, + 320, + 785, + 301, + 9, + 679, + 882, + 98, + 431, + 223, + 920, + 173, + 895, + 605, + 68, + 698, + 696, + 987, + 855, + 191, + 657, + 533, + 478, + 321, + 846, + 921, + 490, + 278, + 145, + 500, + 274, + 974, + 505, + 33, + 936, + 691, + 922, + 140, + 846, + 951, + 745, + 893, + 803, + 316, + 689, + 960, + 509, + 518, + 911, + 121, + 12, + 477, + 702, + 94, + 521, + 751, + 840, + 492, + 666, + 922, + 714, + 43, + 683, + 871, + 531, + 774, + 137, + 914, + 745, + 722, + 78, + 398, + 384, + 536, + 365, + 245, + 807, + 925, + 201, + 917, + 368, + 214, + 246, + 143, + 388, + 937, + 483, + 480, + 793, + 415, + 835, + 554, + 514, + 838, + 655, + 837, + 481, + 483, + 777, + 447, + 963, + 596, + 248, + 819, + 696, + 540, + 163, + 333, + 589, + 863, + 603, + 835, + 952, + 253, + 329, + 552, + 207, + 684, + 593, + 618, + 742, + 53, + 90, + 27, + 955, + 217, + 955, + 20, + 520, + 221, + 316, + 45, + 948, + 552, + 110, + 594, + 774, + 517, + 880, + 32, + 575, + 852, + 463, + 685, + 10, + 58, + 945, + 572, + 875, + 633, + 942, + 880, + 426, + 283, + 491, + 848, + 491, + 280, + 412, + 1, + 819, + 199, + 190, + 577, + 488, + 936, + 678, + 79, + 317, + 408, + 689, + 353, + 889, + 294, + 561, + 501, + 411, + 554, + 321, + 193, + 748, + 309, + 110, + 454, + 33, + 28, + 193, + 166, + 804, + 710, + 581, + 70, + 726, + 805, + 673, + 751, + 147, + 793, + 395, + 151, + 129, + 143, + 610, + 700, + 590, + 577, + 814, + 104, + 990, + 56, + 254, + 816, + 278, + 108, + 765, + 31, + 208, + 804, + 730, + 960, + 323, + 152, + 202, + 449, + 238, + 907, + 532, + 618, + 377, + 295, + 625, + 252, + 383, + 345, + 46, + 934, + 908, + 851, + 304, + 235, + 623, + 808, + 363, + 80, + 373, + 858, + 839, + 385, + 426, + 727, + 615, + 675, + 860, + 602, + 623, + 780, + 246, + 22, + 681, + 623, + 293, + 421, + 908, + 419, + 811, + 631, + 155, + 139, + 861, + 262, + 789, + 344, + 507, + 14, + 445, + 995, + 316, + 74, + 32, + 239, + 932, + 586, + 167, + 578, + 555, + 8, + 720, + 804, + 18, + 185, + 637, + 185, + 21, + 121, + 993, + 457, + 0, + 911, + 330, + 214, + 343, + 600, + 720, + 645, + 542, + 991, + 704, + 261, + 481, + 242, + 949, + 909, + 745, + 799, + 644, + 858, + 132, + 886, + 194, + 886, + 695, + 912, + 980, + 956, + 51, + 885, + 410, + 88, + 578, + 636, + 698, + 636, + 532, + 579, + 389, + 124, + 386, + 54, + 616, + 203, + 838, + 732, + 152, + 775, + 749, + 373 +}; +const int ptr[1001] = { + 0, + 6, + 18, + 31, + 40, + 49, + 58, + 67, + 75, + 85, + 98, + 111, + 121, + 135, + 139, + 146, + 159, + 169, + 175, + 181, + 191, + 203, + 210, + 217, + 228, + 238, + 245, + 254, + 265, + 278, + 290, + 298, + 311, + 323, + 332, + 343, + 353, + 360, + 370, + 383, + 396, + 407, + 415, + 427, + 433, + 440, + 449, + 461, + 467, + 474, + 487, + 503, + 510, + 522, + 530, + 542, + 549, + 556, + 570, + 584, + 594, + 605, + 614, + 624, + 629, + 637, + 644, + 653, + 663, + 674, + 685, + 691, + 701, + 712, + 723, + 734, + 746, + 754, + 766, + 779, + 788, + 802, + 809, + 820, + 831, + 846, + 860, + 869, + 874, + 883, + 886, + 900, + 915, + 929, + 937, + 946, + 955, + 969, + 985, + 993, + 1004, + 1014, + 1026, + 1035, + 1040, + 1053, + 1064, + 1073, + 1078, + 1089, + 1097, + 1105, + 1108, + 1119, + 1131, + 1143, + 1156, + 1165, + 1175, + 1187, + 1196, + 1205, + 1209, + 1218, + 1230, + 1242, + 1253, + 1263, + 1277, + 1288, + 1306, + 1323, + 1331, + 1345, + 1355, + 1362, + 1372, + 1380, + 1388, + 1395, + 1412, + 1424, + 1428, + 1436, + 1443, + 1457, + 1473, + 1488, + 1498, + 1511, + 1520, + 1533, + 1543, + 1556, + 1567, + 1578, + 1590, + 1598, + 1609, + 1618, + 1627, + 1634, + 1638, + 1643, + 1649, + 1654, + 1660, + 1675, + 1688, + 1698, + 1712, + 1722, + 1730, + 1738, + 1746, + 1758, + 1765, + 1778, + 1787, + 1802, + 1814, + 1821, + 1833, + 1842, + 1851, + 1864, + 1877, + 1886, + 1890, + 1898, + 1904, + 1916, + 1931, + 1942, + 1953, + 1966, + 1975, + 1988, + 1999, + 2008, + 2021, + 2027, + 2036, + 2049, + 2058, + 2069, + 2078, + 2086, + 2099, + 2109, + 2115, + 2123, + 2133, + 2142, + 2155, + 2166, + 2175, + 2185, + 2191, + 2202, + 2215, + 2220, + 2234, + 2248, + 2260, + 2271, + 2277, + 2285, + 2297, + 2310, + 2318, + 2328, + 2337, + 2352, + 2358, + 2370, + 2378, + 2391, + 2397, + 2407, + 2413, + 2425, + 2434, + 2442, + 2452, + 2462, + 2476, + 2480, + 2487, + 2500, + 2512, + 2525, + 2533, + 2545, + 2552, + 2563, + 2576, + 2585, + 2591, + 2599, + 2608, + 2619, + 2629, + 2643, + 2658, + 2664, + 2675, + 2682, + 2696, + 2705, + 2715, + 2718, + 2736, + 2746, + 2765, + 2771, + 2787, + 2793, + 2802, + 2813, + 2826, + 2837, + 2849, + 2863, + 2870, + 2885, + 2895, + 2904, + 2914, + 2925, + 2931, + 2944, + 2949, + 2957, + 2973, + 2982, + 2995, + 3009, + 3025, + 3031, + 3046, + 3061, + 3069, + 3082, + 3089, + 3100, + 3106, + 3116, + 3119, + 3123, + 3130, + 3136, + 3144, + 3153, + 3162, + 3180, + 3185, + 3200, + 3205, + 3215, + 3225, + 3234, + 3246, + 3255, + 3266, + 3273, + 3283, + 3293, + 3303, + 3312, + 3320, + 3331, + 3342, + 3349, + 3357, + 3367, + 3372, + 3380, + 3387, + 3398, + 3405, + 3417, + 3425, + 3432, + 3443, + 3449, + 3456, + 3461, + 3471, + 3480, + 3491, + 3498, + 3521, + 3530, + 3539, + 3554, + 3562, + 3569, + 3579, + 3585, + 3597, + 3604, + 3613, + 3628, + 3646, + 3657, + 3673, + 3681, + 3691, + 3696, + 3709, + 3717, + 3731, + 3745, + 3756, + 3763, + 3769, + 3774, + 3786, + 3799, + 3810, + 3819, + 3827, + 3838, + 3854, + 3867, + 3876, + 3885, + 3902, + 3911, + 3926, + 3936, + 3948, + 3959, + 3970, + 3983, + 3991, + 4002, + 4009, + 4023, + 4032, + 4043, + 4058, + 4065, + 4078, + 4087, + 4099, + 4106, + 4114, + 4120, + 4132, + 4146, + 4155, + 4168, + 4177, + 4189, + 4199, + 4212, + 4219, + 4231, + 4241, + 4253, + 4260, + 4266, + 4278, + 4287, + 4303, + 4310, + 4322, + 4334, + 4344, + 4354, + 4368, + 4376, + 4383, + 4399, + 4408, + 4416, + 4431, + 4444, + 4458, + 4467, + 4474, + 4486, + 4495, + 4506, + 4515, + 4521, + 4536, + 4549, + 4564, + 4571, + 4580, + 4593, + 4602, + 4613, + 4618, + 4627, + 4635, + 4644, + 4659, + 4664, + 4675, + 4684, + 4690, + 4702, + 4713, + 4723, + 4735, + 4743, + 4751, + 4759, + 4768, + 4779, + 4790, + 4799, + 4811, + 4818, + 4823, + 4830, + 4838, + 4850, + 4861, + 4870, + 4878, + 4890, + 4897, + 4908, + 4916, + 4930, + 4939, + 4950, + 4959, + 4971, + 4977, + 4985, + 4996, + 4999, + 5003, + 5012, + 5018, + 5026, + 5041, + 5048, + 5058, + 5071, + 5081, + 5086, + 5094, + 5099, + 5109, + 5114, + 5127, + 5137, + 5147, + 5162, + 5172, + 5179, + 5187, + 5197, + 5209, + 5226, + 5231, + 5239, + 5248, + 5263, + 5270, + 5283, + 5293, + 5301, + 5308, + 5318, + 5327, + 5342, + 5349, + 5357, + 5367, + 5374, + 5381, + 5395, + 5406, + 5418, + 5428, + 5435, + 5440, + 5452, + 5464, + 5477, + 5490, + 5497, + 5504, + 5510, + 5518, + 5529, + 5542, + 5561, + 5579, + 5588, + 5599, + 5601, + 5609, + 5618, + 5627, + 5631, + 5640, + 5646, + 5654, + 5661, + 5672, + 5690, + 5699, + 5712, + 5723, + 5733, + 5742, + 5752, + 5759, + 5766, + 5776, + 5788, + 5799, + 5801, + 5813, + 5825, + 5829, + 5841, + 5846, + 5858, + 5867, + 5878, + 5892, + 5902, + 5910, + 5921, + 5933, + 5941, + 5957, + 5964, + 5975, + 5988, + 6000, + 6007, + 6019, + 6027, + 6036, + 6046, + 6055, + 6065, + 6080, + 6090, + 6098, + 6110, + 6122, + 6139, + 6151, + 6160, + 6168, + 6181, + 6190, + 6202, + 6209, + 6221, + 6228, + 6238, + 6249, + 6260, + 6266, + 6274, + 6289, + 6302, + 6310, + 6325, + 6334, + 6349, + 6367, + 6370, + 6382, + 6391, + 6399, + 6414, + 6423, + 6435, + 6442, + 6452, + 6461, + 6469, + 6479, + 6493, + 6502, + 6517, + 6524, + 6539, + 6549, + 6555, + 6561, + 6568, + 6575, + 6594, + 6605, + 6613, + 6620, + 6626, + 6637, + 6643, + 6656, + 6669, + 6679, + 6687, + 6698, + 6706, + 6715, + 6730, + 6739, + 6746, + 6762, + 6768, + 6776, + 6785, + 6791, + 6798, + 6805, + 6818, + 6827, + 6836, + 6846, + 6853, + 6861, + 6877, + 6885, + 6894, + 6901, + 6912, + 6924, + 6937, + 6947, + 6951, + 6966, + 6975, + 6985, + 6996, + 7003, + 7019, + 7029, + 7037, + 7046, + 7053, + 7060, + 7068, + 7075, + 7081, + 7088, + 7094, + 7108, + 7117, + 7123, + 7139, + 7150, + 7162, + 7168, + 7182, + 7191, + 7203, + 7219, + 7222, + 7229, + 7243, + 7251, + 7260, + 7269, + 7279, + 7289, + 7294, + 7307, + 7321, + 7338, + 7349, + 7353, + 7361, + 7371, + 7379, + 7386, + 7397, + 7411, + 7422, + 7428, + 7437, + 7442, + 7452, + 7463, + 7474, + 7483, + 7491, + 7499, + 7514, + 7523, + 7536, + 7542, + 7549, + 7556, + 7568, + 7577, + 7586, + 7597, + 7609, + 7623, + 7633, + 7645, + 7658, + 7664, + 7677, + 7694, + 7703, + 7718, + 7727, + 7736, + 7749, + 7758, + 7768, + 7775, + 7782, + 7790, + 7803, + 7812, + 7823, + 7833, + 7842, + 7859, + 7870, + 7879, + 7891, + 7901, + 7912, + 7921, + 7928, + 7935, + 7943, + 7958, + 7965, + 7972, + 7984, + 7991, + 7997, + 8010, + 8020, + 8033, + 8041, + 8048, + 8059, + 8069, + 8080, + 8088, + 8097, + 8108, + 8113, + 8119, + 8128, + 8135, + 8148, + 8163, + 8172, + 8182, + 8194, + 8203, + 8214, + 8223, + 8237, + 8246, + 8252, + 8264, + 8269, + 8282, + 8293, + 8305, + 8317, + 8330, + 8336, + 8347, + 8354, + 8364, + 8376, + 8383, + 8398, + 8406, + 8414, + 8429, + 8443, + 8460, + 8467, + 8475, + 8484, + 8493, + 8503, + 8510, + 8518, + 8527, + 8535, + 8544, + 8548, + 8555, + 8561, + 8571, + 8578, + 8590, + 8599, + 8603, + 8614, + 8621, + 8628, + 8638, + 8644, + 8654, + 8664, + 8675, + 8688, + 8698, + 8705, + 8711, + 8721, + 8729, + 8739, + 8754, + 8770, + 8775, + 8792, + 8802, + 8812, + 8824, + 8829, + 8838, + 8847, + 8858, + 8869, + 8878, + 8889, + 8906, + 8911, + 8916, + 8928, + 8939, + 8950, + 8957, + 8969, + 8980, + 8988, + 8992, + 9005, + 9014, + 9024, + 9032, + 9048, + 9060, + 9069, + 9079, + 9086, + 9098, + 9112, + 9123, + 9135, + 9143, + 9152, + 9163, + 9168, + 9176, + 9184, + 9193, + 9203, + 9214, + 9229, + 9239, + 9252, + 9260, + 9272, + 9283, + 9290, + 9299, + 9313, + 9329, + 9335, + 9348, + 9359, + 9370, + 9375, + 9384, + 9395, + 9402, + 9410, + 9429, + 9440, + 9454, + 9468, + 9479, + 9489, + 9497, + 9507, + 9518, + 9530, + 9538, + 9549, + 9560, + 9570, + 9581, + 9590, + 9600, + 9613, + 9624, + 9637, + 9654, + 9664, + 9675, + 9686, + 9697, + 9714, + 9724, + 9737, + 9754, + 9767, + 9776, + 9781, + 9791, + 9804, + 9809, + 9823, + 9833, + 9841, + 9848, + 9856, + 9867, + 9879, + 9892, + 9902, + 9907, + 9916, + 9925, + 9934, + 9944, + 9959, + 9972, + 9980, + 9986, + 9992, + 10004 +}; +const double verify_data[1000] = { + 1971101, + 3601995, + 3608374, + 3068439, + 2756891, + 1644445, + 2326970, + 3571797, + 2167311, + 3272467, + 5257490, + 2287052, + 5507394, + 1707471, + 1181529, + 2596954, + 2999820, + 1456597, + 1755714, + 2783599, + 2224880, + 953747, + 1863442, + 2375479, + 3838149, + 1472958, + 2613759, + 1412651, + 2454897, + 4139599, + 1540527, + 2373885, + 2371153, + 2496043, + 2946006, + 3041837, + 2102841, + 3413598, + 3937131, + 3428786, + 2323528, + 1657458, + 3358521, + 1821261, + 937257, + 2638848, + 3351703, + 2436591, + 1387045, + 3372777, + 4422352, + 2696491, + 2775768, + 1711500, + 2463910, + 1906176, + 2655972, + 2176802, + 4025605, + 1836921, + 2902963, + 1950818, + 2553243, + 2012524, + 2449182, + 1632320, + 2628093, + 1093587, + 3089207, + 3020390, + 1485696, + 1932818, + 3334949, + 1610563, + 2076427, + 3114683, + 1548840, + 3339439, + 3335032, + 1366398, + 1685659, + 1668385, + 2510712, + 2871270, + 3270369, + 4311377, + 1982006, + 1326681, + 1381634, + 398901, + 3333661, + 3352243, + 2878790, + 1577319, + 2415255, + 1191188, + 3219765, + 3467850, + 1940862, + 2056258, + 1786527, + 2278347, + 2077897, + 1457888, + 3707208, + 1405999, + 952210, + 1600564, + 2343319, + 1781556, + 2474389, + 522450, + 3674982, + 3619187, + 3211390, + 3586103, + 1475431, + 3546147, + 3698208, + 2049193, + 1979189, + 1111515, + 2790498, + 3439083, + 4279066, + 2774436, + 2077245, + 4390617, + 3149593, + 5326535, + 3848199, + 2772446, + 2682304, + 2277814, + 1222790, + 2067874, + 1982666, + 2371257, + 1270393, + 3228410, + 2598823, + 2428645, + 904561, + 2100006, + 2337148, + 3164102, + 3908197, + 1529402, + 3084375, + 1927419, + 3196639, + 2303890, + 4265937, + 2061281, + 2212135, + 2407656, + 1723976, + 2903704, + 3276733, + 1491735, + 1684162, + 1307018, + 1201185, + 636997, + 1186016, + 1774809, + 2607471, + 2619840, + 3493545, + 3226129, + 1737347, + 2380184, + 1201957, + 983240, + 2529069, + 2689857, + 3022018, + 2223714, + 3625235, + 3008732, + 2417998, + 4428750, + 2270952, + 2186948, + 4812008, + 2233927, + 3334976, + 1264519, + 1626345, + 1123879, + 3098605, + 4036407, + 3104973, + 2897790, + 3788865, + 2422217, + 3611590, + 1749696, + 2447434, + 2977777, + 1573650, + 2620107, + 2319242, + 2902283, + 1882200, + 1787017, + 2436605, + 3467551, + 2413830, + 187567, + 2242075, + 1754385, + 1836061, + 4245412, + 3751015, + 2715151, + 1557751, + 421948, + 2963355, + 2050843, + 1758567, + 2680768, + 4076059, + 4484640, + 3293151, + 1433126, + 1649435, + 4409656, + 2223098, + 2455979, + 1874200, + 2098066, + 4020158, + 1312572, + 2801068, + 3341899, + 3785087, + 1569098, + 2778159, + 1992179, + 2669866, + 1914494, + 1619868, + 2274333, + 1857912, + 3099797, + 809499, + 1679713, + 3531350, + 2599926, + 1970143, + 2920228, + 2883295, + 1394658, + 3554897, + 3534392, + 1625041, + 1492274, + 1451033, + 2248274, + 2910569, + 2341827, + 2768016, + 3567361, + 781606, + 2434644, + 1782504, + 4124675, + 3646132, + 2864945, + 512560, + 3618571, + 2223074, + 4315721, + 1195043, + 4737421, + 1748427, + 3474050, + 1798506, + 4916152, + 2411793, + 3382242, + 5132409, + 810557, + 4870878, + 1368859, + 2955757, + 1940419, + 3146202, + 880792, + 3448573, + 1017493, + 2481321, + 3652309, + 3475252, + 2845994, + 3182841, + 5898263, + 1771223, + 3346757, + 2512678, + 1778448, + 3432671, + 2814247, + 3403195, + 812303, + 2104162, + 85040, + 989115, + 1897384, + 1248980, + 2002961, + 1371732, + 2373820, + 5178478, + 1511192, + 5127654, + 1468260, + 2185303, + 2436412, + 2978141, + 2230665, + 1707852, + 2529167, + 1152196, + 3239187, + 2498749, + 2707774, + 1502699, + 1633289, + 2782744, + 4089832, + 1548833, + 1704769, + 2712629, + 992084, + 1369606, + 2480517, + 2846051, + 3100172, + 2371224, + 1173652, + 1837754, + 3822172, + 1417367, + 1538908, + 1146694, + 2528965, + 2800885, + 3461160, + 786155, + 6573509, + 3071638, + 1511640, + 3652853, + 1475533, + 1525596, + 2695806, + 1277883, + 3278333, + 2226936, + 2030339, + 3914645, + 4318373, + 2059669, + 3961569, + 1772074, + 3135802, + 1261862, + 4771438, + 1587528, + 2435428, + 2869031, + 2629400, + 1533986, + 1866116, + 1203541, + 2007311, + 4295134, + 3082652, + 2127515, + 3110833, + 2895900, + 4701588, + 2727753, + 2324739, + 2142817, + 4359375, + 2762710, + 2675084, + 2776056, + 2906201, + 2859945, + 1471060, + 3224362, + 2455374, + 2030195, + 909337, + 2716237, + 2230075, + 3070171, + 4476596, + 2646370, + 3421732, + 2163616, + 4043766, + 2111374, + 2016619, + 1318843, + 3586217, + 3000490, + 2914687, + 2728187, + 3496083, + 3137438, + 1555757, + 2975780, + 864871, + 3568793, + 3273559, + 4362169, + 1225951, + 1858409, + 1867854, + 2081582, + 4028493, + 1772236, + 2634979, + 3563733, + 1734270, + 2430471, + 3597625, + 1010411, + 1086456, + 3717761, + 3038402, + 1630224, + 4565438, + 3347069, + 2543316, + 3034145, + 1190307, + 3710367, + 2894919, + 4122408, + 1917891, + 1308296, + 1847812, + 2799933, + 5544619, + 990734, + 2302389, + 2828494, + 2767749, + 2734181, + 1584801, + 2096227, + 2132396, + 1605917, + 3953389, + 489065, + 3370917, + 1246610, + 1859633, + 3905768, + 2375583, + 2352791, + 3066605, + 3023804, + 1714567, + 1630198, + 3244096, + 3311209, + 2837076, + 1806523, + 3111912, + 924345, + 891749, + 1710635, + 2779972, + 2288984, + 2104226, + 2726511, + 2994247, + 4159385, + 927922, + 3372483, + 2093351, + 3228595, + 1549615, + 3203118, + 1566786, + 2046013, + 1122663, + 902592, + 2101848, + 633763, + 1382735, + 2235887, + 1595380, + 1684910, + 4534882, + 1927642, + 3881319, + 4091228, + 3489550, + 1186206, + 1089968, + 1673520, + 2908231, + 1060251, + 4422500, + 2814892, + 2014163, + 3954105, + 2685902, + 1427353, + 1040905, + 2481509, + 2984177, + 5050926, + 1266027, + 2158372, + 2317752, + 4020554, + 1226253, + 3034218, + 3335936, + 3282626, + 1782262, + 3007006, + 2399815, + 4116453, + 1101525, + 2175742, + 1919181, + 1935647, + 3021439, + 2975812, + 1409385, + 3435714, + 2843659, + 2535310, + 973352, + 4051148, + 3198667, + 3025227, + 3821291, + 2634495, + 1066026, + 1015860, + 2374721, + 1893315, + 2896157, + 5768610, + 4638503, + 1096525, + 2521763, + 201516, + 1885950, + 2456554, + 2395576, + 1805310, + 3539192, + 706652, + 3652867, + 1803915, + 2740108, + 4902727, + 2480670, + 4763486, + 2831231, + 2804267, + 2958655, + 1180330, + 1377988, + 1967048, + 3251495, + 3641699, + 2327118, + 518996, + 3627226, + 4512513, + 821503, + 4513458, + 1746977, + 3396668, + 2072470, + 3064446, + 4435618, + 2734309, + 2193304, + 4275484, + 3468741, + 2498396, + 3068739, + 1699359, + 2816909, + 2705770, + 2392503, + 1288021, + 2667346, + 1722567, + 2924017, + 3160472, + 1098169, + 3756129, + 5913618, + 3768712, + 2089078, + 2340072, + 2483109, + 4368798, + 2778403, + 1706517, + 2503001, + 2633764, + 2488649, + 3759253, + 1596753, + 1671868, + 1377167, + 2721074, + 2026518, + 3148597, + 1753515, + 2407030, + 3191030, + 3974792, + 1798541, + 4805468, + 2569249, + 4324091, + 3385093, + 745588, + 2231981, + 2000465, + 2339460, + 3327609, + 3719613, + 4276833, + 1018769, + 2495582, + 2942706, + 2035953, + 2227503, + 3631249, + 2988856, + 2784977, + 1822310, + 4621193, + 2352625, + 1249877, + 1540945, + 1241921, + 1994350, + 5628798, + 1620488, + 1897543, + 952310, + 1052254, + 3358187, + 2994928, + 2959189, + 2720309, + 2875425, + 2144130, + 4548462, + 2048162, + 1339841, + 4090958, + 1862715, + 1268274, + 4042390, + 1581631, + 2874452, + 1735445, + 1588799, + 1331885, + 2179684, + 5179645, + 1959366, + 2027198, + 2755029, + 2265692, + 2335785, + 4348426, + 1879924, + 2696539, + 1106357, + 2932568, + 2492358, + 3120132, + 3691105, + 1442767, + 4534420, + 2112951, + 2625910, + 3375099, + 1555111, + 4988419, + 1174798, + 1332818, + 1869705, + 1696774, + 1175511, + 1819161, + 1548388, + 1420761, + 1580164, + 943541, + 4405558, + 2240390, + 1501984, + 4062955, + 3082580, + 2967491, + 1152855, + 3788527, + 2868984, + 4078134, + 3701904, + 752170, + 1758523, + 3256074, + 2335111, + 2496969, + 2165110, + 2589055, + 1648006, + 966763, + 3719559, + 4883836, + 2489406, + 2900336, + 1003207, + 914713, + 2687415, + 2957174, + 991602, + 3005713, + 3016805, + 3646583, + 2002778, + 2188117, + 996416, + 3940661, + 3749144, + 1702093, + 1779575, + 2135189, + 1198463, + 1665170, + 1230802, + 3071243, + 1250575, + 1159769, + 2008716, + 2577482, + 1680782, + 2755046, + 2798673, + 2779172, + 4719731, + 2451896, + 2268516, + 3364116, + 2139930, + 4014502, + 5474835, + 2379560, + 3272928, + 2133308, + 2638465, + 3610736, + 2437161, + 2469816, + 1951246, + 1998282, + 2022421, + 2093450, + 2415039, + 4011191, + 2829334, + 2863331, + 4093600, + 2661113, + 2923200, + 2198013, + 2162835, + 2958211, + 1829311, + 750764, + 1125263, + 1293794, + 4883789, + 1165273, + 1322292, + 2045605, + 1796576, + 1587215, + 3595048, + 2442957, + 3675117, + 2022610, + 2207877, + 3164247, + 2539827, + 2289433, + 2050621, + 2033111, + 2996013, + 643859, + 1353849, + 2284477, + 1687120, + 2374034, + 3975861, + 3174103, + 3090405, + 3004853, + 1655110, + 2881453, + 3229992, + 3406893, + 1953384, + 2162162, + 3005248, + 1806960, + 2262637, + 2658934, + 3172203, + 2346601, + 2083857, + 1905139, + 2243485, + 1779413, + 2958736, + 2324181, + 1167937, + 2487352, + 2195558, + 2511598, + 3374057, + 3239559, + 3989322, + 2007874, + 1142953, + 1917363, + 1413284, + 2254989, + 2519517, + 2612721, + 1979898, + 1472130, + 4246577, + 678823, + 1032892, + 1956684, + 2963972, + 2501714, + 3206467, + 3867577, + 1866296, + 1852756, + 2674353, + 2068891, + 2485623, + 1691978, + 3224678, + 2235530, + 2642436, + 3528805, + 3154289, + 763332, + 2188687, + 2175236, + 3423181, + 2228774, + 4926897, + 4720293, + 1365097, + 4384144, + 1933318, + 1538742, + 3060760, + 891455, + 2247727, + 1481978, + 2009726, + 3389542, + 737932, + 4035426, + 4661761, + 1332633, + 913928, + 2479290, + 1992229, + 2961682, + 1641167, + 3217414, + 3225260, + 2595246, + 591918, + 5566353, + 2528672, + 2502651, + 1241588, + 2590376, + 3876970, + 1793155, + 1501528, + 1838442, + 2522918, + 2422260, + 3056321, + 2273838, + 2071241, + 1658722, + 2562266, + 1338349, + 1376886, + 2223907, + 1921712, + 2211260, + 1602704, + 5260200, + 2189077, + 3019251, + 2106858, + 3976347, + 2463524, + 1576729, + 491605, + 3168168, + 4672180, + 1922298, + 2396219, + 2857066, + 3012596, + 874988, + 2600192, + 2197450, + 1567978, + 1636166, + 4334187, + 2964752, + 4434709, + 2753079, + 2384760, + 1534463, + 2112708, + 2065799, + 1431116, + 3960134, + 2861238, + 2406750, + 2744852, + 2940188, + 3343790, + 2451949, + 2431427, + 2343771, + 4247520, + 2386347, + 5806313, + 2995484, + 3520605, + 1723394, + 2278390, + 4240678, + 1794433, + 3515379, + 4577968, + 2412014, + 1533701, + 733354, + 2879952, + 4102595, + 1847856, + 1920316, + 2281251, + 1136467, + 2032967, + 2387741, + 2059754, + 3098458, + 2813846, + 2264943, + 1328950, + 1544527, + 1143015, + 2417418, + 2816076, + 4485204, + 2576250, + 2144794, + 1827914, + 1906691, + 2348923 +}; diff --git a/benchmarks/spmv/spmv_gendata.scala b/benchmarks/spmv/spmv_gendata.scala new file mode 100644 index 0000000..f777445 --- /dev/null +++ b/benchmarks/spmv/spmv_gendata.scala @@ -0,0 +1,48 @@ +#!/usr/bin/env scala +!# + +val m = args(0).toInt +val n = args(1).toInt +val approx_nnz = args(2).toInt + +val pnnz = approx_nnz.toDouble/(m*n) +val idx = collection.mutable.ArrayBuffer[Int]() +val p = collection.mutable.ArrayBuffer(0) + +for (i <- 0 until m) { + for (j <- 0 until n) { + if (util.Random.nextDouble < pnnz) + idx += j + } + p += idx.length +} + +val nnz = idx.length +val v = Array.tabulate(n)(i => util.Random.nextInt(1000)) +val d = Array.tabulate(nnz)(i => util.Random.nextInt(1000)) + +def printVec(t: String, name: String, data: Seq[Int]) = { + println("const " + t + " " + name + "[" + data.length + "] = {") + println(" "+data.map(_.toString).reduceLeft(_+",\n "+_)) + println("};") +} + +def spmv(p: Seq[Int], d: Seq[Int], idx: Seq[Int], v: Seq[Int]) = { + val y = collection.mutable.ArrayBuffer[Int]() + for (i <- 0 until p.length-1) { + var yi = 0 + for (k <- p(i) until p(i+1)) + yi = yi + d(k)*v(idx(k)) + y += yi + } + y +} + +println("#define R " + m) +println("#define C " + n) +println("#define NNZ " + nnz) +printVec("double", "val", d) +printVec("int", "idx", idx) +printVec("double", "x", v) +printVec("int", "ptr", p) +printVec("double", "verify_data", spmv(p, d, idx, v)) diff --git a/benchmarks/spmv/spmv_main.c b/benchmarks/spmv/spmv_main.c new file mode 100644 index 0000000..11d9540 --- /dev/null +++ b/benchmarks/spmv/spmv_main.c @@ -0,0 +1,123 @@ +//************************************************************************** +// Double-precision general matrix multiplication benchmark +//-------------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +//-------------------------------------------------------------------------- +// Input/Reference Data + +#include "dataset1.h" + +//-------------------------------------------------------------------------- +// Helper functions + +int verify( long n, const double test[], const double correct[] ) +{ + int i; + for ( i = 0; i < n; i++ ) { + if ( test[i] != correct[i] ) { + return 2; + } + } + return 1; +} + +#if HOST_DEBUG +#include +#include +void printArray( char name[], long n, const double arr[] ) +{ + int i; + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " %8.1f ", arr[i] ); + printf( "\n" ); +} +#endif + +void finishTest( int toHostValue ) +{ +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + asm( "mtpcr %0, cr30" : : "r" (toHostValue) ); + while ( 1 ) { } +#endif +} + +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +void spmv(int r, const double* val, const int* idx, const double* x, + const int* ptr, double* y) +{ + for (int i = 0; i < r; i++) + { + int k; + double yi0 = 0, yi1 = 0, yi2 = 0, yi3 = 0; + for (k = ptr[i]; k < ptr[i+1]-3; k+=4) + { + yi0 += val[k+0]*x[idx[k+0]]; + yi1 += val[k+1]*x[idx[k+1]]; + yi2 += val[k+2]*x[idx[k+2]]; + yi3 += val[k+3]*x[idx[k+3]]; + } + for ( ; k < ptr[i+1]; k++) + { + yi0 += val[k]*x[idx[k]]; + } + y[i] = (yi0+yi1)+(yi2+yi3); + } +} + +//-------------------------------------------------------------------------- +// Main + +int main( int argc, char* argv[] ) +{ + double y[R]; + +#if PREALLOCATE + spmv(R, val, idx, x, ptr, y); +#endif + + setStats(1); + spmv(R, val, idx, x, ptr, y); + setStats(0); + + finishTest(verify(R, y, verify_data)); +} diff --git a/benchmarks/towers/bmark.mk b/benchmarks/towers/bmark.mk new file mode 100644 index 0000000..0c16a81 --- /dev/null +++ b/benchmarks/towers/bmark.mk @@ -0,0 +1,29 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +towers_c_src = \ + towers_main.c \ + +towers_riscv_src = \ + crt.S \ + +towers_c_objs = $(patsubst %.c, %.o, $(towers_c_src)) +towers_riscv_objs = $(patsubst %.S, %.o, $(towers_riscv_src)) + +towers_host_bin = towers.host +$(towers_host_bin) : $(towers_c_src) + $(HOST_COMP) $^ -o $(towers_host_bin) + +towers_riscv_bin = towers.riscv +$(towers_riscv_bin) : $(towers_c_objs) $(towers_riscv_objs) + $(RISCV_LINK) $(towers_c_objs) $(towers_riscv_objs) -o $(towers_riscv_bin) + +junk += $(towers_c_objs) $(towers_riscv_objs) \ + $(towers_host_bin) $(towers_riscv_bin) diff --git a/benchmarks/towers/towers_main.c b/benchmarks/towers/towers_main.c new file mode 100644 index 0000000..36526a2 --- /dev/null +++ b/benchmarks/towers/towers_main.c @@ -0,0 +1,341 @@ +//************************************************************************** +// Towers of Hanoi benchmark +//-------------------------------------------------------------------------- +// +// Towers of Hanoi is a classic puzzle problem. The game consists of +// three pegs and a set of discs. Each disc is a different size, and +// initially all of the discs are on the left most peg with the smallest +// disc on top and the largest disc on the bottom. The goal is to move all +// of the discs onto the right most peg. The catch is that you are only +// allowed to move one disc at a time and you can never place a larger +// disc on top of a smaller disc. +// +// This implementation starts with NUM_DISC discs and uses a recursive +// algorithm to sovel the puzzle. The smips-gcc toolchain does not support +// system calls so printf's can only be used on a host system, not on the +// smips processor simulator itself. You should not change anything except +// the HOST_DEBUG and PREALLOCATE macros for your timing run. + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +// This is the number of discs in the puzzle. + +#define NUM_DISCS 7 + +//-------------------------------------------------------------------------- +// Helper functions + +void finishTest( int toHostValue ) +{ +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + asm( "mtpcr %0, cr30" : : "r" (toHostValue) ); + while ( 1 ) { } +#endif +} + +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +//-------------------------------------------------------------------------- +// List data structure and functions + +struct Node +{ + int val; + struct Node* next; +}; + +struct List +{ + int size; + struct Node* head; +}; + +struct List g_nodeFreeList; +struct Node g_nodePool[NUM_DISCS]; + +int list_getSize( struct List* list ) +{ + return list->size; +} + +void list_init( struct List* list ) +{ + list->size = 0; + list->head = 0; +} + +void list_push( struct List* list, int val ) +{ + struct Node* newNode; + + // Pop the next free node off the free list + newNode = g_nodeFreeList.head; + g_nodeFreeList.head = g_nodeFreeList.head->next; + + // Push the new node onto the given list + newNode->next = list->head; + list->head = newNode; + + // Assign the value + list->head->val = val; + + // Increment size + list->size++; + +} + +int list_pop( struct List* list ) +{ + struct Node* freedNode; + int val; + + // Get the value from the->head of given list + val = list->head->val; + + // Pop the head node off the given list + freedNode = list->head; + list->head = list->head->next; + + // Push the freed node onto the free list + freedNode->next = g_nodeFreeList.head; + g_nodeFreeList.head = freedNode; + + // Decrement size + list->size--; + + return val; +} + +void list_clear( struct List* list ) +{ + while ( list_getSize(list) > 0 ) + list_pop(list); +} + +//-------------------------------------------------------------------------- +// Tower data structure and functions + +struct Towers +{ + int numDiscs; + int numMoves; + struct List pegA; + struct List pegB; + struct List pegC; +}; + +void towers_init( struct Towers* this, int n ) +{ + int i; + + this->numDiscs = n; + this->numMoves = 0; + + list_init( &(this->pegA) ); + list_init( &(this->pegB) ); + list_init( &(this->pegC) ); + + for ( i = 0; i < n; i++ ) + list_push( &(this->pegA), n-i ); + +} + +void towers_clear( struct Towers* this ) +{ + + list_clear( &(this->pegA) ); + list_clear( &(this->pegB) ); + list_clear( &(this->pegC) ); + + towers_init( this, this->numDiscs ); + +} + +#if HOST_DEBUG +void towers_print( struct Towers* this ) +{ + struct Node* ptr; + int i, numElements; + + printf( " pegA: " ); + for ( i = 0; i < ((this->numDiscs)-list_getSize(&(this->pegA))); i++ ) + printf( ". " ); + for ( ptr = this->pegA.head; ptr != 0; ptr = ptr->next ) + printf( "%d ", ptr->val ); + + printf( " pegB: " ); + for ( i = 0; i < ((this->numDiscs)-list_getSize(&(this->pegB))); i++ ) + printf( ". " ); + for ( ptr = this->pegB.head; ptr != 0; ptr = ptr->next ) + printf( "%d ", ptr->val ); + + printf( " pegC: " ); + for ( i = 0; i < ((this->numDiscs)-list_getSize(&(this->pegC))); i++ ) + printf( ". " ); + for ( ptr = this->pegC.head; ptr != 0; ptr = ptr->next ) + printf( "%d ", ptr->val ); + + printf( "\n" ); +} +#endif + +void towers_solve_h( struct Towers* this, int n, + struct List* startPeg, + struct List* tempPeg, + struct List* destPeg ) +{ + int val; + + if ( n == 1 ) { +#if HOST_DEBUG + towers_print(this); +#endif + val = list_pop(startPeg); + list_push(destPeg,val); + this->numMoves++; + } + else { + towers_solve_h( this, n-1, startPeg, destPeg, tempPeg ); + towers_solve_h( this, 1, startPeg, tempPeg, destPeg ); + towers_solve_h( this, n-1, tempPeg, startPeg, destPeg ); + } + +} + +void towers_solve( struct Towers* this ) +{ + towers_solve_h( this, this->numDiscs, &(this->pegA), &(this->pegB), &(this->pegC) ); +} + +int towers_verify( struct Towers* this ) +{ + struct Node* ptr; + int numDiscs = 0; + + if ( list_getSize(&this->pegA) != 0 ) { +#if HOST_DEBUG + printf( "ERROR: Peg A is not empty!\n" ); +#endif + return 2; + } + + if ( list_getSize(&this->pegB) != 0 ) { +#if HOST_DEBUG + printf( "ERROR: Peg B is not empty!\n" ); +#endif + return 3; + } + + if ( list_getSize(&this->pegC) != this->numDiscs ) { +#if HOST_DEBUG + printf( " ERROR: Expected %d discs but found only %d discs!\n", \ + this->numDiscs, list_getSize(&this->pegC) ); +#endif + return 4; + } + + for ( ptr = this->pegC.head; ptr != 0; ptr = ptr->next ) { + numDiscs++; + if ( ptr->val != numDiscs ) { +#if HOST_DEBUG + printf( " ERROR: Expecting disc %d on peg C but found disc %d instead!\n", \ + numDiscs, ptr->val ); +#endif + return 5; + } + } + + if ( this->numMoves != ((1 << this->numDiscs) - 1) ) { +#if HOST_DEBUG + printf( " ERROR: Expecting %d num moves but found %d instead!\n", \ + ((1 << this->numDiscs) - 1), this->numMoves ); +#endif + return 6; + } + + return 1; +} + +//-------------------------------------------------------------------------- +// Main + +int main( int argc, char* argv[] ) +{ + struct Towers towers; + int i; + + // Initialize free list + + list_init( &g_nodeFreeList ); + g_nodeFreeList.head = &(g_nodePool[0]); + g_nodeFreeList.size = NUM_DISCS; + g_nodePool[NUM_DISCS-1].next = 0; + g_nodePool[NUM_DISCS-1].val = 99; + for ( i = 0; i < (NUM_DISCS-1); i++ ) { + g_nodePool[i].next = &(g_nodePool[i+1]); + g_nodePool[i].val = i; + } + + towers_init( &towers, NUM_DISCS ); + + // If needed we preallocate everything in the caches + +#if PREALLOCATE + towers_solve( &towers ); +#endif + + // Solve it + + towers_clear( &towers ); + setStats(1); + towers_solve( &towers ); + setStats(0); + + // Print out the results + +#if HOST_DEBUG + towers_print( &towers ); +#endif + + // Check the results + + finishTest( towers_verify( &towers ) ); + +} + diff --git a/benchmarks/vec-cmplxmult/bmark.mk b/benchmarks/vec-cmplxmult/bmark.mk new file mode 100644 index 0000000..ae93506 --- /dev/null +++ b/benchmarks/vec-cmplxmult/bmark.mk @@ -0,0 +1,30 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +vec_cmplxmult_c_src = \ + vec_cmplxmult_main.c \ + +vec_cmplxmult_riscv_src = \ + crt.S \ + vec_cmplxmult_asm.S + +vec_cmplxmult_c_objs = $(patsubst %.c, %.o, $(vec_cmplxmult_c_src)) +vec_cmplxmult_riscv_objs = $(patsubst %.S, %.o, $(vec_cmplxmult_riscv_src)) + +vec_cmplxmult_host_bin = vec-cmplxmult.host +$(vec_cmplxmult_host_bin) : $(vec_cmplxmult_c_src) + $(HOST_COMP) $^ -o $(vec_cmplxmult_host_bin) + +vec_cmplxmult_riscv_bin = vec-cmplxmult.riscv +$(vec_cmplxmult_riscv_bin) : $(vec_cmplxmult_c_objs) $(vec_cmplxmult_riscv_objs) + $(RISCV_LINK) $(RISCV_LINK_SYSCALL) $(vec_cmplxmult_c_objs) $(vec_cmplxmult_riscv_objs) -o $(vec_cmplxmult_riscv_bin) + +junk += $(vec_cmplxmult_c_objs) $(vec_cmplxmult_riscv_objs) \ + $(vec_cmplxmult_host_bin) $(vec_cmplxmult_riscv_bin) diff --git a/benchmarks/vec-cmplxmult/cmplxmult_gendata.pl b/benchmarks/vec-cmplxmult/cmplxmult_gendata.pl new file mode 100755 index 0000000..07881b8 --- /dev/null +++ b/benchmarks/vec-cmplxmult/cmplxmult_gendata.pl @@ -0,0 +1,117 @@ +#!/usr/bin/perl -w +#========================================================================== +# vvadd_gendata.pl +# +# Author : Christopher Batten (cbatten@mit.edu) +# Date : April 29, 2005 +# +(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm; +# +# Simple script which creates an input data set and the reference data +# for the vvadd benchmark. +# +ENDMSG + +use strict "vars"; +use warnings; +no warnings("once"); +use Getopt::Long; + +#-------------------------------------------------------------------------- +# Command line processing +#-------------------------------------------------------------------------- + +our %opts; + +sub usage() +{ + + print "\n"; + print " Usage: vvadd_gendata.pl [options] \n"; + print "\n"; + print " Options:\n"; + print " --help print this message\n"; + print " --size size of input data [1000]\n"; + print " --seed random seed [1]\n"; + print "$usageMsg"; + + exit(); +} + +sub processCommandLine() +{ + + $opts{"help"} = 0; + $opts{"size"} = 1000; + $opts{"seed"} = 1; + Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage(); + $opts{"help"} and usage(); + +} + +#-------------------------------------------------------------------------- +# Helper Functions +#-------------------------------------------------------------------------- + +sub printArray +{ + my $arrayName = $_[0]; + my $arrayRefReal = $_[1]; + my $arrayRefImag = $_[2]; + + my $numCols = 20; + my $arrayLen = scalar(@{$arrayRefReal}); + + print "struct Complex ".$arrayName."[DATA_SIZE] = \n"; + print "{\n"; + + print " "; + for ( my $i = 0; $i < $arrayLen; $i++ ) { + print sprintf("{%3.2f, %3.2f}",$arrayRefReal->[$i], $arrayRefImag->[$i]); + if ( $i != $arrayLen-1 ) { + print ",\n "; + } + } + + print "\n};\n\n"; +} + +#-------------------------------------------------------------------------- +# Main +#-------------------------------------------------------------------------- + +sub main() +{ + + processCommandLine(); + srand($opts{"seed"}); + + my @values_real1; + my @values_imag1; + my @values_real2; + my @values_imag2; + my @product_real; + my @product_imag; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + my $value_real1 = (rand(9.0)); + my $value_imag1 = (rand(9.0)); + my $value_real2 = (rand(9.0)); + my $value_imag2 = (rand(9.0)); + push( @values_real1, $value_real1 ); + push( @values_imag1, $value_imag1 ); + push( @values_real2, $value_real2 ); + push( @values_imag2, $value_imag2 ); + push( @product_real, ($value_real1 * $value_real2) - ($value_imag1 * $value_imag2)); + push( @product_imag, ($value_imag1 * $value_real2) + ($value_real1 * $value_imag2)); + } + + + print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n"; + printArray( "input1_data", \@values_real1, \@values_imag1 ); + printArray( "input2_data", \@values_real2, \@values_imag2 ); + printArray( "verify_data", \@product_real, \@product_imag ); + +} + +main(); + diff --git a/benchmarks/vec-cmplxmult/dataset.h b/benchmarks/vec-cmplxmult/dataset.h new file mode 100644 index 0000000..1e6fa13 --- /dev/null +++ b/benchmarks/vec-cmplxmult/dataset.h @@ -0,0 +1,1551 @@ + +#define DATA_SIZE 512 + +struct Complex input1_data[DATA_SIZE] = +{ + {0.37, 4.09}, + {5.09, 0.02}, + {6.75, 3.30}, + {1.19, 0.58}, + {5.26, 1.95}, + {5.60, 1.90}, + {8.39, 3.06}, + {3.54, 8.09}, + {8.66, 0.11}, + {1.05, 6.76}, + {3.84, 4.51}, + {5.94, 6.32}, + {2.88, 8.84}, + {7.88, 6.27}, + {4.27, 2.45}, + {4.86, 5.83}, + {1.83, 0.80}, + {6.84, 6.04}, + {4.61, 4.97}, + {1.76, 5.34}, + {2.41, 8.58}, + {3.04, 5.26}, + {8.13, 3.32}, + {8.23, 2.96}, + {8.41, 5.34}, + {1.77, 4.90}, + {5.11, 8.82}, + {5.85, 7.34}, + {1.63, 1.88}, + {7.74, 5.67}, + {2.60, 6.35}, + {1.28, 2.28}, + {7.98, 3.87}, + {5.20, 4.85}, + {6.86, 0.04}, + {4.31, 0.90}, + {3.63, 6.25}, + {4.00, 2.67}, + {6.09, 5.59}, + {2.02, 3.17}, + {2.60, 5.83}, + {5.54, 4.75}, + {3.51, 7.17}, + {4.10, 6.49}, + {3.31, 6.72}, + {5.26, 8.91}, + {8.88, 7.69}, + {3.12, 4.79}, + {5.04, 4.15}, + {6.99, 3.23}, + {7.02, 6.17}, + {1.29, 4.02}, + {1.13, 6.70}, + {8.41, 4.32}, + {4.98, 8.34}, + {5.85, 3.22}, + {2.59, 6.00}, + {0.45, 5.03}, + {0.86, 7.69}, + {5.29, 0.55}, + {3.44, 3.57}, + {7.28, 0.16}, + {7.38, 2.62}, + {4.06, 4.83}, + {8.70, 8.26}, + {7.29, 8.86}, + {4.84, 0.49}, + {6.32, 8.57}, + {5.12, 1.36}, + {0.20, 5.78}, + {6.00, 6.58}, + {3.91, 6.56}, + {0.02, 3.56}, + {2.23, 8.21}, + {3.92, 7.34}, + {7.83, 2.39}, + {3.73, 2.13}, + {4.94, 1.63}, + {8.00, 4.54}, + {2.57, 1.56}, + {4.50, 3.13}, + {8.08, 0.62}, + {6.59, 5.93}, + {2.26, 1.10}, + {5.01, 7.47}, + {4.76, 3.91}, + {2.90, 6.79}, + {2.59, 5.65}, + {2.75, 0.10}, + {6.61, 0.95}, + {3.30, 7.37}, + {2.65, 3.66}, + {5.89, 7.72}, + {0.82, 0.54}, + {0.95, 6.02}, + {3.44, 1.09}, + {7.44, 3.72}, + {3.22, 0.11}, + {0.49, 8.70}, + {8.61, 5.60}, + {4.81, 8.30}, + {4.70, 5.83}, + {5.34, 7.99}, + {1.56, 0.33}, + {1.09, 4.96}, + {6.83, 8.74}, + {8.57, 3.91}, + {1.17, 2.73}, + {7.64, 7.75}, + {2.30, 4.31}, + {3.69, 6.08}, + {3.60, 8.92}, + {6.79, 4.06}, + {1.54, 1.40}, + {6.55, 4.08}, + {7.01, 4.59}, + {6.79, 3.84}, + {1.82, 4.35}, + {1.39, 3.06}, + {3.22, 0.46}, + {8.31, 5.42}, + {4.47, 8.73}, + {4.66, 7.93}, + {2.49, 7.84}, + {1.03, 5.44}, + {8.17, 8.00}, + {2.14, 3.65}, + {7.07, 6.72}, + {3.22, 2.48}, + {7.38, 2.04}, + {2.52, 8.50}, + {4.13, 6.39}, + {6.40, 0.49}, + {0.38, 0.48}, + {3.40, 0.37}, + {6.31, 3.75}, + {4.33, 1.98}, + {4.50, 6.94}, + {0.45, 4.35}, + {7.87, 6.53}, + {8.94, 1.68}, + {6.50, 0.01}, + {2.10, 2.23}, + {6.29, 3.27}, + {3.14, 2.11}, + {3.16, 0.37}, + {5.17, 1.76}, + {6.75, 6.70}, + {7.42, 3.21}, + {1.53, 1.27}, + {6.08, 2.61}, + {1.82, 2.88}, + {7.69, 1.07}, + {3.56, 0.64}, + {7.70, 3.50}, + {1.42, 0.32}, + {6.90, 6.29}, + {1.76, 6.10}, + {1.97, 7.96}, + {1.60, 6.73}, + {6.30, 4.61}, + {6.37, 3.97}, + {0.76, 6.60}, + {8.05, 6.33}, + {3.36, 0.78}, + {0.13, 1.94}, + {0.75, 5.87}, + {7.16, 3.87}, + {5.79, 0.87}, + {7.52, 5.94}, + {4.16, 4.72}, + {5.06, 5.63}, + {0.09, 6.44}, + {8.15, 0.50}, + {3.67, 2.75}, + {5.04, 8.12}, + {4.62, 6.23}, + {2.73, 4.48}, + {3.85, 8.48}, + {3.24, 4.33}, + {6.17, 7.41}, + {1.67, 6.13}, + {0.97, 1.01}, + {3.49, 1.67}, + {4.38, 6.48}, + {6.30, 6.75}, + {6.94, 7.33}, + {0.73, 2.94}, + {3.67, 0.31}, + {0.27, 8.43}, + {7.84, 0.80}, + {1.34, 3.06}, + {1.33, 4.99}, + {7.61, 8.60}, + {1.27, 3.57}, + {7.36, 2.25}, + {5.07, 7.50}, + {5.55, 3.55}, + {7.32, 4.24}, + {1.44, 3.03}, + {7.24, 2.25}, + {4.91, 4.89}, + {4.13, 5.73}, + {7.86, 5.24}, + {7.26, 6.05}, + {0.94, 3.77}, + {2.29, 8.29}, + {1.23, 6.71}, + {5.27, 1.25}, + {3.74, 8.36}, + {6.37, 4.12}, + {3.41, 1.66}, + {8.80, 1.77}, + {8.54, 3.75}, + {1.49, 8.98}, + {0.95, 6.63}, + {7.17, 7.44}, + {2.74, 0.46}, + {5.72, 4.84}, + {1.07, 2.65}, + {4.79, 0.99}, + {0.34, 7.04}, + {6.67, 3.38}, + {6.91, 8.08}, + {0.52, 0.40}, + {7.07, 7.62}, + {7.54, 0.89}, + {0.61, 4.00}, + {8.98, 1.49}, + {1.55, 0.26}, + {5.60, 2.92}, + {7.44, 3.39}, + {6.25, 8.09}, + {2.13, 1.52}, + {6.71, 1.75}, + {1.12, 8.43}, + {8.49, 7.04}, + {3.34, 5.58}, + {2.43, 8.41}, + {6.88, 7.45}, + {8.25, 8.90}, + {0.01, 5.85}, + {8.97, 0.01}, + {5.05, 3.60}, + {8.76, 7.13}, + {4.59, 8.87}, + {8.74, 5.41}, + {5.22, 6.15}, + {2.26, 8.14}, + {1.16, 8.97}, + {6.45, 5.61}, + {6.12, 8.07}, + {2.17, 7.39}, + {7.15, 2.04}, + {0.01, 2.37}, + {8.89, 2.15}, + {6.80, 5.50}, + {1.83, 2.15}, + {1.62, 7.97}, + {1.49, 0.97}, + {8.78, 7.11}, + {5.04, 0.21}, + {3.81, 8.02}, + {5.10, 0.48}, + {4.44, 1.81}, + {6.72, 3.68}, + {3.36, 5.82}, + {5.99, 0.74}, + {4.81, 0.47}, + {8.19, 2.02}, + {0.30, 6.63}, + {3.30, 1.51}, + {7.04, 4.79}, + {6.35, 1.52}, + {8.53, 0.92}, + {0.45, 0.39}, + {4.28, 5.90}, + {6.12, 5.64}, + {8.59, 7.41}, + {4.30, 5.78}, + {6.43, 2.21}, + {4.77, 7.90}, + {0.70, 5.41}, + {8.18, 6.98}, + {1.29, 2.11}, + {2.16, 4.09}, + {3.29, 1.89}, + {0.49, 8.12}, + {3.96, 5.91}, + {2.84, 5.36}, + {6.28, 4.19}, + {6.54, 0.63}, + {2.55, 0.29}, + {5.61, 0.23}, + {8.02, 4.40}, + {2.62, 3.69}, + {6.54, 0.25}, + {4.94, 4.86}, + {5.81, 2.73}, + {2.61, 6.62}, + {1.47, 4.98}, + {4.43, 0.97}, + {1.05, 0.44}, + {7.74, 1.30}, + {2.55, 6.53}, + {8.23, 4.24}, + {1.76, 3.09}, + {7.05, 6.10}, + {6.56, 3.03}, + {3.88, 4.19}, + {6.85, 5.32}, + {2.79, 3.66}, + {3.19, 6.72}, + {6.30, 4.73}, + {4.39, 2.31}, + {0.91, 4.92}, + {2.42, 3.31}, + {0.68, 0.96}, + {8.90, 3.57}, + {8.19, 3.87}, + {0.83, 1.18}, + {2.50, 8.93}, + {3.17, 8.93}, + {7.78, 4.05}, + {0.91, 5.55}, + {5.12, 6.37}, + {3.34, 7.63}, + {4.16, 2.85}, + {1.64, 6.72}, + {1.44, 4.71}, + {0.20, 1.04}, + {5.81, 2.04}, + {7.02, 1.80}, + {7.71, 6.69}, + {8.86, 6.35}, + {5.09, 7.07}, + {2.28, 8.67}, + {1.39, 2.65}, + {2.29, 1.30}, + {8.10, 7.17}, + {2.94, 6.11}, + {2.78, 7.15}, + {1.44, 5.74}, + {7.56, 2.18}, + {4.96, 6.24}, + {0.74, 5.42}, + {2.92, 3.59}, + {0.93, 0.66}, + {8.71, 8.81}, + {1.60, 5.03}, + {3.36, 4.56}, + {5.40, 5.87}, + {3.40, 2.89}, + {5.33, 3.61}, + {3.97, 7.61}, + {5.35, 8.41}, + {8.18, 4.04}, + {3.40, 0.46}, + {7.04, 8.11}, + {4.47, 6.74}, + {7.27, 0.06}, + {4.94, 2.57}, + {0.27, 4.06}, + {5.68, 6.95}, + {5.53, 4.82}, + {1.05, 4.34}, + {8.15, 3.91}, + {5.47, 0.38}, + {1.53, 7.80}, + {4.57, 3.74}, + {3.89, 4.86}, + {1.33, 0.95}, + {1.01, 5.36}, + {7.52, 3.15}, + {8.55, 2.59}, + {4.40, 1.39}, + {7.19, 4.86}, + {6.93, 7.86}, + {4.37, 5.88}, + {6.50, 6.74}, + {7.40, 3.07}, + {0.00, 1.86}, + {2.50, 4.56}, + {6.13, 8.66}, + {5.00, 5.65}, + {4.66, 8.75}, + {4.56, 3.70}, + {2.22, 0.57}, + {3.55, 3.57}, + {1.93, 5.58}, + {4.73, 5.02}, + {1.56, 0.61}, + {5.59, 4.62}, + {4.82, 0.06}, + {1.44, 7.95}, + {7.30, 6.89}, + {0.68, 4.56}, + {1.51, 7.49}, + {7.69, 5.75}, + {2.92, 0.66}, + {0.47, 0.54}, + {0.10, 8.37}, + {6.58, 8.66}, + {2.59, 7.19}, + {0.83, 7.69}, + {8.22, 5.41}, + {7.75, 2.10}, + {6.71, 1.62}, + {5.54, 6.22}, + {8.24, 4.46}, + {2.60, 2.11}, + {1.16, 7.03}, + {4.95, 0.20}, + {8.84, 6.68}, + {5.61, 3.86}, + {5.64, 5.44}, + {3.48, 3.11}, + {4.26, 2.86}, + {2.16, 7.76}, + {7.79, 4.61}, + {3.21, 0.63}, + {7.44, 7.69}, + {3.52, 4.42}, + {0.35, 2.73}, + {5.56, 7.33}, + {1.86, 3.50}, + {7.06, 8.72}, + {7.34, 0.44}, + {6.00, 2.27}, + {0.85, 6.68}, + {3.80, 1.59}, + {6.08, 4.72}, + {3.37, 8.58}, + {0.58, 4.79}, + {6.83, 0.21}, + {4.51, 7.63}, + {3.03, 7.70}, + {2.14, 0.22}, + {4.22, 2.87}, + {5.09, 5.97}, + {4.05, 2.53}, + {1.23, 2.65}, + {3.45, 6.61}, + {2.42, 4.24}, + {8.18, 6.07}, + {8.58, 3.96}, + {3.58, 1.40}, + {2.09, 8.55}, + {0.32, 4.01}, + {3.99, 7.07}, + {3.50, 8.50}, + {5.60, 3.30}, + {5.52, 5.45}, + {8.59, 3.07}, + {4.16, 8.21}, + {7.32, 3.92}, + {6.06, 0.71}, + {2.82, 8.56}, + {0.50, 0.24}, + {6.79, 1.81}, + {7.92, 7.91}, + {5.16, 7.92}, + {6.50, 1.29}, + {5.80, 7.32}, + {8.72, 4.75}, + {7.57, 7.18}, + {5.68, 2.65}, + {7.16, 2.49}, + {7.98, 3.72}, + {6.28, 3.48}, + {0.84, 2.91}, + {7.07, 4.85}, + {5.24, 8.65}, + {8.32, 0.44}, + {5.88, 8.09}, + {2.36, 4.46}, + {5.49, 7.25}, + {4.86, 3.89}, + {5.05, 1.73}, + {0.18, 7.01}, + {8.80, 3.24}, + {3.48, 6.73}, + {5.98, 6.75}, + {1.91, 3.68}, + {8.17, 3.98}, + {6.64, 0.88}, + {0.23, 3.24}, + {7.19, 6.06}, + {4.07, 7.93}, + {6.16, 2.71}, + {7.35, 8.32}, + {5.52, 7.36}, + {1.05, 2.20}, + {2.54, 8.26}, + {2.61, 5.89}, + {5.81, 3.66}, + {8.40, 0.98}, + {6.17, 4.18}, + {7.89, 0.78}, + {3.71, 4.02}, + {5.98, 4.86}, + {7.06, 0.26}, + {6.38, 6.63}, + {4.72, 5.50}, + {0.34, 6.06}, + {0.39, 6.90}, + {1.12, 3.69}, + {7.34, 1.68}, + {1.93, 5.12}, + {5.16, 8.99}, + {8.62, 4.11}, + {5.87, 5.10} +}; + +struct Complex input2_data[DATA_SIZE] = +{ + {7.51, 3.02}, + {1.69, 8.91}, + {3.16, 5.16}, + {8.56, 1.38}, + {7.26, 1.26}, + {0.06, 5.16}, + {8.02, 5.34}, + {6.25, 2.06}, + {1.00, 7.96}, + {2.67, 5.82}, + {2.83, 3.93}, + {6.97, 7.32}, + {6.12, 1.36}, + {3.40, 5.08}, + {8.45, 2.33}, + {5.13, 4.59}, + {2.53, 6.34}, + {5.46, 3.38}, + {5.93, 8.44}, + {0.74, 5.13}, + {2.06, 7.22}, + {8.51, 5.79}, + {2.18, 4.41}, + {7.45, 2.82}, + {8.88, 3.50}, + {8.65, 5.85}, + {3.16, 8.99}, + {5.92, 0.71}, + {1.01, 8.99}, + {0.59, 7.63}, + {3.15, 8.98}, + {8.16, 6.45}, + {2.38, 3.74}, + {8.83, 6.31}, + {2.17, 4.46}, + {4.50, 7.79}, + {2.00, 3.75}, + {6.50, 2.58}, + {2.86, 0.71}, + {8.45, 4.87}, + {1.08, 1.53}, + {5.46, 2.61}, + {3.16, 7.22}, + {2.51, 6.84}, + {3.23, 0.83}, + {0.57, 2.44}, + {3.63, 7.10}, + {4.66, 2.01}, + {8.18, 2.18}, + {2.30, 2.99}, + {5.39, 6.67}, + {0.31, 2.81}, + {8.48, 5.02}, + {7.20, 5.02}, + {3.89, 7.17}, + {8.58, 8.03}, + {0.18, 4.64}, + {0.78, 7.84}, + {3.98, 3.97}, + {5.54, 6.12}, + {2.53, 0.09}, + {8.75, 1.54}, + {3.11, 3.43}, + {4.62, 1.67}, + {3.13, 4.86}, + {7.95, 8.00}, + {8.53, 5.52}, + {3.21, 4.32}, + {8.03, 0.07}, + {5.12, 3.02}, + {3.81, 0.86}, + {1.43, 2.53}, + {0.76, 6.20}, + {0.45, 4.30}, + {7.14, 6.57}, + {4.38, 1.15}, + {3.33, 1.93}, + {4.67, 0.06}, + {6.15, 5.37}, + {2.38, 5.80}, + {2.62, 5.40}, + {1.94, 7.66}, + {6.20, 5.58}, + {7.08, 1.19}, + {2.72, 6.01}, + {4.91, 4.40}, + {8.54, 1.13}, + {7.42, 0.13}, + {7.11, 3.64}, + {8.65, 6.34}, + {6.51, 8.69}, + {8.79, 7.88}, + {6.75, 0.78}, + {3.41, 5.95}, + {0.93, 1.38}, + {5.87, 0.88}, + {7.57, 2.13}, + {1.34, 3.82}, + {1.26, 1.95}, + {3.09, 3.26}, + {6.82, 6.44}, + {7.55, 2.70}, + {0.12, 6.15}, + {0.57, 4.45}, + {1.20, 4.84}, + {3.35, 5.79}, + {0.36, 3.74}, + {1.00, 3.95}, + {3.94, 1.83}, + {2.43, 8.90}, + {5.66, 6.48}, + {4.95, 3.05}, + {5.08, 5.70}, + {0.17, 5.83}, + {4.52, 3.85}, + {0.39, 8.91}, + {0.73, 0.11}, + {7.69, 1.28}, + {6.85, 3.52}, + {8.50, 1.54}, + {2.96, 0.95}, + {3.99, 1.09}, + {5.78, 0.74}, + {7.08, 5.41}, + {7.59, 7.85}, + {2.48, 5.50}, + {0.30, 2.11}, + {5.09, 4.74}, + {7.24, 3.98}, + {6.77, 6.78}, + {0.77, 6.54}, + {4.10, 1.81}, + {4.14, 6.83}, + {2.28, 3.58}, + {4.58, 1.27}, + {7.75, 6.74}, + {6.68, 4.31}, + {6.39, 1.62}, + {3.35, 6.23}, + {8.52, 1.56}, + {4.75, 8.24}, + {3.92, 8.68}, + {4.48, 4.19}, + {0.28, 4.70}, + {2.26, 1.09}, + {2.26, 7.02}, + {7.06, 1.45}, + {4.53, 3.96}, + {7.45, 3.63}, + {1.45, 5.70}, + {0.29, 7.05}, + {1.29, 5.73}, + {0.81, 7.68}, + {0.97, 7.35}, + {0.96, 8.60}, + {0.05, 0.15}, + {1.84, 6.27}, + {5.18, 5.39}, + {4.74, 7.43}, + {2.16, 4.17}, + {6.82, 4.81}, + {0.45, 3.86}, + {7.21, 6.55}, + {4.62, 4.93}, + {4.44, 7.20}, + {5.60, 0.20}, + {0.93, 0.54}, + {8.30, 5.93}, + {7.93, 8.77}, + {2.16, 8.70}, + {1.03, 0.56}, + {4.77, 2.73}, + {8.98, 3.69}, + {3.49, 6.57}, + {0.95, 3.93}, + {8.44, 5.34}, + {3.69, 7.18}, + {1.82, 1.60}, + {5.53, 8.97}, + {4.70, 1.43}, + {0.20, 5.51}, + {2.82, 0.13}, + {2.48, 7.18}, + {2.19, 0.00}, + {0.95, 0.87}, + {8.10, 6.66}, + {5.81, 3.92}, + {1.46, 0.34}, + {8.52, 5.46}, + {6.92, 0.24}, + {1.03, 3.98}, + {0.56, 3.10}, + {7.55, 3.29}, + {3.90, 5.76}, + {1.90, 8.93}, + {7.40, 3.05}, + {3.28, 8.78}, + {4.47, 2.40}, + {8.26, 3.14}, + {3.88, 3.78}, + {1.62, 1.95}, + {7.57, 8.14}, + {7.09, 6.58}, + {7.17, 7.39}, + {6.83, 8.82}, + {3.62, 6.04}, + {8.87, 5.12}, + {6.57, 5.97}, + {7.16, 3.48}, + {4.76, 1.56}, + {4.99, 2.85}, + {6.91, 4.30}, + {2.13, 3.60}, + {2.07, 7.26}, + {4.56, 2.43}, + {6.35, 6.28}, + {1.26, 4.76}, + {7.17, 5.62}, + {5.05, 0.79}, + {0.08, 7.82}, + {7.33, 3.59}, + {5.27, 5.83}, + {5.58, 8.50}, + {4.31, 5.31}, + {8.64, 2.60}, + {8.88, 6.69}, + {2.77, 4.71}, + {7.43, 3.89}, + {6.75, 8.39}, + {7.44, 4.16}, + {1.40, 2.46}, + {0.39, 3.07}, + {0.73, 1.43}, + {6.74, 4.00}, + {2.40, 5.69}, + {6.59, 2.47}, + {3.83, 1.67}, + {2.89, 2.63}, + {4.89, 1.41}, + {6.78, 0.80}, + {0.13, 5.67}, + {8.16, 0.29}, + {7.30, 6.71}, + {7.87, 8.25}, + {2.61, 5.00}, + {5.03, 4.78}, + {3.65, 3.62}, + {2.64, 4.87}, + {7.66, 1.09}, + {4.08, 4.70}, + {0.78, 2.02}, + {1.64, 4.78}, + {3.03, 5.87}, + {5.78, 0.87}, + {2.88, 5.13}, + {5.83, 1.14}, + {8.64, 1.73}, + {1.28, 7.18}, + {2.70, 5.16}, + {6.86, 1.27}, + {5.83, 7.68}, + {5.58, 6.35}, + {2.35, 4.33}, + {4.88, 3.36}, + {8.93, 4.92}, + {1.87, 1.08}, + {8.40, 4.19}, + {0.31, 2.64}, + {4.31, 7.93}, + {1.83, 6.71}, + {1.93, 7.98}, + {8.04, 0.02}, + {6.13, 2.90}, + {6.20, 4.38}, + {3.48, 1.60}, + {0.91, 6.38}, + {3.60, 8.25}, + {2.97, 2.18}, + {4.25, 7.17}, + {6.54, 2.27}, + {8.45, 1.36}, + {7.84, 3.00}, + {4.91, 8.46}, + {7.69, 3.58}, + {8.82, 6.81}, + {0.95, 3.82}, + {0.89, 8.67}, + {0.88, 8.32}, + {6.89, 4.77}, + {3.03, 0.82}, + {6.98, 6.18}, + {2.92, 6.80}, + {4.83, 4.46}, + {5.36, 3.51}, + {0.68, 0.34}, + {4.47, 5.76}, + {4.05, 8.57}, + {1.22, 0.73}, + {7.55, 6.52}, + {6.91, 1.13}, + {3.75, 2.24}, + {8.88, 3.26}, + {5.57, 7.83}, + {2.12, 7.58}, + {5.15, 3.02}, + {5.05, 2.37}, + {2.18, 7.29}, + {8.88, 3.06}, + {3.10, 3.70}, + {5.52, 0.51}, + {1.59, 4.38}, + {3.01, 8.95}, + {2.79, 2.15}, + {0.42, 3.03}, + {4.54, 1.21}, + {3.54, 6.51}, + {2.83, 8.50}, + {3.12, 5.67}, + {5.41, 1.88}, + {3.47, 4.72}, + {4.91, 3.21}, + {6.02, 6.07}, + {7.69, 6.49}, + {2.82, 0.77}, + {4.80, 1.90}, + {7.53, 6.64}, + {8.92, 4.08}, + {8.22, 8.78}, + {2.42, 7.18}, + {6.95, 5.57}, + {7.70, 6.55}, + {0.16, 1.49}, + {8.21, 7.48}, + {1.24, 1.69}, + {6.46, 6.05}, + {6.48, 7.98}, + {7.08, 5.93}, + {1.77, 5.59}, + {4.03, 1.56}, + {0.05, 0.65}, + {5.55, 0.72}, + {1.58, 6.17}, + {1.11, 8.72}, + {6.45, 8.09}, + {2.07, 3.36}, + {5.65, 6.50}, + {8.35, 4.98}, + {0.16, 1.58}, + {1.43, 2.93}, + {5.35, 1.67}, + {3.55, 7.75}, + {6.72, 5.17}, + {7.80, 3.15}, + {4.98, 8.02}, + {3.12, 7.97}, + {2.62, 8.84}, + {4.91, 8.91}, + {4.11, 2.99}, + {0.99, 6.46}, + {8.07, 4.00}, + {6.31, 3.55}, + {3.07, 6.34}, + {7.48, 5.88}, + {4.92, 4.37}, + {8.76, 5.04}, + {2.83, 4.57}, + {8.75, 3.10}, + {7.16, 7.07}, + {8.08, 3.80}, + {8.26, 7.85}, + {3.06, 1.46}, + {2.03, 4.34}, + {5.23, 1.04}, + {1.21, 8.69}, + {1.82, 2.10}, + {3.57, 5.43}, + {4.31, 8.50}, + {5.17, 1.09}, + {3.06, 7.31}, + {4.06, 3.26}, + {6.71, 8.20}, + {5.36, 5.16}, + {1.08, 8.77}, + {6.82, 3.20}, + {7.64, 7.66}, + {3.42, 8.21}, + {8.15, 6.94}, + {2.19, 7.88}, + {3.88, 4.35}, + {2.20, 5.82}, + {3.60, 2.96}, + {2.75, 7.97}, + {5.36, 8.76}, + {6.30, 4.62}, + {6.76, 5.07}, + {4.10, 3.30}, + {0.84, 7.09}, + {0.15, 3.45}, + {4.46, 4.08}, + {0.71, 0.76}, + {1.01, 8.40}, + {3.09, 8.33}, + {6.13, 0.62}, + {8.66, 8.88}, + {5.64, 7.97}, + {5.55, 3.51}, + {6.70, 7.15}, + {4.31, 6.97}, + {4.58, 6.99}, + {7.30, 1.26}, + {8.78, 3.89}, + {5.23, 3.35}, + {7.82, 5.89}, + {2.43, 7.35}, + {5.88, 1.26}, + {8.92, 2.84}, + {2.92, 8.01}, + {1.48, 2.34}, + {1.71, 3.40}, + {2.09, 2.74}, + {1.38, 0.32}, + {2.96, 5.20}, + {7.64, 2.94}, + {3.63, 3.88}, + {4.92, 6.39}, + {0.02, 8.67}, + {8.02, 3.99}, + {7.50, 7.49}, + {3.70, 2.90}, + {2.22, 1.62}, + {1.91, 1.05}, + {0.09, 6.89}, + {3.85, 6.35}, + {0.48, 7.25}, + {7.31, 5.51}, + {3.95, 3.38}, + {2.96, 8.75}, + {3.75, 5.76}, + {6.17, 6.52}, + {2.75, 5.83}, + {5.39, 1.43}, + {7.95, 7.98}, + {8.45, 7.81}, + {1.04, 2.67}, + {0.45, 4.26}, + {3.30, 0.05}, + {2.32, 4.57}, + {6.01, 5.41}, + {8.93, 2.00}, + {1.93, 3.15}, + {0.12, 1.35}, + {0.48, 4.00}, + {8.42, 6.49}, + {7.47, 8.76}, + {5.60, 2.90}, + {4.71, 0.45}, + {0.52, 6.86}, + {3.18, 2.15}, + {8.76, 2.04}, + {3.75, 1.59}, + {7.79, 4.06}, + {1.47, 0.90}, + {0.11, 0.29}, + {4.57, 6.95}, + {7.04, 4.40}, + {2.18, 1.75}, + {7.30, 8.71}, + {3.93, 3.11}, + {5.40, 1.78}, + {5.80, 1.05}, + {6.40, 6.13}, + {1.01, 4.99}, + {0.12, 7.88}, + {5.55, 4.57}, + {3.24, 4.86}, + {2.10, 6.88}, + {6.18, 2.58}, + {1.06, 7.54}, + {6.66, 7.44}, + {2.86, 5.28}, + {5.17, 3.18}, + {6.96, 0.10}, + {4.55, 0.05}, + {8.01, 5.80}, + {3.79, 3.32}, + {4.65, 1.53}, + {1.98, 4.75}, + {6.46, 0.63}, + {6.23, 2.69}, + {4.14, 2.95}, + {2.92, 7.47}, + {2.23, 4.48}, + {3.18, 8.84}, + {6.66, 6.43}, + {8.20, 4.54}, + {5.64, 4.90}, + {1.98, 2.74}, + {3.36, 8.60}, + {5.83, 7.23}, + {8.61, 0.25}, + {7.66, 5.90}, + {3.54, 4.24}, + {3.80, 8.48}, + {6.15, 4.07}, + {1.41, 2.14}, + {6.92, 6.43}, + {4.95, 7.83}, + {2.26, 4.29}, + {1.91, 0.40}, + {8.10, 1.26}, + {5.49, 4.23}, + {3.92, 3.68} +}; + +struct Complex verify_data[DATA_SIZE] = +{ + {-9.55, 31.87}, + {8.45, 45.39}, + {4.34, 45.27}, + {9.41, 6.59}, + {35.73, 20.80}, + {-9.46, 29.00}, + {50.95, 69.43}, + {5.47, 57.90}, + {7.79, 69.03}, + {-36.53, 24.18}, + {-6.85, 27.86}, + {-4.86, 87.57}, + {5.59, 57.99}, + {-5.10, 61.38}, + {30.42, 30.70}, + {-1.81, 52.19}, + {-0.43, 13.62}, + {16.97, 56.10}, + {-14.63, 68.37}, + {-26.08, 12.95}, + {-56.93, 35.07}, + {-4.61, 62.42}, + {3.10, 43.03}, + {52.89, 45.25}, + {55.98, 76.85}, + {-13.41, 52.73}, + {-63.15, 73.78}, + {29.38, 47.60}, + {-15.25, 16.57}, + {-38.76, 62.42}, + {-48.83, 43.31}, + {-4.32, 26.85}, + {4.49, 39.11}, + {15.24, 75.60}, + {14.71, 30.66}, + {12.39, 37.66}, + {-16.19, 26.14}, + {19.10, 27.68}, + {13.49, 20.33}, + {1.62, 36.60}, + {-6.13, 10.25}, + {17.87, 40.40}, + {-40.70, 48.05}, + {-34.10, 44.30}, + {5.13, 24.45}, + {-18.80, 17.91}, + {-22.36, 91.00}, + {4.95, 28.61}, + {32.18, 44.95}, + {6.40, 28.33}, + {-3.28, 80.04}, + {-10.91, 4.86}, + {-24.07, 62.47}, + {38.92, 73.33}, + {-40.44, 68.15}, + {24.28, 74.58}, + {-27.37, 13.08}, + {-39.05, 7.43}, + {-27.07, 33.97}, + {25.94, 35.40}, + {8.40, 9.34}, + {63.51, 12.56}, + {13.94, 33.44}, + {10.67, 29.11}, + {-12.93, 68.17}, + {-12.91, 128.67}, + {38.58, 30.92}, + {-16.80, 54.81}, + {41.01, 11.31}, + {-16.46, 30.20}, + {17.23, 30.21}, + {-10.98, 19.28}, + {-22.07, 2.83}, + {-34.27, 13.24}, + {-20.25, 78.23}, + {31.56, 19.48}, + {8.30, 14.29}, + {22.98, 7.89}, + {24.83, 70.87}, + {-2.96, 18.61}, + {-5.10, 32.50}, + {10.92, 63.09}, + {7.76, 73.56}, + {14.73, 10.45}, + {-31.23, 50.42}, + {6.18, 40.10}, + {17.09, 61.26}, + {18.50, 42.26}, + {19.17, 10.67}, + {51.10, 50.14}, + {-42.52, 76.67}, + {-5.54, 53.06}, + {33.70, 56.65}, + {-0.44, 6.76}, + {-7.42, 6.89}, + {19.24, 9.46}, + {48.41, 43.99}, + {3.87, 12.42}, + {-16.32, 11.94}, + {8.37, 45.34}, + {-20.69, 87.66}, + {19.71, 56.72}, + {-48.50, 33.76}, + {-0.57, 7.13}, + {-22.71, 11.26}, + {-27.73, 68.86}, + {-11.59, 33.48}, + {-9.62, 7.36}, + {15.89, 44.50}, + {-32.81, 30.96}, + {-18.53, 58.34}, + {-9.41, 55.15}, + {11.33, 59.36}, + {-7.88, 9.24}, + {13.91, 43.66}, + {-38.15, 64.22}, + {4.54, 3.59}, + {8.44, 35.80}, + {-1.29, 25.84}, + {26.64, 8.86}, + {19.44, 23.93}, + {8.31, 39.70}, + {21.07, 49.26}, + {-24.77, 69.02}, + {-34.89, 49.32}, + {-23.70, 64.79}, + {-7.06, 5.59}, + {4.13, 67.73}, + {13.44, 30.78}, + {36.07, 63.89}, + {-53.67, 23.06}, + {5.35, 33.70}, + {23.17, 45.78}, + {-0.85, 2.44}, + {15.12, 6.04}, + {23.63, 71.56}, + {20.37, 31.88}, + {17.50, 51.67}, + {-25.60, 17.35}, + {56.86, 67.97}, + {28.63, 81.59}, + {25.38, 56.49}, + {0.05, 18.79}, + {-13.60, 30.47}, + {4.80, 8.17}, + {4.55, 23.00}, + {33.94, 19.94}, + {4.04, 57.01}, + {43.61, 50.83}, + {-5.06, 10.59}, + {-16.60, 43.62}, + {-14.17, 14.19}, + {-1.97, 59.94}, + {-1.25, 26.76}, + {-22.66, 69.63}, + {0.03, 0.23}, + {-26.76, 54.82}, + {-23.82, 41.05}, + {-49.83, 52.38}, + {-24.58, 21.18}, + {20.76, 61.75}, + {-12.48, 26.36}, + {-37.73, 52.56}, + {6.00, 68.90}, + {9.32, 27.67}, + {0.36, 10.88}, + {-2.45, 5.87}, + {36.49, 74.56}, + {38.31, 57.71}, + {-35.46, 78.25}, + {1.62, 7.20}, + {8.75, 40.70}, + {-22.91, 58.17}, + {25.14, 55.26}, + {-7.33, 17.05}, + {-0.86, 95.47}, + {-27.65, 56.11}, + {-2.21, 12.53}, + {-54.69, 81.45}, + {9.02, 24.97}, + {-39.56, 35.42}, + {3.90, 17.48}, + {-4.84, 9.43}, + {7.63, 3.67}, + {-1.49, 9.99}, + {6.07, 96.66}, + {11.55, 69.81}, + {0.06, 4.54}, + {29.61, 22.63}, + {-0.18, 58.41}, + {4.87, 32.02}, + {-8.74, 5.88}, + {-6.42, 42.08}, + {-19.85, 77.38}, + {-29.51, 18.18}, + {47.64, 39.05}, + {-49.21, 69.14}, + {16.27, 29.14}, + {47.13, 57.96}, + {-5.88, 17.20}, + {7.39, 17.73}, + {-2.63, 76.94}, + {-8.43, 67.80}, + {17.66, 95.65}, + {-3.78, 105.43}, + {-19.35, 19.33}, + {-22.13, 85.25}, + {-32.01, 51.45}, + {33.34, 27.27}, + {4.76, 45.63}, + {20.07, 38.73}, + {16.43, 26.11}, + {12.41, 35.49}, + {-9.54, 69.75}, + {-15.05, 44.52}, + {-35.58, 48.02}, + {-26.35, 43.57}, + {17.04, 18.66}, + {25.06, 28.94}, + {-20.65, 8.61}, + {31.60, 24.50}, + {-39.23, 39.05}, + {8.47, 75.50}, + {-13.14, 71.52}, + {3.44, 4.81}, + {11.79, 114.92}, + {16.71, 37.99}, + {-11.03, 32.07}, + {48.07, 85.39}, + {10.42, 8.37}, + {0.67, 17.83}, + {-7.51, 24.17}, + {-6.98, 14.83}, + {8.26, 18.75}, + {6.14, 42.31}, + {-13.44, 58.32}, + {20.77, 41.19}, + {-5.08, 24.90}, + {0.02, 44.55}, + {40.65, 56.02}, + {-49.38, 47.95}, + {-1.62, 47.74}, + {65.36, 60.27}, + {10.12, 69.99}, + {-12.80, 62.38}, + {-19.28, 66.58}, + {12.35, 51.40}, + {-16.15, 41.69}, + {8.46, 64.81}, + {-37.44, 42.07}, + {-6.31, 17.43}, + {-28.52, 42.42}, + {-36.85, 35.12}, + {39.58, 17.97}, + {-12.11, 6.90}, + {49.39, 22.67}, + {49.25, 59.28}, + {-13.11, 15.93}, + {-36.76, 29.92}, + {9.02, 8.57}, + {-3.52, 108.92}, + {26.81, 33.21}, + {-25.78, 35.35}, + {23.31, 19.43}, + {30.72, 38.03}, + {8.59, 14.15}, + {3.84, 62.92}, + {-0.07, 16.04}, + {16.99, 40.18}, + {1.44, 58.64}, + {-52.31, 15.21}, + {26.47, 12.18}, + {29.26, 49.76}, + {32.75, 37.25}, + {28.24, 16.85}, + {-2.05, 3.25}, + {-33.27, 56.51}, + {5.90, 30.11}, + {-16.63, 93.02}, + {14.99, 47.54}, + {51.31, 27.46}, + {13.69, 76.22}, + {-42.35, 32.55}, + {37.88, 82.98}, + {-2.92, 27.40}, + {-13.59, 12.14}, + {-13.48, 30.24}, + {-67.06, 11.26}, + {-0.87, 59.62}, + {4.24, 18.59}, + {17.98, 68.03}, + {14.82, 46.36}, + {11.00, 12.77}, + {29.22, 20.92}, + {3.95, 5.68}, + {-9.54, 31.57}, + {24.37, 57.06}, + {2.50, 9.51}, + {26.05, 58.50}, + {10.56, 48.73}, + {-5.65, 21.94}, + {36.16, 23.04}, + {2.42, 10.68}, + {6.56, 61.46}, + {-6.60, 41.32}, + {31.49, 40.93}, + {-18.71, 19.55}, + {43.97, 75.72}, + {9.14, 33.64}, + {19.30, 25.13}, + {-12.38, 38.43}, + {-24.39, 35.99}, + {-5.55, 25.66}, + {-11.71, 21.07}, + {17.12, 15.80}, + {-28.85, 23.36}, + {-21.31, 29.96}, + {-3.33, 6.83}, + {41.43, 36.06}, + {10.13, 52.06}, + {0.30, 8.45}, + {-39.11, 68.91}, + {-33.57, 89.22}, + {18.81, 17.35}, + {-6.22, 28.36}, + {-3.80, 82.00}, + {-1.35, 81.71}, + {9.18, 59.90}, + {-44.29, 28.03}, + {-16.17, 40.76}, + {-5.22, 9.32}, + {-2.14, 9.00}, + {44.18, 67.32}, + {-1.76, 21.32}, + {18.82, 94.67}, + {-23.49, 86.50}, + {-35.23, 74.91}, + {-12.32, 12.48}, + {7.18, 8.81}, + {-4.30, 5.64}, + {11.90, 36.04}, + {-39.71, 28.47}, + {-48.46, 18.94}, + {31.11, 75.20}, + {-10.67, 29.61}, + {-31.00, 35.43}, + {6.53, 44.56}, + {-0.88, 1.57}, + {-13.32, 38.14}, + {0.14, 29.57}, + {-23.39, 42.20}, + {5.95, 67.32}, + {17.38, 33.26}, + {-2.36, 60.71}, + {-48.30, 55.33}, + {-60.27, 69.27}, + {4.13, 92.76}, + {12.63, 12.06}, + {-45.40, 53.50}, + {9.11, 72.28}, + {45.68, 26.21}, + {-1.17, 39.19}, + {-21.89, 31.92}, + {-2.45, 59.04}, + {24.16, 70.02}, + {-16.86, 17.05}, + {59.15, 59.47}, + {36.45, 41.38}, + {-17.30, 68.80}, + {8.35, 66.77}, + {4.78, 20.56}, + {-1.41, 7.70}, + {-0.27, 29.10}, + {-18.33, 69.13}, + {10.10, 22.61}, + {8.17, 28.85}, + {-10.28, 82.05}, + {27.25, 48.21}, + {-29.61, 49.95}, + {4.42, 48.59}, + {24.46, 81.28}, + {-9.60, 10.00}, + {-37.27, 26.90}, + {14.15, 78.71}, + {-5.04, 81.46}, + {-55.91, 68.15}, + {11.48, 61.76}, + {0.33, 18.74}, + {-1.75, 29.29}, + {-28.27, 23.57}, + {2.14, 32.10}, + {-0.58, 14.09}, + {-10.48, 73.71}, + {30.11, 22.64}, + {-30.62, 61.05}, + {7.14, 52.31}, + {-31.75, 8.68}, + {-25.60, 6.33}, + {10.81, 57.00}, + {1.58, 2.68}, + {-4.03, 4.49}, + {-69.40, 26.65}, + {34.97, 57.23}, + {-41.39, 85.26}, + {-56.66, 50.02}, + {26.67, 58.89}, + {36.97, 69.48}, + {17.62, 53.74}, + {-18.06, 67.20}, + {54.54, 42.92}, + {14.62, 28.66}, + {-17.46, 40.70}, + {37.49, 30.72}, + {-27.58, 81.20}, + {28.17, 29.78}, + {34.89, 64.55}, + {-14.73, 36.98}, + {-0.38, 14.23}, + {-22.73, 20.62}, + {3.66, 30.99}, + {4.21, 1.91}, + {-17.97, 61.45}, + {13.89, 44.10}, + {-9.36, 11.27}, + {-19.45, 71.53}, + {-30.31, 16.20}, + {21.83, 98.07}, + {51.73, 58.32}, + {15.61, 25.75}, + {-8.92, 16.21}, + {5.57, 7.03}, + {-31.94, 42.30}, + {-41.53, 54.41}, + {-34.46, 6.55}, + {48.82, 39.18}, + {-7.99, 45.35}, + {-58.46, 49.26}, + {6.76, 13.13}, + {7.31, 45.21}, + {-20.81, 46.15}, + {18.17, 19.43}, + {-11.37, 30.95}, + {-22.46, 82.83}, + {-8.81, 10.85}, + {-22.15, 37.62}, + {28.11, 13.51}, + {1.90, 19.58}, + {-33.67, 62.66}, + {-5.18, 36.44}, + {-14.59, 26.19}, + {-11.07, 5.77}, + {-10.54, 23.97}, + {11.13, 81.69}, + {37.26, 98.19}, + {-0.45, 58.06}, + {32.69, 21.79}, + {-1.75, 41.90}, + {-9.42, 33.26}, + {3.90, 3.16}, + {22.57, 17.60}, + {29.61, 93.77}, + {0.47, 16.32}, + {0.35, 2.00}, + {-24.37, 73.72}, + {40.52, 71.85}, + {3.95, 28.92}, + {18.43, 68.77}, + {20.38, 32.06}, + {36.49, 34.30}, + {32.78, 26.76}, + {-12.45, 23.75}, + {-17.04, 40.20}, + {-67.58, 42.30}, + {44.14, 40.41}, + {-20.29, 54.82}, + {-25.76, 25.64}, + {15.24, 59.03}, + {-24.18, 40.82}, + {20.78, 49.10}, + {-36.53, 21.06}, + {35.15, 44.67}, + {23.56, 47.18}, + {26.83, 31.04}, + {-6.04, 40.57}, + {17.77, 42.20}, + {29.56, 14.24}, + {-14.93, 7.49}, + {42.65, 43.61}, + {4.09, 60.41}, + {17.54, 29.38}, + {-40.77, 79.19}, + {-20.66, 41.15}, + {-16.10, 16.23}, + {-36.23, 71.30}, + {-5.32, 60.14}, + {14.84, 49.12}, + {13.98, 25.01}, + {-15.22, 67.15}, + {40.35, 61.61}, + {30.94, 35.53}, + {17.11, 72.57}, + {23.87, 30.84}, + {-31.95, 79.27}, + {6.63, 52.97}, + {-12.48, 9.24}, + {-41.66, 50.25}, + {-23.34, 27.06}, + {9.40, 35.27}, + {1.66, 10.57}, + {30.45, 79.29}, + {29.85, 59.03}, + {4.19, 41.60} +}; + diff --git a/benchmarks/vec-cmplxmult/dataset_test.h b/benchmarks/vec-cmplxmult/dataset_test.h new file mode 100644 index 0000000..a522516 --- /dev/null +++ b/benchmarks/vec-cmplxmult/dataset_test.h @@ -0,0 +1,27 @@ + +#define DATA_SIZE 4 + +struct Complex input1_data[DATA_SIZE] = +{ + {0.37, 4.09}, + {5.09, 0.02}, + {6.75, 3.30}, + {1.19, 0.58} +}; + +struct Complex input2_data[DATA_SIZE] = +{ + {7.51, 3.02}, + {1.69, 8.91}, + {3.16, 5.16}, + {8.56, 1.38} +}; + +struct Complex verify_data[DATA_SIZE] = +{ + {-9.55, 31.87}, + {8.45, 45.39}, + {4.34, 45.27}, + {9.41, 6.59} +}; + diff --git a/benchmarks/vec-cmplxmult/vec_cmplxmult_asm.S b/benchmarks/vec-cmplxmult/vec_cmplxmult_asm.S new file mode 100644 index 0000000..0771965 --- /dev/null +++ b/benchmarks/vec-cmplxmult/vec_cmplxmult_asm.S @@ -0,0 +1,146 @@ +#***************************************************************************** +# cmplxmult function (assembly version) +#----------------------------------------------------------------------------- + + +#-------------------------------------------------------------------------- +# Headers and Defines +#-------------------------------------------------------------------------- + +# Here are some defines that make writing assembly code easier. + +# I'm using the knowledge that rN will be placed in register a0, rA will be +# placed into register a1, etc., based on the calling convention for functions. + + +#define rN a0 +#define rA a1 +#define rB a2 +#define rC a3 + +#define rVlen a6 +#define rStride a7 + +#define rAI a8 +#define rBI a9 +#define rCI a10 + +# WARNING: do not write to the s0,...,s9 registers without first saving them to +# the stack. + +#-------------------------------------------------------------------------- +# void scalar_cmplxmult_asm( int n, float a[], float b[], float c[] ) +#-------------------------------------------------------------------------- + + .text + .align 2 + .globl scalar_cmplxmult_asm + .type scalar_cmplxmult_asm,@function + +scalar_cmplxmult_asm: + + # ***** Scalar Example ***** + + blez rN, done # exit early if n < 0 + +loop: + # The following code is a naive implementation... + # Re-ordering instructions may increase performance, also, + # RISC-V supports instrucitons such as the "fmuladd" and "fmulsub". + # fmsub.s fa2,fa4,fa3,ft1 + # Finally, unrolling and other fun transformations can also provide + # performance gains. + + flw f2, 0(rA) + flw f3, 4(rA) + flw f4, 0(rB) + flw f5, 4(rB) + fmul.s f6, f2, f4 + fmul.s f7, f3, f5 + fmul.s f8, f3, f4 + fmul.s f9, f2, f5 + fsub.s f10, f6, f7 + fadd.s f11, f8, f9 + fsw f10, 0(rC) + fsw f11, 4(rC) + addi rN, rN, -1 + addi rA, rA, 8 + addi rB, rB, 8 + addi rC, rC, 8 + bne rN, zero, loop +done: + ret + + +#-------------------------------------------------------------------------- +# void vt_cmplxmult_asm( int n, float a[], float b[], float c[] ) +#-------------------------------------------------------------------------- + + + # ***** Vector-Thread Example ***** + + .globl vt_cmplxmult_asm + .type vt_cmplxmult_asm,@function + + # HINT: because you are dealing with an array of structures, a regular, + # vanilla vector-load/vector-store won't work here! + +vt_cmplxmult_asm: + + blez rN, cpdone + la a4, vtcode + li rStride, 8 + + vvcfgivl rVlen, rN, 1, 7 + +stripmineloop: + + # ADD YOUR CODE HERE.... + vsetvl rVlen, rN # set the vector length + # rN is the desired (application) vector length + # rVLen is what vector length we were given + + vflstw vf2, rA, rStride # real number vector load of A + addi rAI, rA, 4 + vflstw vf4, rB, rStride # real number vector load of B + addi rBI, rB, 4 + vflstw vf3, rAI, rStride #imaginary number vector load of A + vflstw vf5, rBI, rStride #imaginary vector number load of B + + vf 0(a4) # jump to vector-fetch code + + vfsstw vf0, rC, rStride # real number vector store C + addi rCI, rC, 4 + vfsstw vf1, rCI, rStride # imaginary + + slli a5, rVlen, 3 + sub rN, rN, rVlen # book keeping + add rA, rA, a5 + add rB, rB, a5 + add rC, rC, a5 + bne rN, zero, stripmineloop + # Step 0: set the vector length + # Step 1: perform your vector loads + # Step 2: jump to the vector-fetch code to perform the calculation + # Step 3: perform the vector store + # Step 4: book keeping, update the pointers, etc. + +cpdone: + fence.v.l + ret + +vtcode: + # ADD YOUR VECTOR-ELEMENT CODE HERE ... + fmul.s f0, f2, f4 + fmsub.s f0, f3, f5, f0 + + fmul.s f1, f2, f5 + fmadd.s f1, f3, f4, f1 + stop + + # The C code uses a jalr instruction to call this function + # so we can use a jr to return back to where the function + # was called. Also known as "ret", for "return". + + ret + diff --git a/benchmarks/vec-cmplxmult/vec_cmplxmult_main.c b/benchmarks/vec-cmplxmult/vec_cmplxmult_main.c new file mode 100644 index 0000000..3251ef9 --- /dev/null +++ b/benchmarks/vec-cmplxmult/vec_cmplxmult_main.c @@ -0,0 +1,316 @@ +//************************************************************************** +// Vector-Thread Complex Multiply benchmark +//-------------------------------------------------------------------------- +// +// This benchmark multiplies two complex numbers together. The input data (and +// reference data) should be generated using the cmplxmult_gendata.pl perl +// script and dumped to a file named dataset.h. The riscv-gcc toolchain does +// not support system calls so printf's can only be used on a host system, not +// on the riscv-v processor simulator itself. +// +// HOWEVER: printstr() and printhex() are provided, for a primitive form of +// printing strings and hexadecimal values to stdout. + + +// Choose which implementation you wish to test... but leave only one on! +// (only the first one will be executed). +//#define SCALAR_C +//#define SCALAR_ASM +#define VT_ASM + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +//-------------------------------------------------------------------------- +// Host Platform Includes + +#if HOST_DEBUG + #include + #include +#else +void printstr(const char*); +void exit(); +#endif + + +//-------------------------------------------------------------------------- +// Complex Value Structs + +struct Complex +{ + float real; + float imag; +}; + + +//-------------------------------------------------------------------------- +// Input/Reference Data + +//#include "dataset_test.h" +#include "dataset.h" + + +//-------------------------------------------------------------------------- +// Helper functions + +float absolute( float in) +{ + if (in > 0) + return in; + else + return -in; +} + + +// are two floating point numbers "close enough"? +// this is pretty loose, because Perl is giving me pretty terrible answers +int close_enough(float a, float b) +{ + int close_enough = 1; + + if ( absolute(a) > 1.10*absolute(b) + || absolute(a) < 0.90*absolute(b) + || absolute(a) > 1.10*absolute(b) + || absolute(a) < 0.90*absolute(b)) + { + if (absolute(absolute(a) - absolute(b)) > 0.1) + { + close_enough = 0; + } + } + + return close_enough; +} + +int verify( int n, struct Complex test[], struct Complex correct[] ) +{ + int i; + for ( i = 0; i < n; i++ ) { + if ( !close_enough(test[i].real, correct[i].real) + || !close_enough(test[i].imag, correct[i].imag)) + { +#if HOST_DEBUG + printf(" test[%d] : {%3.2f, %3.2f}\n", i, test[i].real, test[i].imag); + printf(" corr[%d] : {%3.2f, %3.2f}\n", i, correct[i].real, correct[i].imag); +#endif + // tell us which index fails + 10 + // (so that if i==0,i==1 fails, we don't + // think it was a 'not-finished yet' or pass) +// return i+10; + return 2; + } + } + return 1; +} + +//#if HOST_DEBUG +void printComplexArray( char name[], int n, struct Complex arr[] ) +{ +#if HOST_DEBUG + int i; + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " {%03.2f,%03.2f} ", arr[i].real, arr[i].imag ); + printf( "\n" ); +#else + int i; + printstr( name ); + for ( i = 0; i < n; i++ ) + { + printstr(" {"); + printhex((int) arr[i].real); + printstr(","); + printhex((int) arr[i].imag); + printstr("}"); + } + printstr( "\n" ); +#endif +} +//#endif + + + +void finishTest( int correct, long long num_cycles, long long num_retired ) +{ + int toHostValue = correct; +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + // we no longer run in -testrun mode, which means we can't use + // the tohost register to communicate "test is done" and "test results" + // so instead we will communicate through print* functions! + if ( correct == 1 ) + { + printstr( "*** PASSED *** (num_cycles = 0x" ); + printhex(num_cycles); + printstr( ", num_inst_retired = 0x"); + printhex(num_retired); + printstr( ")\n" ); + } + else + { + printstr( "*** FAILED *** (num_cycles = 0x"); + printhex(num_cycles); + printstr( ", num_inst_retired = 0x"); + printhex(num_retired); + printstr( ")\n" ); + } + exit(); +#endif +} + + + + +// deprecated - cr10/stats-enable register no longer exists +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +long long getCycles() +{ + long long cycles = 1337; +#if ( !HOST_DEBUG && SET_STATS ) + __asm__ __volatile__( "rdcycle %0" : "=r" (cycles) ); +#endif + return cycles; +} + +long long getInstRetired() +{ + long long inst_retired = 1338; +#if ( !HOST_DEBUG && SET_STATS ) + __asm__ __volatile__( "rdinstret %0" : "=r" (inst_retired) ); +#endif + return inst_retired; +} + +//-------------------------------------------------------------------------- +// complex multiply function + +// scalar C implementation +void cmplxmult( int n, struct Complex a[], struct Complex b[], struct Complex c[] ) +{ + int i; + for ( i = 0; i < n; i++ ) + { + c[i].real = (a[i].real * b[i].real) - (a[i].imag * b[i].imag); + c[i].imag = (a[i].imag * b[i].real) + (a[i].real * b[i].imag); + } +} + +// assembly implementations can be found in *_asm.S + +//-------------------------------------------------------------------------- +// Main + +int main( int argc, char* argv[] ) +{ + struct Complex results_data[DATA_SIZE]; + long long start_cycles = 0; + long long stop_cycles = 0; + long long num_cycles; + long long start_retired = 0; + long long stop_retired = 0; + long long num_retired; + + // Output the input array + +#if HOST_DEBUG + printComplexArray( "input1", DATA_SIZE, input1_data ); + printComplexArray( "input2", DATA_SIZE, input2_data ); + printComplexArray( "verify", DATA_SIZE, verify_data ); +#endif + + // -------------------------------------------------- + // If needed we preallocate everything in the caches + +#if PREALLOCATE + +#ifdef SCALAR_C + cmplxmult( DATA_SIZE, input1_data, input2_data, results_data ); +#else +#ifdef SCALAR_ASM + scalar_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data ); +#else +#ifdef VT_ASM + vt_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data ); +#endif +#endif +#endif + +#endif + + // -------------------------------------------------- + // Do the cmplxmult + + start_cycles = getCycles(); + start_retired = getInstRetired(); + +#ifdef SCALAR_C + cmplxmult( DATA_SIZE, input1_data, input2_data, results_data ); +#else +#ifdef SCALAR_ASM + #if HOST_DEBUG==0 + scalar_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data ); + #endif +#else +#ifdef VT_ASM + #if HOST_DEBUG==0 + vt_cmplxmult_asm( DATA_SIZE, input1_data, input2_data, results_data ); + #endif +#endif +#endif +#endif + + stop_cycles = getCycles(); + stop_retired = getInstRetired(); + num_cycles = stop_cycles - start_cycles; + num_retired = stop_retired - start_retired; + + // -------------------------------------------------- + // Print out the results + +#if HOST_DEBUG + printComplexArray( "results", DATA_SIZE, results_data ); + printComplexArray( "verify ", DATA_SIZE, verify_data ); +#endif + + + // -------------------------------------------------- + // Check the results + int correct = verify( DATA_SIZE, results_data, verify_data ); + finishTest(correct, num_cycles, num_retired); + +} diff --git a/benchmarks/vec-matmul/bmark.mk b/benchmarks/vec-matmul/bmark.mk new file mode 100644 index 0000000..a503f7b --- /dev/null +++ b/benchmarks/vec-matmul/bmark.mk @@ -0,0 +1,30 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +vec_matmul_c_src = \ + vec_matmul_main.c \ + +vec_matmul_riscv_src = \ + crt.S \ + vec_matmul_asm.S + +vec_matmul_c_objs = $(patsubst %.c, %.o, $(vec_matmul_c_src)) +vec_matmul_riscv_objs = $(patsubst %.S, %.o, $(vec_matmul_riscv_src)) + +vec_matmul_host_bin = vec-matmul.host +$(vec_matmul_host_bin) : $(vec_matmul_c_src) + $(HOST_COMP) $^ -o $(vec_matmul_host_bin) + +vec_matmul_riscv_bin = vec-matmul.riscv +$(vec_matmul_riscv_bin) : $(vec_matmul_c_objs) $(vec_matmul_riscv_objs) + $(RISCV_LINK) $(RISCV_LINK_SYSCALL) $(vec_matmul_c_objs) $(vec_matmul_riscv_objs) -o $(vec_matmul_riscv_bin) + +junk += $(vec_matmul_c_objs) $(vec_matmul_riscv_objs) \ + $(vec_matmul_host_bin) $(vec_matmul_riscv_bin) diff --git a/benchmarks/vec-matmul/dataset.h b/benchmarks/vec-matmul/dataset.h new file mode 100644 index 0000000..a2dccb4 --- /dev/null +++ b/benchmarks/vec-matmul/dataset.h @@ -0,0 +1,633 @@ + +#define ARRAY_SIZE 4096 + + +#define DIM_SIZE 64 + +float input1_data[ARRAY_SIZE] = +{ + 0.37, 7.51, 5.09, 1.69, 6.75, 3.16, 1.19, 8.56, 5.26, 7.26, 5.60, 0.06, 8.39, 8.02, 3.54, 6.25, 8.66, 1.00, 1.05, 2.67, + 3.84, 2.83, 5.94, 6.97, 2.88, 6.12, 7.88, 3.40, 4.27, 8.45, 4.86, 5.13, 1.83, 2.53, 6.84, 5.46, 4.61, 5.93, 1.76, 0.74, + 2.41, 2.06, 3.04, 8.51, 8.13, 2.18, 8.23, 7.45, 8.41, 8.88, 1.77, 8.65, 5.11, 3.16, 5.85, 5.92, 1.63, 1.01, 7.74, 0.59, + 2.60, 3.15, 1.28, 8.16, 7.98, 2.38, 5.20, 8.83, 6.86, 2.17, 4.31, 4.50, 3.63, 2.00, 4.00, 6.50, 6.09, 2.86, 2.02, 8.45, + 2.60, 1.08, 5.54, 5.46, 3.51, 3.16, 4.10, 2.51, 3.31, 3.23, 5.26, 0.57, 8.88, 3.63, 3.12, 4.66, 5.04, 8.18, 6.99, 2.30, + 7.02, 5.39, 1.29, 0.31, 1.13, 8.48, 8.41, 7.20, 4.98, 3.89, 5.85, 8.58, 2.59, 0.18, 0.45, 0.78, 0.86, 3.98, 5.29, 5.54, + 3.44, 2.53, 7.28, 8.75, 7.38, 3.11, 4.06, 4.62, 8.70, 3.13, 7.29, 7.95, 4.84, 8.53, 6.32, 3.21, 5.12, 8.03, 0.20, 5.12, + 6.00, 3.81, 3.91, 1.43, 0.02, 0.76, 2.23, 0.45, 3.92, 7.14, 7.83, 4.38, 3.73, 3.33, 4.94, 4.67, 8.00, 6.15, 2.57, 2.38, + 4.50, 2.62, 8.08, 1.94, 6.59, 6.20, 2.26, 7.08, 5.01, 2.72, 4.76, 4.91, 2.90, 8.54, 2.59, 7.42, 2.75, 7.11, 6.61, 8.65, + 3.30, 6.51, 2.65, 8.79, 5.89, 6.75, 0.82, 3.41, 0.95, 0.93, 3.44, 5.87, 7.44, 7.57, 3.22, 1.34, 0.49, 1.26, 8.61, 3.09, + 4.81, 6.82, 4.70, 7.55, 5.34, 0.12, 1.56, 0.57, 1.09, 1.20, 6.83, 3.35, 8.57, 0.36, 1.17, 1.00, 7.64, 3.94, 2.30, 2.43, + 3.69, 5.66, 3.60, 4.95, 6.79, 5.08, 1.54, 0.17, 6.55, 4.52, 7.01, 0.39, 6.79, 0.73, 1.82, 7.69, 1.39, 6.85, 3.22, 8.50, + 8.31, 2.96, 4.47, 3.99, 4.66, 5.78, 2.49, 7.08, 1.03, 7.59, 8.17, 2.48, 2.14, 0.30, 7.07, 5.09, 3.22, 7.24, 7.38, 6.77, + 2.52, 0.77, 4.13, 4.10, 6.40, 4.14, 0.38, 2.28, 3.40, 4.58, 6.31, 7.75, 4.33, 6.68, 4.50, 6.39, 0.45, 3.35, 7.87, 8.52, + 8.94, 4.75, 6.50, 3.92, 2.10, 4.48, 6.29, 0.28, 3.14, 2.26, 3.16, 2.26, 5.17, 7.06, 6.75, 4.53, 7.42, 7.45, 1.53, 1.45, + 6.08, 0.29, 1.82, 1.29, 7.69, 0.81, 3.56, 0.97, 7.70, 0.96, 1.42, 0.05, 6.90, 1.84, 1.76, 5.18, 1.97, 4.74, 1.60, 2.16, + 6.30, 6.82, 6.37, 0.45, 0.76, 7.21, 8.05, 4.62, 3.36, 4.44, 0.13, 5.60, 0.75, 0.93, 7.16, 8.30, 5.79, 7.93, 7.52, 2.16, + 4.16, 1.03, 5.06, 4.77, 0.09, 8.98, 8.15, 3.49, 3.67, 0.95, 5.04, 8.44, 4.62, 3.69, 2.73, 1.82, 3.85, 5.53, 3.24, 4.70, + 6.17, 0.20, 1.67, 2.82, 0.97, 2.48, 3.49, 2.19, 4.38, 0.95, 6.30, 8.10, 6.94, 5.81, 0.73, 1.46, 3.67, 8.52, 0.27, 6.92, + 7.84, 1.03, 1.34, 0.56, 1.33, 7.55, 7.61, 3.90, 1.27, 1.90, 7.36, 7.40, 5.07, 3.28, 5.55, 4.47, 7.32, 8.26, 1.44, 3.88, + 7.24, 1.62, 4.91, 7.57, 4.13, 7.09, 7.86, 7.17, 7.26, 6.83, 0.94, 3.62, 2.29, 8.87, 1.23, 6.57, 5.27, 7.16, 3.74, 4.76, + 6.37, 4.99, 3.41, 6.91, 8.80, 2.13, 8.54, 2.07, 1.49, 4.56, 0.95, 6.35, 7.17, 1.26, 2.74, 7.17, 5.72, 5.05, 1.07, 0.08, + 4.79, 7.33, 0.34, 5.27, 6.67, 5.58, 6.91, 4.31, 0.52, 8.64, 7.07, 8.88, 7.54, 2.77, 0.61, 7.43, 8.98, 6.75, 1.55, 7.44, + 5.60, 1.40, 7.44, 0.39, 6.25, 0.73, 2.13, 6.74, 6.71, 2.40, 1.12, 6.59, 8.49, 3.83, 3.34, 2.89, 2.43, 4.89, 6.88, 6.78, + 8.25, 0.13, 0.01, 8.16, 8.97, 7.30, 5.05, 7.87, 8.76, 2.61, 4.59, 5.03, 8.74, 3.65, 5.22, 2.64, 2.26, 7.66, 1.16, 4.08, + 6.45, 0.78, 6.12, 1.64, 2.17, 3.03, 7.15, 5.78, 0.01, 2.88, 8.89, 5.83, 6.80, 8.64, 1.83, 1.28, 1.62, 2.70, 1.49, 6.86, + 8.78, 5.83, 5.04, 5.58, 3.81, 2.35, 5.10, 4.88, 4.44, 8.93, 6.72, 1.87, 3.36, 8.40, 5.99, 0.31, 4.81, 4.31, 8.19, 1.83, + 0.30, 1.93, 3.30, 8.04, 7.04, 6.13, 6.35, 6.20, 8.53, 3.48, 0.45, 0.91, 4.28, 3.60, 6.12, 2.97, 8.59, 4.25, 4.30, 6.54, + 6.43, 8.45, 4.77, 7.84, 0.70, 4.91, 8.18, 7.69, 1.29, 8.82, 2.16, 0.95, 3.29, 0.89, 0.49, 0.88, 3.96, 6.89, 2.84, 3.03, + 6.28, 6.98, 6.54, 2.92, 2.55, 4.83, 5.61, 5.36, 8.02, 0.68, 2.62, 4.47, 6.54, 4.05, 4.94, 1.22, 5.81, 7.55, 2.61, 6.91, + 1.47, 3.75, 4.43, 8.88, 1.05, 5.57, 7.74, 2.12, 2.55, 5.15, 8.23, 5.05, 1.76, 2.18, 7.05, 8.88, 6.56, 3.10, 3.88, 5.52, + 6.85, 1.59, 2.79, 3.01, 3.19, 2.79, 6.30, 0.42, 4.39, 4.54, 0.91, 3.54, 2.42, 2.83, 0.68, 3.12, 8.90, 5.41, 8.19, 3.47, + 0.83, 4.91, 2.50, 6.02, 3.17, 7.69, 7.78, 2.82, 0.91, 4.80, 5.12, 7.53, 3.34, 8.92, 4.16, 8.22, 1.64, 2.42, 1.44, 6.95, + 0.20, 7.70, 5.81, 0.16, 7.02, 8.21, 7.71, 1.24, 8.86, 6.46, 5.09, 6.48, 2.28, 7.08, 1.39, 1.77, 2.29, 4.03, 8.10, 0.05, + 2.94, 5.55, 2.78, 1.58, 1.44, 1.11, 7.56, 6.45, 4.96, 2.07, 0.74, 5.65, 2.92, 8.35, 0.93, 0.16, 8.71, 1.43, 1.60, 5.35, + 3.36, 3.55, 5.40, 6.72, 3.40, 7.80, 5.33, 4.98, 3.97, 3.12, 5.35, 2.62, 8.18, 4.91, 3.40, 4.11, 7.04, 0.99, 4.47, 8.07, + 7.27, 6.31, 4.94, 3.07, 0.27, 7.48, 5.68, 4.92, 5.53, 8.76, 1.05, 2.83, 8.15, 8.75, 5.47, 7.16, 1.53, 8.08, 4.57, 8.26, + 3.89, 3.06, 1.33, 2.03, 1.01, 5.23, 7.52, 1.21, 8.55, 1.82, 4.40, 3.57, 7.19, 4.31, 6.93, 5.17, 4.37, 3.06, 6.50, 4.06, + 7.40, 6.71, 0.00, 5.36, 2.50, 1.08, 6.13, 6.82, 5.00, 7.64, 4.66, 3.42, 4.56, 8.15, 2.22, 2.19, 3.55, 3.88, 1.93, 2.20, + 4.73, 3.60, 1.56, 2.75, 5.59, 5.36, 4.82, 6.30, 1.44, 6.76, 7.30, 4.10, 0.68, 0.84, 1.51, 0.15, 7.69, 4.46, 2.92, 0.71, + 0.47, 1.01, 0.10, 3.09, 6.58, 6.13, 2.59, 8.66, 0.83, 5.64, 8.22, 5.55, 7.75, 6.70, 6.71, 4.31, 5.54, 4.58, 8.24, 7.30, + 2.60, 8.78, 1.16, 5.23, 4.95, 7.82, 8.84, 2.43, 5.61, 5.88, 5.64, 8.92, 3.48, 2.92, 4.26, 1.48, 2.16, 1.71, 7.79, 2.09, + 3.21, 1.38, 7.44, 2.96, 3.52, 7.64, 0.35, 3.63, 5.56, 4.92, 1.86, 0.02, 7.06, 8.02, 7.34, 7.50, 6.00, 3.70, 0.85, 2.22, + 3.80, 1.91, 6.08, 0.09, 3.37, 3.85, 0.58, 0.48, 6.83, 7.31, 4.51, 3.95, 3.03, 2.96, 2.14, 3.75, 4.22, 6.17, 5.09, 2.75, + 4.05, 5.39, 1.23, 7.95, 3.45, 8.45, 2.42, 1.04, 8.18, 0.45, 8.58, 3.30, 3.58, 2.32, 2.09, 6.01, 0.32, 8.93, 3.99, 1.93, + 3.50, 0.12, 5.60, 0.48, 5.52, 8.42, 8.59, 7.47, 4.16, 5.60, 7.32, 4.71, 6.06, 0.52, 2.82, 3.18, 0.50, 8.76, 6.79, 3.75, + 7.92, 7.79, 5.16, 1.47, 6.50, 0.11, 5.80, 4.57, 8.72, 7.04, 7.57, 2.18, 5.68, 7.30, 7.16, 3.93, 7.98, 5.40, 6.28, 5.80, + 0.84, 6.40, 7.07, 1.01, 5.24, 0.12, 8.32, 5.55, 5.88, 3.24, 2.36, 2.10, 5.49, 6.18, 4.86, 1.06, 5.05, 6.66, 0.18, 2.86, + 8.80, 5.17, 3.48, 6.96, 5.98, 4.55, 1.91, 8.01, 8.17, 3.79, 6.64, 4.65, 0.23, 1.98, 7.19, 6.46, 4.07, 6.23, 6.16, 4.14, + 7.35, 2.92, 5.52, 2.23, 1.05, 3.18, 2.54, 6.66, 2.61, 8.20, 5.81, 5.64, 8.40, 1.98, 6.17, 3.36, 7.89, 5.83, 3.71, 8.61, + 5.98, 7.66, 7.06, 3.54, 6.38, 3.80, 4.72, 6.15, 0.34, 1.41, 0.39, 6.92, 1.12, 4.95, 7.34, 2.26, 1.93, 1.91, 5.16, 8.10, + 8.62, 5.49, 5.87, 3.92, 8.17, 8.75, 5.77, 6.19, 5.78, 2.39, 2.45, 8.76, 7.34, 7.43, 1.09, 4.20, 4.22, 5.69, 2.54, 3.76, + 2.84, 2.12, 5.65, 2.67, 4.53, 0.25, 6.02, 2.94, 5.21, 7.94, 2.74, 3.74, 0.00, 1.80, 8.42, 1.92, 4.83, 0.37, 4.76, 7.53, + 3.14, 3.05, 2.08, 7.86, 3.38, 1.29, 8.97, 3.47, 7.64, 4.39, 5.30, 0.07, 4.39, 6.57, 8.51, 6.21, 7.85, 1.41, 5.62, 2.43, + 0.43, 2.26, 4.43, 7.95, 1.92, 2.09, 2.94, 1.19, 5.81, 3.80, 2.95, 0.52, 6.10, 4.68, 6.99, 2.12, 5.83, 0.86, 2.35, 6.43, + 1.79, 4.44, 8.50, 0.78, 2.01, 7.60, 3.04, 6.78, 0.48, 0.78, 8.01, 2.42, 1.69, 6.59, 4.86, 6.84, 8.67, 5.47, 0.09, 5.05, + 1.10, 8.62, 2.60, 5.45, 1.16, 0.98, 1.58, 5.32, 3.72, 3.12, 2.25, 5.72, 4.64, 7.20, 7.95, 8.47, 1.42, 7.99, 1.55, 8.78, + 8.31, 2.92, 7.06, 7.50, 0.90, 6.96, 6.77, 6.27, 5.86, 8.89, 1.73, 7.19, 0.36, 5.90, 6.86, 8.04, 7.22, 2.50, 4.07, 8.71, + 3.25, 0.58, 8.37, 8.24, 4.83, 2.20, 2.39, 7.93, 5.77, 1.88, 2.73, 2.66, 7.33, 5.17, 3.12, 8.69, 4.35, 5.46, 0.92, 1.10, + 3.92, 4.09, 0.19, 0.63, 0.21, 2.30, 2.49, 8.02, 3.86, 4.89, 5.61, 6.30, 6.97, 2.67, 2.50, 0.94, 0.72, 5.69, 7.35, 7.67, + 6.60, 3.54, 6.85, 1.14, 1.52, 7.60, 1.71, 5.31, 8.44, 2.31, 2.10, 0.68, 1.72, 3.82, 6.77, 6.82, 7.90, 0.43, 7.72, 6.94, + 5.75, 4.40, 1.59, 4.27, 4.16, 5.46, 8.32, 0.00, 5.70, 2.53, 8.36, 2.71, 4.07, 6.34, 6.41, 5.59, 4.00, 7.11, 5.51, 2.09, + 4.78, 7.13, 6.60, 2.60, 6.55, 7.27, 1.55, 8.09, 4.11, 8.49, 5.47, 7.22, 4.53, 6.68, 7.27, 5.71, 8.56, 8.54, 0.37, 3.18, + 1.76, 7.16, 6.31, 2.59, 2.41, 6.98, 5.86, 1.80, 2.38, 2.85, 8.53, 8.47, 5.44, 7.51, 5.76, 4.71, 2.31, 3.77, 2.40, 8.27, + 7.09, 7.05, 4.77, 4.45, 2.72, 1.76, 3.53, 6.58, 8.22, 7.19, 4.26, 7.45, 3.31, 1.04, 2.10, 7.66, 7.70, 4.97, 7.72, 2.83, + 7.41, 3.81, 1.58, 4.24, 7.49, 2.81, 1.86, 1.30, 0.96, 5.75, 1.21, 5.61, 3.96, 8.23, 5.43, 8.98, 5.00, 4.34, 2.04, 2.93, + 7.67, 4.83, 1.21, 1.84, 6.27, 7.13, 1.52, 5.61, 0.78, 4.36, 0.83, 4.25, 4.85, 2.73, 7.01, 6.33, 4.78, 4.14, 8.23, 8.68, + 6.17, 2.95, 1.48, 3.94, 1.34, 0.02, 0.96, 6.69, 2.74, 6.26, 4.54, 0.36, 0.35, 0.64, 5.75, 7.60, 2.34, 4.79, 4.43, 6.25, + 2.51, 8.74, 4.93, 4.54, 8.61, 6.28, 7.59, 2.93, 2.01, 0.76, 6.60, 2.88, 6.34, 8.83, 4.02, 8.04, 6.21, 0.91, 1.77, 3.10, + 5.74, 3.31, 0.43, 7.75, 6.27, 6.53, 1.72, 3.53, 4.60, 8.79, 5.13, 6.52, 6.24, 0.44, 0.44, 0.79, 8.11, 4.38, 3.83, 6.84, + 3.97, 0.52, 5.74, 3.65, 5.69, 1.33, 4.02, 3.34, 8.97, 8.70, 6.58, 6.62, 4.21, 6.22, 2.64, 6.19, 3.91, 3.27, 6.54, 6.65, + 3.34, 6.68, 4.01, 2.79, 2.52, 3.04, 4.53, 4.66, 7.95, 4.86, 1.32, 3.03, 7.11, 0.71, 3.31, 7.72, 3.82, 0.75, 8.30, 0.79, + 4.81, 5.67, 3.09, 5.16, 5.07, 8.93, 4.66, 1.25, 8.37, 6.94, 2.63, 2.03, 5.08, 6.35, 3.44, 5.37, 6.09, 2.09, 5.44, 6.51, + 6.72, 7.39, 0.53, 6.51, 2.31, 6.10, 3.97, 5.27, 4.28, 6.01, 0.84, 3.01, 8.33, 1.87, 6.93, 7.91, 7.42, 4.07, 2.90, 5.40, + 7.81, 2.58, 6.22, 0.91, 1.94, 4.86, 5.95, 1.32, 4.10, 3.07, 6.98, 4.87, 5.22, 6.54, 6.73, 5.38, 6.92, 4.24, 3.74, 7.73, + 7.61, 5.09, 0.53, 8.72, 7.34, 8.81, 3.82, 8.41, 7.31, 0.79, 3.26, 4.74, 1.10, 6.10, 3.31, 2.13, 6.17, 4.51, 5.56, 0.43, + 5.57, 1.67, 3.37, 2.13, 7.75, 6.25, 6.17, 5.25, 0.04, 5.95, 3.64, 5.72, 6.50, 5.69, 4.22, 1.38, 0.00, 6.21, 1.98, 3.88, + 4.72, 8.70, 3.01, 8.97, 1.71, 2.46, 4.89, 0.68, 5.97, 4.16, 8.50, 2.54, 3.13, 1.23, 1.28, 2.44, 7.82, 0.41, 7.61, 3.72, + 4.07, 7.20, 7.54, 1.34, 1.20, 5.22, 3.96, 3.09, 7.16, 1.21, 5.86, 7.72, 3.88, 6.19, 1.79, 4.62, 7.91, 3.12, 5.46, 7.61, + 4.60, 1.81, 2.05, 3.05, 8.98, 5.49, 8.15, 2.94, 2.96, 0.75, 4.96, 3.33, 6.48, 7.07, 4.26, 6.62, 8.26, 7.99, 6.56, 4.74, + 5.94, 8.64, 1.02, 1.39, 6.70, 0.90, 6.02, 0.47, 2.16, 6.65, 6.77, 0.15, 7.63, 8.45, 6.71, 0.70, 3.14, 4.56, 4.69, 5.16, + 2.91, 4.03, 5.26, 8.58, 0.88, 1.11, 5.94, 8.32, 8.46, 8.66, 1.31, 6.44, 0.60, 6.71, 4.30, 5.42, 8.56, 2.51, 8.45, 3.32, + 6.74, 6.68, 7.77, 0.07, 3.57, 1.08, 4.59, 7.61, 0.88, 8.17, 0.75, 1.72, 3.95, 6.36, 4.92, 7.28, 3.24, 3.84, 7.68, 6.90, + 4.96, 4.93, 2.05, 6.12, 5.62, 2.78, 8.29, 8.76, 5.32, 6.75, 5.97, 4.92, 6.73, 2.08, 5.91, 1.33, 0.64, 4.09, 5.05, 7.53, + 5.48, 0.12, 3.33, 1.25, 1.57, 1.89, 4.12, 8.17, 7.51, 1.58, 3.37, 3.76, 2.82, 3.51, 1.40, 8.48, 4.06, 2.55, 8.99, 8.27, + 2.55, 8.65, 1.75, 7.20, 1.12, 0.37, 0.56, 7.92, 2.87, 1.80, 4.62, 6.40, 8.19, 3.06, 4.89, 1.61, 5.32, 1.65, 5.58, 8.75, + 6.33, 6.45, 3.84, 8.75, 8.61, 1.30, 8.30, 0.15, 7.18, 8.33, 8.70, 5.64, 0.06, 0.06, 0.52, 4.73, 2.23, 5.36, 7.82, 1.97, + 6.39, 6.31, 3.10, 4.11, 8.46, 1.42, 0.90, 1.27, 1.96, 0.76, 6.44, 1.35, 5.10, 4.70, 3.17, 4.93, 5.44, 4.85, 6.80, 8.05, + 8.23, 1.74, 3.26, 6.33, 5.66, 5.40, 6.19, 5.45, 1.38, 7.12, 5.44, 4.19, 7.04, 1.55, 4.01, 4.52, 0.41, 1.67, 0.64, 4.04, + 1.81, 1.72, 1.57, 8.48, 2.30, 6.25, 1.36, 5.52, 2.05, 7.07, 7.03, 7.06, 1.62, 0.48, 7.42, 2.96, 6.12, 2.71, 3.65, 8.60, + 8.79, 1.11, 6.12, 1.42, 1.14, 6.64, 8.20, 0.79, 6.54, 4.80, 4.27, 7.99, 6.45, 4.13, 6.93, 3.45, 7.96, 6.46, 2.17, 5.20, + 3.35, 2.16, 8.51, 0.95, 4.20, 0.49, 1.56, 5.85, 3.49, 8.86, 5.87, 3.00, 5.77, 0.61, 6.97, 2.54, 6.56, 6.41, 0.74, 7.82, + 5.72, 8.04, 0.11, 5.63, 5.49, 5.55, 4.33, 4.16, 1.47, 4.20, 4.24, 5.58, 1.05, 2.81, 1.68, 6.50, 6.93, 1.30, 6.58, 3.81, + 8.53, 5.12, 4.26, 3.43, 7.09, 6.40, 4.23, 6.57, 5.09, 1.28, 3.09, 7.12, 7.43, 8.85, 0.19, 4.35, 2.81, 4.62, 5.40, 7.24, + 8.66, 4.13, 3.43, 6.95, 2.63, 5.68, 7.62, 3.92, 0.64, 6.61, 8.10, 8.23, 0.55, 8.87, 2.20, 8.43, 8.65, 5.67, 1.31, 0.07, + 3.95, 5.32, 1.48, 1.77, 2.18, 2.15, 6.08, 4.10, 8.87, 6.47, 0.75, 5.36, 1.01, 3.26, 6.48, 2.29, 8.51, 4.07, 3.12, 6.50, + 4.23, 0.18, 8.89, 0.37, 6.33, 3.63, 5.91, 5.20, 0.43, 0.17, 0.97, 1.74, 0.63, 1.55, 3.57, 1.72, 4.30, 6.81, 3.92, 4.34, + 8.37, 3.35, 1.46, 6.83, 4.26, 6.71, 1.84, 0.48, 0.51, 2.88, 0.92, 6.50, 4.94, 4.92, 2.53, 6.90, 1.44, 6.36, 8.51, 3.87, + 8.61, 0.68, 8.88, 1.30, 3.97, 7.55, 7.33, 2.36, 6.86, 4.36, 6.70, 4.18, 2.10, 2.52, 1.80, 3.43, 2.14, 0.80, 4.78, 6.86, + 4.56, 8.82, 6.26, 4.33, 8.98, 0.24, 3.34, 6.76, 2.71, 1.92, 3.38, 1.91, 4.99, 5.61, 3.28, 8.60, 3.45, 8.26, 8.19, 1.23, + 1.92, 5.99, 8.87, 4.88, 6.12, 2.39, 7.14, 3.52, 4.44, 0.30, 5.79, 5.90, 2.60, 4.83, 2.61, 3.94, 4.38, 3.65, 6.57, 2.19, + 0.99, 5.84, 8.72, 4.90, 7.66, 8.99, 6.03, 6.02, 3.77, 8.07, 8.44, 8.07, 3.00, 4.78, 6.10, 5.49, 8.09, 6.89, 1.22, 4.39, + 0.26, 8.00, 2.15, 0.28, 8.79, 7.83, 2.73, 1.47, 7.08, 1.66, 4.82, 2.03, 4.18, 3.37, 4.39, 4.46, 3.90, 1.57, 2.82, 2.06, + 7.67, 4.14, 1.86, 3.15, 6.80, 2.17, 8.32, 0.79, 6.94, 6.13, 5.56, 2.79, 3.62, 3.51, 4.83, 7.05, 3.98, 2.61, 2.92, 3.14, + 1.28, 8.84, 6.70, 7.30, 1.45, 7.71, 6.01, 3.48, 1.36, 1.31, 0.67, 6.24, 1.02, 6.96, 5.65, 5.71, 2.17, 0.70, 1.07, 8.49, + 0.71, 4.29, 6.19, 7.86, 2.14, 6.27, 2.59, 2.22, 7.35, 4.08, 2.54, 0.45, 8.05, 3.20, 3.79, 8.00, 1.74, 3.53, 6.26, 7.57, + 0.44, 4.99, 6.66, 6.21, 3.07, 0.22, 4.53, 0.81, 8.36, 7.99, 8.00, 8.63, 3.70, 4.72, 8.58, 2.15, 7.18, 5.89, 0.34, 2.41, + 6.41, 4.71, 7.80, 1.52, 3.16, 7.77, 2.78, 0.17, 2.57, 0.74, 8.48, 0.82, 4.98, 5.15, 8.94, 1.09, 2.10, 1.83, 5.18, 3.34, + 7.44, 6.97, 2.70, 2.33, 2.88, 6.38, 4.91, 3.98, 7.04, 2.64, 5.75, 4.93, 6.13, 5.19, 1.73, 1.80, 8.19, 3.51, 5.94, 5.19, + 5.99, 0.49, 8.51, 4.70, 8.17, 0.27, 4.94, 1.16, 1.17, 1.27, 2.84, 7.26, 5.08, 0.37, 2.77, 0.65, 6.46, 2.44, 6.46, 6.04, + 3.56, 5.31, 0.14, 1.97, 8.44, 2.45, 6.53, 1.93, 3.89, 6.35, 2.74, 1.38, 0.86, 8.45, 5.76, 4.33, 7.68, 7.18, 4.88, 2.68, + 3.24, 7.19, 4.26, 0.20, 3.50, 3.44, 4.08, 6.82, 4.80, 8.19, 6.35, 6.25, 5.88, 4.18, 1.57, 6.15, 2.90, 6.79, 4.01, 0.93, + 7.74, 2.59, 8.84, 1.73, 1.34, 5.29, 7.57, 2.92, 5.12, 3.71, 1.50, 1.03, 7.44, 7.19, 7.79, 7.16, 3.68, 2.94, 7.33, 0.67, + 5.57, 1.14, 7.51, 4.79, 8.46, 0.38, 4.22, 6.21, 4.62, 7.38, 2.42, 0.58, 0.84, 3.50, 8.21, 8.07, 6.67, 0.50, 8.74, 6.50, + 7.65, 8.65, 5.05, 6.07, 7.68, 1.92, 3.81, 1.59, 0.85, 8.35, 1.88, 6.29, 8.07, 7.48, 7.85, 3.51, 7.40, 1.39, 0.97, 6.03, + 4.48, 2.95, 6.43, 3.08, 1.00, 3.17, 5.59, 3.26, 8.13, 7.34, 0.41, 1.85, 4.92, 1.89, 8.54, 5.79, 2.42, 5.40, 4.36, 7.67, + 0.23, 6.39, 5.78, 0.01, 6.89, 1.63, 5.76, 7.47, 0.96, 0.85, 8.31, 2.91, 2.59, 7.70, 7.44, 1.93, 3.07, 1.62, 0.17, 8.85, + 7.36, 2.14, 8.14, 8.78, 2.23, 8.83, 0.22, 4.15, 6.80, 2.60, 3.06, 6.81, 7.96, 7.72, 0.08, 0.52, 6.82, 6.20, 7.78, 1.81, + 1.34, 5.62, 3.44, 4.02, 7.92, 5.57, 3.06, 2.14, 2.54, 3.14, 6.50, 0.82, 0.79, 2.80, 6.22, 8.54, 1.96, 7.09, 5.31, 7.20, + 3.90, 8.27, 0.22, 8.43, 6.35, 5.93, 0.38, 8.36, 3.92, 5.08, 2.60, 2.83, 3.71, 2.03, 7.62, 0.15, 4.29, 5.64, 0.90, 6.58, + 3.43, 7.94, 5.66, 7.70, 2.47, 5.57, 5.26, 0.56, 5.16, 6.38, 4.01, 2.51, 6.34, 2.00, 3.26, 6.02, 3.38, 1.78, 4.60, 1.61, + 4.93, 2.85, 0.22, 3.33, 2.53, 5.47, 0.78, 4.76, 8.58, 0.82, 6.60, 4.66, 1.33, 5.94, 6.72, 3.81, 6.02, 5.02, 7.03, 7.40, + 6.55, 4.70, 4.72, 3.70, 3.08, 0.53, 2.34, 7.37, 3.36, 2.66, 6.10, 5.75, 3.91, 5.43, 1.46, 1.19, 1.04, 4.17, 0.42, 5.15, + 5.10, 0.87, 5.07, 8.22, 4.78, 8.95, 2.37, 2.88, 2.90, 7.36, 6.55, 0.99, 0.62, 0.76, 2.56, 7.41, 7.49, 6.39, 2.27, 4.17, + 6.95, 6.36, 8.93, 3.94, 6.12, 2.93, 5.60, 3.26, 5.10, 4.21, 7.69, 6.03, 8.37, 4.51, 7.06, 8.69, 4.88, 3.97, 7.90, 0.83, + 2.91, 0.91, 5.41, 2.09, 8.08, 8.62, 3.05, 6.34, 8.68, 3.64, 2.66, 6.70, 4.39, 5.01, 0.38, 2.39, 0.12, 8.81, 2.43, 4.36, + 1.18, 4.88, 0.77, 3.21, 1.98, 0.93, 7.88, 8.49, 1.10, 7.81, 3.33, 1.83, 2.99, 0.87, 0.33, 1.97, 5.49, 2.65, 3.16, 4.66, + 6.07, 1.03, 7.29, 8.93, 6.93, 0.33, 6.82, 8.06, 4.17, 2.29, 2.36, 4.73, 8.65, 3.17, 2.46, 4.63, 5.86, 0.49, 2.44, 0.69, + 2.43, 6.98, 3.87, 1.62, 3.15, 6.37, 1.06, 3.43, 1.18, 8.66, 1.54, 8.64, 1.17, 5.25, 8.77, 0.76, 8.60, 3.11, 7.70, 8.60, + 6.86, 7.94, 5.95, 2.52, 8.36, 0.57, 6.10, 8.60, 1.66, 4.63, 2.53, 4.91, 3.66, 7.74, 6.57, 0.07, 6.77, 4.66, 5.40, 0.98, + 5.42, 8.34, 1.95, 1.50, 0.70, 5.54, 2.44, 0.55, 4.16, 7.94, 4.92, 8.54, 0.00, 6.61, 2.58, 6.72, 8.35, 3.13, 2.62, 2.28, + 4.46, 5.11, 2.34, 6.47, 0.07, 7.50, 2.27, 6.97, 5.10, 4.70, 3.56, 8.31, 2.84, 7.95, 1.09, 1.55, 3.86, 5.54, 2.52, 8.94, + 0.31, 6.21, 4.31, 4.72, 4.74, 1.52, 7.44, 7.17, 3.98, 5.77, 0.94, 7.47, 1.75, 3.44, 0.19, 5.79, 4.18, 4.43, 7.75, 5.12, + 0.03, 0.87, 2.74, 7.03, 8.07, 1.17, 5.52, 5.54, 0.94, 3.31, 6.48, 0.81, 2.20, 1.30, 8.46, 8.97, 0.92, 5.72, 1.70, 0.96, + 3.14, 5.78, 5.58, 2.55, 2.55, 5.57, 4.63, 7.06, 1.93, 0.26, 1.21, 5.62, 2.06, 2.00, 8.95, 5.60, 6.64, 6.35, 5.93, 6.32, + 1.10, 0.69, 6.72, 0.61, 2.13, 8.11, 2.80, 1.04, 2.76, 4.66, 1.00, 2.99, 8.80, 0.65, 5.52, 8.76, 7.94, 0.88, 6.63, 0.12, + 0.97, 5.46, 3.86, 6.42, 3.56, 8.64, 2.12, 1.57, 6.18, 6.89, 7.61, 3.66, 8.46, 5.88, 4.44, 6.87, 6.53, 0.74, 6.86, 0.79, + 1.70, 2.10, 0.12, 4.82, 3.85, 6.08, 1.32, 7.72, 1.66, 6.35, 8.14, 7.64, 0.32, 1.54, 1.94, 7.15, 8.31, 1.55, 3.41, 0.04, + 8.81, 1.88, 0.23, 8.42, 0.41, 2.26, 7.78, 9.00, 2.17, 6.53, 1.85, 7.64, 1.53, 5.26, 0.99, 7.77, 1.05, 4.32, 7.46, 5.12, + 6.13, 4.99, 7.87, 8.50, 7.13, 4.70, 5.82, 8.19, 0.22, 4.51, 0.79, 7.37, 3.80, 5.08, 1.76, 3.90, 7.18, 0.42, 5.26, 6.26, + 5.66, 4.23, 4.45, 5.23, 1.77, 3.20, 6.86, 4.24, 5.40, 2.67, 3.00, 6.75, 5.60, 3.61, 7.27, 7.44, 1.88, 5.63, 3.49, 2.93, + 4.36, 5.27, 2.91, 0.16, 7.47, 1.06, 5.78, 8.46, 4.65, 2.58, 4.35, 2.11, 7.15, 4.53, 7.83, 4.37, 1.34, 1.45, 0.77, 6.32, + 5.62, 4.30, 1.40, 5.77, 6.61, 2.68, 0.86, 8.01, 4.64, 1.70, 6.19, 8.38, 6.18, 4.85, 5.14, 4.44, 6.40, 2.60, 2.93, 5.39, + 7.43, 5.05, 0.47, 0.70, 6.31, 6.78, 6.04, 7.22, 4.38, 4.90, 7.25, 4.62, 3.94, 8.30, 5.66, 8.15, 1.66, 4.61, 4.69, 5.64, + 8.75, 4.22, 6.35, 7.96, 8.04, 6.07, 2.90, 6.18, 1.76, 2.39, 4.66, 1.05, 2.17, 3.18, 2.01, 5.64, 5.56, 2.94, 2.46, 0.72, + 1.41, 2.96, 3.30, 1.36, 3.18, 2.92, 1.68, 6.47, 7.18, 6.15, 6.13, 1.14, 6.58, 3.13, 0.78, 4.56, 6.99, 4.25, 7.31, 7.95, + 2.04, 7.92, 6.21, 4.23, 0.12, 7.31, 3.84, 3.05, 5.55, 1.86, 2.67, 6.28, 6.73, 1.91, 2.56, 0.73, 4.98, 6.21, 7.87, 0.88, + 4.71, 2.11, 5.94, 7.28, 8.72, 5.79, 7.09, 3.84, 1.72, 7.29, 8.92, 6.94, 8.95, 6.70, 5.87, 7.77, 1.96, 7.18, 7.88, 0.84, + 2.87, 1.71, 0.47, 5.72, 7.99, 5.56, 6.81, 1.45, 1.38, 0.70, 0.99, 4.37, 1.35, 0.30, 8.44, 3.73, 2.25, 6.15, 1.35, 8.82, + 1.83, 3.90, 6.90, 2.11, 5.55, 5.60, 8.45, 8.42, 0.88, 1.50, 1.04, 7.23, 8.00, 0.78, 2.20, 4.43, 8.14, 7.14, 4.66, 0.64, + 4.58, 5.55, 6.34, 5.26, 2.42, 2.76, 5.14, 2.17, 1.39, 1.04, 2.05, 7.65, 3.38, 6.11, 4.29, 3.74, 0.68, 0.60, 4.02, 2.01, + 5.84, 2.73, 7.33, 2.50, 2.59, 1.39, 8.28, 6.85, 6.52, 1.43, 8.49, 8.87, 6.99, 6.78, 1.02, 3.95, 4.45, 7.15, 5.43, 5.78, + 1.32, 8.84, 3.24, 8.69, 2.58, 4.05, 5.61, 0.08, 3.64, 2.65, 2.90, 7.76, 4.22, 8.19, 7.29, 3.09, 6.91, 7.15, 6.01, 3.10, + 0.23, 8.16, 3.68, 4.57, 6.49, 6.81, 8.63, 6.91, 8.34, 1.52, 6.64, 6.80, 6.31, 0.28, 8.98, 5.83, 2.85, 3.94, 7.73, 7.34, + 1.05, 2.86, 0.93, 4.94, 7.56, 0.36, 3.60, 1.78, 5.54, 4.46, 0.62, 2.97, 5.79, 7.61, 8.07, 7.54, 7.02, 4.30, 7.10, 4.92, + 7.82, 6.20, 2.29, 4.47, 6.03, 2.59, 7.02, 0.03, 6.04, 5.37, 1.88, 4.91, 8.08, 2.93, 0.90, 6.73, 0.69, 3.51, 8.01, 0.33, + 1.39, 0.22, 3.60, 0.05, 2.02, 4.56, 7.66, 1.86, 3.31, 3.16, 0.80, 7.59, 7.13, 1.07, 1.63, 7.21, 8.17, 7.84, 7.70, 5.14, + 5.94, 7.81, 5.06, 7.79, 4.80, 2.81, 0.35, 1.36, 1.01, 7.44, 3.46, 8.15, 8.91, 7.80, 5.22, 1.20, 1.13, 4.37, 2.56, 4.93, + 3.94, 5.86, 4.91, 8.10, 4.96, 7.91, 6.39, 0.98, 1.28, 0.53, 4.16, 1.96, 2.04, 1.38, 3.55, 6.38, 0.87, 8.62, 8.51, 3.45, + 3.05, 1.63, 7.50, 7.42, 4.54, 8.32, 3.32, 4.23, 5.15, 0.40, 1.22, 3.84, 2.64, 8.93, 5.04, 4.18, 7.67, 4.21, 7.84, 0.96, + 0.90, 5.47, 6.75, 2.54, 6.55, 4.83, 6.82, 7.37, 3.46, 6.79, 2.57, 8.65, 6.33, 2.53, 2.89, 1.29, 5.46, 4.06, 7.42, 4.84, + 0.52, 8.63, 7.86, 1.95, 5.79, 0.85, 0.08, 3.38, 8.69, 1.03, 4.00, 6.45, 7.86, 2.90, 7.70, 8.74, 8.64, 6.85, 4.55, 5.00, + 5.39, 3.53, 3.17, 4.53, 0.39, 2.15, 5.55, 1.49, 6.56, 2.27, 8.96, 5.76, 8.99, 5.56, 3.20, 4.73, 8.24, 6.97, 2.33, 3.54, + 6.24, 6.27, 1.20, 3.00, 4.91, 7.79, 2.06, 0.07, 3.91, 8.54, 6.97, 8.50, 2.53, 3.48, 8.11, 1.65, 6.12, 8.86, 8.69, 0.01, + 0.67, 1.07, 7.89, 1.26, 5.76, 3.35, 8.42, 7.87, 7.34, 1.92, 3.86, 2.57, 5.27, 8.06, 8.85, 2.84, 0.55, 7.50, 1.86, 4.69, + 8.23, 5.20, 6.49, 8.82, 4.52, 8.61, 0.38, 4.01, 2.32, 0.49, 1.17, 6.24, 1.01, 4.77, 5.45, 8.77, 1.82, 1.20, 7.33, 5.58, + 1.21, 4.07, 8.12, 1.42, 3.66, 5.52, 0.46, 6.54, 3.15, 0.62, 7.58, 1.79, 1.67, 6.35, 4.48, 1.61, 2.60, 1.39, 3.36, 8.58, + 7.54, 5.67, 6.19, 5.14, 2.92, 5.27, 8.24, 3.84, 2.62, 1.98, 5.90, 1.23, 7.29, 1.37, 0.81, 0.35, 7.62, 5.63, 2.88, 2.89, + 6.29, 2.06, 8.77, 6.10, 0.76, 3.94, 4.39, 3.40, 2.85, 2.26, 3.32, 7.26, 2.12, 7.33, 5.16, 7.86, 1.86, 1.83, 7.49, 1.32, + 4.96, 4.14, 3.88, 2.15, 2.11, 5.37, 3.98, 6.39, 4.44, 4.54, 7.88, 7.04, 3.35, 5.44, 4.99, 1.70, 7.06, 5.93, 7.05, 7.10, + 7.53, 3.21, 0.20, 8.93, 5.51, 1.64, 7.87, 5.44, 4.59, 5.07, 5.66, 3.82, 5.05, 4.82, 4.83, 7.73, 7.35, 8.53, 6.41, 7.13, + 0.41, 6.92, 2.84, 1.97, 4.36, 1.67, 2.03, 4.12, 2.83, 0.01, 8.28, 2.69, 7.80, 2.80, 6.54, 0.89, 2.86, 4.98, 7.84, 5.90, + 6.70, 7.16, 0.22, 6.35, 8.97, 5.26, 1.30, 8.80, 7.11, 6.75, 4.22, 0.70, 6.98, 2.70, 3.86, 8.05, 1.12, 8.80, 1.28, 7.60, + 3.09, 0.62, 7.72, 0.21, 5.60, 7.24, 3.75, 2.39, 8.83, 0.32, 3.03, 1.49, 8.27, 8.31, 5.66, 3.28, 0.24, 0.44, 7.28, 7.16, + 2.46, 6.19, 7.73, 1.02, 2.27, 0.04, 0.95, 2.03, 6.51, 5.16, 0.45, 6.68, 1.86, 8.25, 1.90, 0.95, 1.80, 6.87, 8.59, 3.62, + 7.63, 2.79, 0.66, 1.22, 4.90, 0.55, 5.87, 6.52, 8.76, 6.94, 2.92, 1.46, 5.21, 5.27, 5.59, 0.26, 2.68, 6.50, 4.62, 0.14, + 6.13, 8.68, 5.47, 2.01, 1.67, 6.86, 6.58, 6.93, 4.65, 8.79, 6.92, 5.74, 3.37, 1.49, 6.44, 2.65, 7.88, 7.64, 7.62, 2.97, + 1.87, 3.11, 7.48, 2.28, 6.94, 6.00, 3.12, 5.66, 1.90, 3.48, 4.59, 8.50, 2.12, 5.53, 8.68, 8.40, 0.30, 8.77, 0.32, 5.63, + 4.42, 8.80, 6.68, 0.27, 0.61, 2.59, 6.88, 1.88, 3.74, 1.34, 6.42, 4.17, 2.79, 6.43, 1.55, 4.46, 4.31, 0.53, 8.94, 6.47, + 2.09, 3.98, 2.85, 2.80, 5.26, 6.95, 5.24, 2.12, 6.79, 2.55, 5.35, 1.92, 4.28, 1.58, 3.14, 4.74, 5.20, 2.61, 8.00, 5.89, + 5.87, 8.90, 8.53, 8.27, 4.20, 0.16, 4.50, 6.73, 8.60, 4.90, 5.83, 6.20, 2.29, 4.49, 3.92, 0.16, 2.36, 0.36, 2.84, 5.48, + 5.70, 2.38, 8.61, 7.31, 8.54, 2.06, 0.36, 1.55, 0.30, 0.06, 4.20, 2.03, 0.59, 6.77, 1.27, 0.20, 1.17, 6.25, 1.18, 6.49, + 3.45, 5.13, 4.83, 3.16, 7.13, 2.19, 7.36, 7.34, 6.78, 1.73, 6.58, 2.64, 4.63, 0.49, 2.10, 4.39, 3.97, 6.15, 7.98, 5.08, + 5.76, 0.19, 3.40, 1.78, 3.31, 5.59, 6.58, 8.09, 8.26, 7.44, 5.91, 5.95, 3.95, 4.47, 2.64, 0.16, 1.79, 5.46, 2.55, 7.09, + 3.36, 2.19, 6.20, 1.63, 2.94, 2.97, 7.49, 3.58, 6.52, 7.62, 4.15, 5.07, 4.64, 4.15, 0.46, 5.82, 0.05, 2.41, 1.85, 8.97, + 6.89, 6.65, 2.63, 2.47, 0.89, 1.01, 4.22, 7.52, 1.17, 1.51, 1.71, 0.83, 3.46, 6.85, 1.47, 8.72, 7.79, 4.77, 3.90, 3.06, + 2.23, 8.28, 8.83, 2.26, 7.03, 0.23, 6.78, 7.30, 8.11, 7.21, 4.90, 7.73, 3.00, 7.67, 4.43, 8.11, 6.32, 3.40, 2.61, 3.34, + 2.34, 7.38, 3.19, 8.56, 3.34, 3.94, 2.86, 4.94, 7.35, 2.95, 2.02, 4.98, 7.34, 3.40, 6.21, 1.20, 8.15, 2.49, 1.25, 6.35, + 4.11, 8.57, 8.34, 1.25, 5.91, 6.97, 7.18, 8.50, 2.32, 3.94, 6.12, 3.96, 2.23, 6.12, 1.94, 7.97, 7.76, 8.18, 7.51, 5.90, + 0.36, 3.20, 3.44, 6.99, 4.77, 5.38, 4.53, 5.47, 2.64, 1.58, 0.36, 8.85, 7.15, 4.71, 6.10, 7.87, 0.44, 5.89, 8.57, 4.94, + 0.04, 7.85, 4.64, 1.74, 8.59, 2.23, 2.33, 1.92, 1.79, 7.34, 4.36, 6.83, 0.86, 1.61, 7.21, 4.86, 8.75, 6.66, 7.99, 5.97, + 1.14, 7.80, 4.60, 0.50, 2.32, 0.69, 4.27, 0.06, 2.33, 7.04, 2.25, 4.72, 2.00, 1.83, 1.26, 4.04, 8.14, 7.38, 6.15, 7.00, + 5.97, 1.13, 8.59, 1.94, 0.17, 4.68, 0.70, 6.54, 5.69, 7.91, 0.04, 7.57, 4.08, 6.42, 1.12, 4.06, 1.43, 7.89, 7.06, 1.38, + 7.84, 3.87, 1.33, 4.71, 2.59, 5.86, 1.16, 2.46, 0.07, 1.35, 2.87, 8.53, 7.61, 6.29, 8.33, 5.92, 3.18, 6.58, 6.69, 3.32, + 5.43, 3.40, 0.87, 3.99, 4.80, 5.27, 4.62, 3.91, 6.93, 0.75, 5.21, 5.63, 8.60, 8.62, 1.05, 4.23, 8.90, 1.23, 2.70, 7.37, + 4.67, 3.23, 7.19, 7.63, 2.40, 0.96, 3.55, 5.79, 3.85, 4.64, 6.65, 6.29, 4.58, 4.75, 1.12, 8.92, 3.81, 3.58, 1.46, 7.78, + 5.22, 1.77, 2.47, 6.31, 8.82, 1.45, 6.80, 2.11, 0.73, 4.81, 8.81, 3.62, 2.33, 0.89, 8.79, 7.67, 2.27, 6.29, 2.23, 4.94, + 7.95, 8.18, 1.39, 4.09, 6.18, 3.77, 5.88, 8.37, 7.41, 8.00, 4.14, 2.84, 7.04, 6.70, 8.42, 1.29, 8.60, 7.80, 1.24, 5.03, + 0.89, 1.65, 4.56, 7.54, 0.70, 8.63, 5.33, 2.91, 0.48, 8.27, 0.82, 6.46, 4.07, 4.43, 1.83, 3.87, 5.68, 0.67, 8.93, 5.31, + 1.46, 6.00, 8.85, 3.92, 0.26, 2.06, 6.54, 8.74, 7.58, 7.04, 3.85, 2.14, 3.71, 5.75, 0.07, 0.23, 5.12, 1.19, 1.78, 5.42, + 1.97, 7.87, 2.90, 7.68, 8.88, 7.88, 4.16, 2.48, 6.02, 7.48, 5.26, 3.57, 8.49, 4.39, 0.42, 5.09, 3.78, 2.84, 5.50, 4.35, + 1.84, 5.37, 6.58, 4.87, 4.86, 6.06, 3.61, 6.99, 0.37, 2.91, 2.88, 2.18, 1.96, 1.35, 4.10, 5.97, 6.64, 3.73, 3.08, 4.95, + 8.10, 8.68, 5.74, 2.90, 2.96, 7.15, 4.45, 5.39, 6.85, 2.51, 2.68, 4.71, 0.99, 2.96, 1.80, 8.04, 6.37, 4.85, 5.93, 8.14, + 6.53, 8.20, 7.95, 4.57, 2.80, 7.94, 6.29, 6.84, 7.93, 1.68, 7.46, 0.23, 3.39, 5.19, 0.19, 5.40, 8.90, 4.53, 6.73, 0.91, + 0.46, 6.23, 4.04, 0.04, 2.61, 8.29, 3.58, 7.20, 5.91, 4.19, 2.94, 4.94, 2.25, 3.23, 7.87, 0.94 +}; + +float input2_data[ARRAY_SIZE] = +{ + 4.09, 3.02, 0.02, 8.91, 3.30, 5.16, 0.58, 1.38, 1.95, 1.26, 1.90, 5.16, 3.06, 5.34, 8.09, 2.06, 0.11, 7.96, 6.76, 5.82, + 4.51, 3.93, 6.32, 7.32, 8.84, 1.36, 6.27, 5.08, 2.45, 2.33, 5.83, 4.59, 0.80, 6.34, 6.04, 3.38, 4.97, 8.44, 5.34, 5.13, + 8.58, 7.22, 5.26, 5.79, 3.32, 4.41, 2.96, 2.82, 5.34, 3.50, 4.90, 5.85, 8.82, 8.99, 7.34, 0.71, 1.88, 8.99, 5.67, 7.63, + 6.35, 8.98, 2.28, 6.45, 3.87, 3.74, 4.85, 6.31, 0.04, 4.46, 0.90, 7.79, 6.25, 3.75, 2.67, 2.58, 5.59, 0.71, 3.17, 4.87, + 5.83, 1.53, 4.75, 2.61, 7.17, 7.22, 6.49, 6.84, 6.72, 0.83, 8.91, 2.44, 7.69, 7.10, 4.79, 2.01, 4.15, 2.18, 3.23, 2.99, + 6.17, 6.67, 4.02, 2.81, 6.70, 5.02, 4.32, 5.02, 8.34, 7.17, 3.22, 8.03, 6.00, 4.64, 5.03, 7.84, 7.69, 3.97, 0.55, 6.12, + 3.57, 0.09, 0.16, 1.54, 2.62, 3.43, 4.83, 1.67, 8.26, 4.86, 8.86, 8.00, 0.49, 5.52, 8.57, 4.32, 1.36, 0.07, 5.78, 3.02, + 6.58, 0.86, 6.56, 2.53, 3.56, 6.20, 8.21, 4.30, 7.34, 6.57, 2.39, 1.15, 2.13, 1.93, 1.63, 0.06, 4.54, 5.37, 1.56, 5.80, + 3.13, 5.40, 0.62, 7.66, 5.93, 5.58, 1.10, 1.19, 7.47, 6.01, 3.91, 4.40, 6.79, 1.13, 5.65, 0.13, 0.10, 3.64, 0.95, 6.34, + 7.37, 8.69, 3.66, 7.88, 7.72, 0.78, 0.54, 5.95, 6.02, 1.38, 1.09, 0.88, 3.72, 2.13, 0.11, 3.82, 8.70, 1.95, 5.60, 3.26, + 8.30, 6.44, 5.83, 2.70, 7.99, 6.15, 0.33, 4.45, 4.96, 4.84, 8.74, 5.79, 3.91, 3.74, 2.73, 3.95, 7.75, 1.83, 4.31, 8.90, + 6.08, 6.48, 8.92, 3.05, 4.06, 5.70, 1.40, 5.83, 4.08, 3.85, 4.59, 8.91, 3.84, 0.11, 4.35, 1.28, 3.06, 3.52, 0.46, 1.54, + 5.42, 0.95, 8.73, 1.09, 7.93, 0.74, 7.84, 5.41, 5.44, 7.85, 8.00, 5.50, 3.65, 2.11, 6.72, 4.74, 2.48, 3.98, 2.04, 6.78, + 8.50, 6.54, 6.39, 1.81, 0.49, 6.83, 0.48, 3.58, 0.37, 1.27, 3.75, 6.74, 1.98, 4.31, 6.94, 1.62, 4.35, 6.23, 6.53, 1.56, + 1.68, 8.24, 0.01, 8.68, 2.23, 4.19, 3.27, 4.70, 2.11, 1.09, 0.37, 7.02, 1.76, 1.45, 6.70, 3.96, 3.21, 3.63, 1.27, 5.70, + 2.61, 7.05, 2.88, 5.73, 1.07, 7.68, 0.64, 7.35, 3.50, 8.60, 0.32, 0.15, 6.29, 6.27, 6.10, 5.39, 7.96, 7.43, 6.73, 4.17, + 4.61, 4.81, 3.97, 3.86, 6.60, 6.55, 6.33, 4.93, 0.78, 7.20, 1.94, 0.20, 5.87, 0.54, 3.87, 5.93, 0.87, 8.77, 5.94, 8.70, + 4.72, 0.56, 5.63, 2.73, 6.44, 3.69, 0.50, 6.57, 2.75, 3.93, 8.12, 5.34, 6.23, 7.18, 4.48, 1.60, 8.48, 8.97, 4.33, 1.43, + 7.41, 5.51, 6.13, 0.13, 1.01, 7.18, 1.67, 0.00, 6.48, 0.87, 6.75, 6.66, 7.33, 3.92, 2.94, 0.34, 0.31, 5.46, 8.43, 0.24, + 0.80, 3.98, 3.06, 3.10, 4.99, 3.29, 8.60, 5.76, 3.57, 8.93, 2.25, 3.05, 7.50, 8.78, 3.55, 2.40, 4.24, 3.14, 3.03, 3.78, + 2.25, 1.95, 4.89, 8.14, 5.73, 6.58, 5.24, 7.39, 6.05, 8.82, 3.77, 6.04, 8.29, 5.12, 6.71, 5.97, 1.25, 3.48, 8.36, 1.56, + 4.12, 2.85, 1.66, 4.30, 1.77, 3.60, 3.75, 7.26, 8.98, 2.43, 6.63, 6.28, 7.44, 4.76, 0.46, 5.62, 4.84, 0.79, 2.65, 7.82, + 0.99, 3.59, 7.04, 5.83, 3.38, 8.50, 8.08, 5.31, 0.40, 2.60, 7.62, 6.69, 0.89, 4.71, 4.00, 3.89, 1.49, 8.39, 0.26, 4.16, + 2.92, 2.46, 3.39, 3.07, 8.09, 1.43, 1.52, 4.00, 1.75, 5.69, 8.43, 2.47, 7.04, 1.67, 5.58, 2.63, 8.41, 1.41, 7.45, 0.80, + 8.90, 5.67, 5.85, 0.29, 0.01, 6.71, 3.60, 8.25, 7.13, 5.00, 8.87, 4.78, 5.41, 3.62, 6.15, 4.87, 8.14, 1.09, 8.97, 4.70, + 5.61, 2.02, 8.07, 4.78, 7.39, 5.87, 2.04, 0.87, 2.37, 5.13, 2.15, 1.14, 5.50, 1.73, 2.15, 7.18, 7.97, 5.16, 0.97, 1.27, + 7.11, 7.68, 0.21, 6.35, 8.02, 4.33, 0.48, 3.36, 1.81, 4.92, 3.68, 1.08, 5.82, 4.19, 0.74, 2.64, 0.47, 7.93, 2.02, 6.71, + 6.63, 7.98, 1.51, 0.02, 4.79, 2.90, 1.52, 4.38, 0.92, 1.60, 0.39, 6.38, 5.90, 8.25, 5.64, 2.18, 7.41, 7.17, 5.78, 2.27, + 2.21, 1.36, 7.90, 3.00, 5.41, 8.46, 6.98, 3.58, 2.11, 6.81, 4.09, 3.82, 1.89, 8.67, 8.12, 8.32, 5.91, 4.77, 5.36, 0.82, + 4.19, 6.18, 0.63, 6.80, 0.29, 4.46, 0.23, 3.51, 4.40, 0.34, 3.69, 5.76, 0.25, 8.57, 4.86, 0.73, 2.73, 6.52, 6.62, 1.13, + 4.98, 2.24, 0.97, 3.26, 0.44, 7.83, 1.30, 7.58, 6.53, 3.02, 4.24, 2.37, 3.09, 7.29, 6.10, 3.06, 3.03, 3.70, 4.19, 0.51, + 5.32, 4.38, 3.66, 8.95, 6.72, 2.15, 4.73, 3.03, 2.31, 1.21, 4.92, 6.51, 3.31, 8.50, 0.96, 5.67, 3.57, 1.88, 3.87, 4.72, + 1.18, 3.21, 8.93, 6.07, 8.93, 6.49, 4.05, 0.77, 5.55, 1.90, 6.37, 6.64, 7.63, 4.08, 2.85, 8.78, 6.72, 7.18, 4.71, 5.57, + 1.04, 6.55, 2.04, 1.49, 1.80, 7.48, 6.69, 1.69, 6.35, 6.05, 7.07, 7.98, 8.67, 5.93, 2.65, 5.59, 1.30, 1.56, 7.17, 0.65, + 6.11, 0.72, 7.15, 6.17, 5.74, 8.72, 2.18, 8.09, 6.24, 3.36, 5.42, 6.50, 3.59, 4.98, 0.66, 1.58, 8.81, 2.93, 5.03, 1.67, + 4.56, 7.75, 5.87, 5.17, 2.89, 3.15, 3.61, 8.02, 7.61, 7.97, 8.41, 8.84, 4.04, 8.91, 0.46, 2.99, 8.11, 6.46, 6.74, 4.00, + 0.06, 3.55, 2.57, 6.34, 4.06, 5.88, 6.95, 4.37, 4.82, 5.04, 4.34, 4.57, 3.91, 3.10, 0.38, 7.07, 7.80, 3.80, 3.74, 7.85, + 4.86, 1.46, 0.95, 4.34, 5.36, 1.04, 3.15, 8.69, 2.59, 2.10, 1.39, 5.43, 4.86, 8.50, 7.86, 1.09, 5.88, 7.31, 6.74, 3.26, + 3.07, 8.20, 1.86, 5.16, 4.56, 8.77, 8.66, 3.20, 5.65, 7.66, 8.75, 8.21, 3.70, 6.94, 0.57, 7.88, 3.57, 4.35, 5.58, 5.82, + 5.02, 2.96, 0.61, 7.97, 4.62, 8.76, 0.06, 4.62, 7.95, 5.07, 6.89, 3.30, 4.56, 7.09, 7.49, 3.45, 5.75, 4.08, 0.66, 0.76, + 0.54, 8.40, 8.37, 8.33, 8.66, 0.62, 7.19, 8.88, 7.69, 7.97, 5.41, 3.51, 2.10, 7.15, 1.62, 6.97, 6.22, 6.99, 4.46, 1.26, + 2.11, 3.89, 7.03, 3.35, 0.20, 5.89, 6.68, 7.35, 3.86, 1.26, 5.44, 2.84, 3.11, 8.01, 2.86, 2.34, 7.76, 3.40, 4.61, 2.74, + 0.63, 0.32, 7.69, 5.20, 4.42, 2.94, 2.73, 3.88, 7.33, 6.39, 3.50, 8.67, 8.72, 3.99, 0.44, 7.49, 2.27, 2.90, 6.68, 1.62, + 1.59, 1.05, 4.72, 6.89, 8.58, 6.35, 4.79, 7.25, 0.21, 5.51, 7.63, 3.38, 7.70, 8.75, 0.22, 5.76, 2.87, 6.52, 5.97, 5.83, + 2.53, 1.43, 2.65, 7.98, 6.61, 7.81, 4.24, 2.67, 6.07, 4.26, 3.96, 0.05, 1.40, 4.57, 8.55, 5.41, 4.01, 2.00, 7.07, 3.15, + 8.50, 1.35, 3.30, 4.00, 5.45, 6.49, 3.07, 8.76, 8.21, 2.90, 3.92, 0.45, 0.71, 6.86, 8.56, 2.15, 0.24, 2.04, 1.81, 1.59, + 7.91, 4.06, 7.92, 0.90, 1.29, 0.29, 7.32, 6.95, 4.75, 4.40, 7.18, 1.75, 2.65, 8.71, 2.49, 3.11, 3.72, 1.78, 3.48, 1.05, + 2.91, 6.13, 4.85, 4.99, 8.65, 7.88, 0.44, 4.57, 8.09, 4.86, 4.46, 6.88, 7.25, 2.58, 3.89, 7.54, 1.73, 7.44, 7.01, 5.28, + 3.24, 3.18, 6.73, 0.10, 6.75, 0.05, 3.68, 5.80, 3.98, 3.32, 0.88, 1.53, 3.24, 4.75, 6.06, 0.63, 7.93, 2.69, 2.71, 2.95, + 8.32, 7.47, 7.36, 4.48, 2.20, 8.84, 8.26, 6.43, 5.89, 4.54, 3.66, 4.90, 0.98, 2.74, 4.18, 8.60, 0.78, 7.23, 4.02, 0.25, + 4.86, 5.90, 0.26, 4.24, 6.63, 8.48, 5.50, 4.07, 6.06, 2.14, 6.90, 6.43, 3.69, 7.83, 1.68, 4.29, 5.12, 0.40, 8.99, 1.26, + 4.11, 4.23, 5.10, 3.68, 6.81, 5.17, 7.91, 0.22, 4.56, 3.32, 3.59, 8.56, 0.99, 5.37, 7.72, 4.65, 4.26, 7.14, 6.63, 6.39, + 8.81, 4.78, 3.78, 4.94, 7.70, 1.66, 7.09, 2.06, 6.66, 2.39, 7.28, 4.42, 5.62, 4.36, 0.95, 4.91, 1.39, 4.26, 6.42, 6.02, + 2.12, 2.77, 3.02, 4.70, 2.03, 6.72, 1.30, 1.23, 4.92, 3.91, 7.54, 4.11, 3.91, 1.03, 8.75, 2.85, 6.01, 2.74, 7.33, 6.57, + 4.85, 6.81, 7.56, 3.65, 0.51, 4.25, 6.83, 4.45, 2.95, 8.94, 3.93, 5.87, 3.18, 1.79, 3.19, 5.84, 0.03, 7.59, 3.11, 8.22, + 7.04, 5.70, 1.28, 5.55, 0.86, 6.70, 8.50, 0.79, 1.10, 2.38, 5.23, 6.00, 0.62, 2.08, 0.65, 2.97, 4.94, 5.35, 2.89, 7.20, + 0.30, 5.82, 4.06, 1.45, 7.93, 1.99, 7.37, 3.84, 1.96, 1.85, 0.57, 7.74, 0.13, 6.90, 5.50, 3.38, 1.09, 8.68, 8.86, 6.80, + 5.15, 3.18, 7.80, 8.61, 4.44, 4.78, 3.25, 2.90, 0.63, 4.98, 0.50, 0.83, 5.07, 5.09, 4.90, 1.51, 1.11, 0.23, 7.47, 7.04, + 1.52, 3.58, 5.08, 3.03, 4.31, 2.32, 4.30, 3.51, 6.32, 2.96, 4.00, 4.70, 8.24, 1.06, 4.74, 4.58, 0.28, 3.75, 0.64, 0.83, + 2.56, 1.46, 3.26, 3.74, 7.24, 7.57, 5.29, 0.33, 2.22, 7.80, 8.59, 3.31, 7.24, 1.21, 4.77, 2.07, 4.17, 2.34, 0.34, 2.14, + 2.19, 7.81, 1.77, 5.69, 2.72, 5.53, 3.01, 2.23, 1.77, 5.35, 8.61, 2.76, 2.97, 1.39, 6.22, 7.26, 4.86, 1.11, 4.27, 3.50, + 1.13, 8.77, 1.83, 6.25, 0.74, 3.90, 0.64, 3.35, 1.86, 5.44, 6.19, 1.08, 7.17, 7.30, 6.38, 3.22, 0.89, 8.14, 0.84, 3.39, + 2.70, 0.01, 2.69, 1.18, 7.52, 2.25, 6.39, 1.11, 0.05, 4.17, 2.91, 1.88, 3.80, 1.65, 2.33, 4.81, 5.36, 0.28, 8.87, 1.93, + 0.45, 8.82, 1.96, 7.40, 6.61, 5.00, 3.26, 2.13, 0.89, 7.30, 8.87, 8.03, 1.63, 3.01, 2.58, 0.30, 1.82, 4.21, 6.46, 1.14, + 6.27, 3.68, 8.30, 1.87, 8.34, 7.25, 8.57, 4.98, 3.89, 0.30, 2.37, 6.74, 7.53, 3.36, 3.17, 8.20, 6.20, 7.96, 0.22, 5.00, + 8.88, 8.26, 1.56, 3.19, 1.88, 7.51, 5.88, 7.42, 1.14, 6.21, 2.77, 7.24, 3.81, 3.15, 3.83, 3.88, 1.30, 6.81, 8.93, 1.87, + 2.73, 7.44, 7.66, 6.16, 5.01, 6.87, 4.81, 1.75, 6.53, 3.97, 7.84, 0.78, 0.43, 7.38, 5.88, 8.11, 4.71, 2.89, 5.04, 8.68, + 3.33, 4.24, 2.56, 8.62, 5.56, 0.98, 2.67, 1.10, 1.18, 8.43, 8.44, 7.96, 8.11, 2.07, 5.90, 7.80, 2.27, 0.48, 8.74, 3.78, + 7.01, 3.99, 4.11, 0.62, 1.16, 5.62, 3.24, 4.65, 4.75, 4.23, 6.53, 0.94, 7.11, 0.99, 7.49, 0.21, 7.97, 7.12, 4.59, 7.46, + 5.23, 7.64, 3.92, 2.63, 4.72, 8.18, 7.26, 8.57, 1.48, 2.33, 8.31, 2.10, 2.96, 5.89, 0.32, 4.06, 7.70, 6.31, 4.64, 4.90, + 5.69, 3.12, 7.34, 7.98, 5.49, 8.58, 8.29, 1.39, 7.34, 7.89, 8.95, 6.91, 1.47, 4.33, 6.17, 0.94, 8.49, 0.26, 1.48, 2.98, + 1.16, 8.58, 2.18, 3.42, 3.03, 5.48, 1.19, 3.32, 0.79, 6.19, 2.10, 4.12, 2.23, 1.74, 0.66, 8.92, 8.52, 8.71, 8.83, 4.99, + 0.30, 5.09, 2.94, 3.88, 0.98, 3.87, 1.61, 7.64, 4.67, 1.45, 0.68, 2.68, 2.11, 8.54, 1.47, 1.47, 3.79, 0.64, 3.30, 7.98, + 5.73, 6.61, 3.36, 7.88, 0.24, 4.07, 1.84, 3.92, 5.23, 4.94, 7.33, 0.44, 4.58, 3.36, 6.15, 4.04, 0.42, 2.48, 6.00, 0.45, + 5.14, 3.99, 3.48, 4.31, 6.43, 2.15, 3.10, 1.28, 2.61, 6.89, 4.67, 8.81, 2.00, 0.06, 5.74, 7.45, 3.23, 0.50, 4.59, 1.09, + 8.87, 5.26, 6.80, 8.29, 0.99, 8.76, 0.31, 6.30, 0.85, 1.89, 3.55, 5.59, 8.96, 8.86, 6.30, 4.51, 0.88, 1.67, 1.40, 0.81, + 3.80, 3.06, 7.73, 6.90, 6.21, 3.98, 8.40, 2.45, 1.03, 8.61, 2.44, 5.68, 5.37, 6.93, 0.86, 8.86, 3.68, 2.64, 5.28, 6.03, + 1.70, 8.20, 5.19, 4.57, 1.20, 4.73, 7.95, 8.25, 5.50, 8.62, 1.97, 1.76, 8.97, 5.31, 6.38, 0.03, 4.22, 6.69, 8.68, 7.75, + 5.73, 8.16, 3.43, 2.52, 3.09, 1.54, 6.63, 8.27, 6.64, 7.74, 4.38, 0.57, 6.10, 6.04, 1.11, 5.16, 8.00, 3.07, 7.45, 3.38, + 7.43, 1.98, 1.81, 4.71, 0.69, 8.31, 2.44, 7.29, 2.57, 5.68, 0.83, 8.63, 8.83, 4.45, 2.08, 3.68, 3.74, 0.33, 1.05, 7.60, + 4.45, 3.56, 6.84, 5.98, 1.41, 6.91, 5.59, 6.73, 0.88, 3.60, 4.13, 0.43, 5.02, 0.65, 7.65, 6.36, 0.30, 0.75, 6.27, 5.96, + 1.11, 3.15, 3.90, 8.16, 3.75, 3.80, 7.60, 8.41, 2.62, 7.76, 3.31, 1.39, 6.29, 5.92, 4.61, 4.02, 4.99, 0.87, 5.01, 3.75, + 1.29, 6.95, 8.93, 2.66, 0.16, 2.13, 2.57, 8.23, 2.12, 1.07, 3.66, 5.58, 3.95, 3.73, 1.93, 4.87, 1.46, 0.38, 2.33, 1.33, + 0.13, 6.35, 6.61, 5.29, 7.17, 4.86, 3.36, 8.38, 4.20, 0.38, 7.16, 0.52, 7.46, 2.59, 3.99, 5.41, 1.89, 4.45, 4.89, 0.42, + 8.76, 5.41, 5.97, 7.37, 5.57, 5.49, 3.36, 8.64, 3.45, 1.23, 1.42, 6.86, 6.40, 6.72, 2.14, 5.12, 6.46, 3.68, 1.75, 7.21, + 6.77, 5.45, 2.80, 1.27, 4.44, 3.96, 3.51, 6.59, 5.23, 3.42, 3.23, 1.70, 5.76, 0.87, 3.55, 1.85, 6.27, 2.23, 3.73, 4.86, + 3.88, 8.56, 6.85, 1.87, 3.36, 0.96, 5.32, 6.97, 1.62, 6.39, 8.95, 6.83, 3.22, 7.02, 1.46, 2.39, 3.38, 4.91, 8.77, 1.53, + 8.29, 1.02, 1.92, 2.90, 1.49, 7.96, 2.33, 4.64, 2.80, 5.95, 4.55, 1.79, 3.08, 4.28, 8.58, 1.65, 7.90, 8.12, 3.27, 8.77, + 2.21, 7.21, 1.40, 5.74, 3.74, 1.60, 6.47, 4.96, 2.18, 1.37, 1.52, 7.02, 4.61, 7.11, 5.57, 2.43, 6.27, 8.35, 8.75, 4.68, + 8.28, 8.64, 7.53, 8.26, 5.18, 8.79, 6.00, 4.08, 2.34, 5.12, 3.56, 0.92, 1.12, 0.48, 7.82, 6.87, 5.18, 8.16, 1.26, 2.53, + 2.22, 6.24, 2.49, 6.63, 4.73, 7.42, 5.95, 8.19, 4.71, 0.84, 7.90, 4.51, 2.33, 0.26, 1.98, 4.54, 0.09, 7.06, 4.68, 8.04, + 2.18, 3.78, 4.20, 5.29, 2.11, 1.75, 7.51, 5.05, 5.31, 6.24, 0.91, 7.12, 0.46, 3.58, 6.31, 6.23, 6.09, 5.69, 7.11, 5.57, + 2.39, 5.56, 6.89, 8.92, 0.53, 7.04, 8.46, 5.51, 1.66, 2.84, 6.29, 7.11, 0.03, 4.11, 1.84, 8.41, 4.53, 8.15, 1.82, 3.76, + 1.39, 2.35, 6.98, 5.55, 1.75, 4.01, 8.50, 1.84, 1.06, 5.12, 7.69, 8.87, 2.68, 7.51, 8.51, 6.84, 0.02, 5.94, 7.76, 0.04, + 7.12, 3.27, 0.81, 3.51, 1.89, 3.97, 2.30, 4.96, 8.33, 5.94, 6.94, 7.13, 8.95, 8.61, 0.50, 7.91, 6.39, 3.38, 7.85, 3.67, + 5.33, 1.12, 3.62, 6.83, 3.92, 1.23, 5.13, 0.44, 8.46, 3.44, 6.99, 0.63, 3.80, 5.64, 5.98, 6.26, 2.54, 1.77, 6.31, 7.47, + 3.32, 7.44, 3.93, 5.21, 1.80, 5.62, 0.31, 8.35, 8.95, 6.68, 1.99, 8.40, 7.50, 3.21, 1.90, 0.49, 7.76, 1.78, 1.80, 0.47, + 3.13, 8.55, 0.10, 5.35, 5.03, 4.46, 1.02, 4.60, 8.33, 1.67, 6.42, 4.28, 5.65, 0.04, 7.97, 6.39, 7.31, 6.60, 6.58, 2.14, + 8.33, 0.22, 3.22, 0.78, 1.89, 5.20, 0.73, 7.29, 2.80, 4.03, 5.69, 5.93, 0.39, 8.05, 2.47, 6.95, 7.35, 0.68, 6.57, 6.73, + 8.11, 2.80, 4.33, 0.74, 6.57, 5.65, 4.87, 0.22, 5.99, 6.76, 0.65, 4.87, 2.07, 7.03, 2.56, 2.40, 5.68, 2.69, 7.91, 4.37, + 4.45, 7.04, 8.71, 3.91, 1.32, 7.01, 6.87, 4.28, 3.94, 4.31, 4.90, 8.65, 0.47, 8.88, 3.32, 8.68, 4.46, 7.23, 6.84, 3.35, + 4.20, 6.98, 1.04, 2.04, 0.92, 0.53, 8.13, 5.76, 6.24, 3.75, 7.38, 0.19, 7.08, 4.89, 8.39, 7.71, 2.60, 8.54, 4.64, 6.93, + 0.32, 3.17, 6.35, 1.42, 5.18, 4.04, 2.99, 2.15, 3.02, 3.67, 2.54, 8.83, 1.24, 3.63, 4.74, 8.82, 0.65, 0.44, 4.70, 0.57, + 0.69, 5.82, 0.15, 0.35, 1.40, 6.57, 4.06, 7.20, 0.70, 4.83, 0.09, 6.14, 5.26, 5.93, 1.06, 7.57, 4.96, 2.86, 5.27, 1.34, + 2.84, 3.89, 8.29, 0.52, 3.61, 7.73, 2.81, 6.06, 1.09, 8.96, 5.51, 2.32, 1.81, 1.97, 2.37, 2.69, 3.04, 4.26, 4.17, 2.45, + 7.29, 6.36, 0.20, 1.94, 6.02, 6.41, 2.91, 2.74, 6.39, 3.74, 4.63, 5.80, 4.10, 5.21, 4.63, 5.92, 5.54, 3.38, 7.11, 4.56, + 0.50, 3.17, 7.36, 2.07, 1.08, 7.30, 0.71, 3.61, 2.46, 6.80, 0.04, 3.61, 3.87, 1.45, 6.50, 5.55, 8.74, 4.11, 5.72, 1.66, + 4.20, 7.43, 7.56, 1.93, 2.58, 0.90, 1.07, 7.09, 7.79, 7.31, 7.42, 3.63, 1.09, 1.70, 1.97, 8.52, 6.04, 6.67, 8.94, 6.67, + 7.11, 3.40, 4.63, 6.00, 6.69, 7.99, 0.29, 8.03, 0.13, 0.03, 4.71, 2.32, 1.65, 1.87, 0.35, 8.66, 5.94, 8.11, 4.11, 6.96, + 2.65, 4.82, 2.65, 5.80, 7.83, 7.64, 7.48, 2.28, 7.89, 3.63, 0.83, 6.41, 4.72, 1.64, 3.77, 3.51, 7.91, 1.48, 2.05, 5.19, + 1.45, 3.65, 2.20, 4.38, 6.33, 3.25, 0.03, 8.43, 7.18, 7.90, 5.49, 7.77, 6.25, 4.90, 7.50, 6.93, 2.55, 7.72, 3.38, 0.49, + 5.35, 8.60, 7.23, 1.47, 1.00, 4.65, 8.53, 4.17, 0.02, 7.24, 7.08, 6.71, 7.67, 6.29, 6.57, 2.87, 1.11, 0.37, 8.61, 6.40, + 5.43, 4.63, 8.75, 0.83, 3.09, 7.61, 7.14, 6.41, 1.20, 0.71, 2.50, 6.56, 3.72, 2.35, 8.45, 0.91, 5.49, 8.68, 1.84, 3.08, + 2.46, 5.97, 4.48, 2.58, 0.88, 1.59, 6.45, 2.12, 7.31, 0.13, 5.60, 1.90, 1.92, 6.56, 3.95, 3.54, 0.80, 0.73, 4.34, 1.72, + 5.47, 1.08, 8.39, 7.27, 7.25, 0.68, 8.86, 5.75, 1.68, 2.72, 4.38, 2.47, 0.58, 3.50, 7.27, 3.72, 2.05, 8.35, 1.21, 4.91, + 6.25, 3.44, 5.69, 7.16, 7.24, 8.70, 7.70, 8.59, 6.20, 3.62, 5.75, 3.20, 1.56, 8.95, 1.88, 8.04, 4.72, 4.35, 5.75, 1.91, + 0.39, 6.55, 7.78, 7.12, 3.73, 3.76, 3.83, 3.90, 7.91, 5.52, 6.62, 3.97, 6.91, 1.24, 1.80, 5.25, 5.86, 4.90, 6.44, 7.46, + 3.57, 5.36, 1.42, 6.07, 6.29, 0.21, 1.94, 7.53, 2.31, 5.30, 5.44, 0.19, 5.42, 2.95, 8.93, 3.94, 6.74, 2.08, 1.60, 6.86, + 2.15, 4.54, 8.83, 2.57, 7.90, 8.84, 0.25, 0.33, 3.85, 2.22, 0.96, 7.22, 7.16, 4.14, 0.62, 0.70, 7.34, 8.96, 2.70, 1.40, + 4.64, 4.11, 5.66, 6.68, 8.36, 7.17, 1.68, 6.85, 7.51, 7.68, 0.95, 1.74, 4.87, 6.84, 1.55, 1.53, 6.74, 3.48, 4.31, 7.05, + 6.90, 1.54, 8.13, 4.43, 8.04, 3.92, 6.91, 3.17, 4.89, 5.17, 2.83, 6.40, 7.20, 2.64, 7.13, 4.31, 3.82, 3.65, 6.70, 4.90, + 8.99, 5.44, 7.42, 3.72, 7.28, 8.67, 7.55, 6.36, 2.24, 8.15, 8.87, 6.32, 0.56, 7.36, 1.97, 6.46, 4.04, 4.24, 4.37, 6.97, + 1.40, 8.61, 1.11, 5.65, 8.87, 8.03, 0.42, 8.71, 6.69, 2.02, 4.64, 2.64, 5.25, 0.88, 1.07, 6.89, 7.59, 8.08, 3.32, 0.69, + 8.31, 6.68, 6.49, 2.25, 4.78, 3.99, 0.86, 0.96, 5.10, 1.43, 0.23, 0.11, 2.67, 6.97, 3.22, 4.23, 8.78, 2.87, 0.11, 0.26, + 8.85, 5.30, 6.52, 8.74, 5.97, 4.47, 7.20, 2.46, 4.25, 5.29, 8.03, 2.97, 6.87, 5.05, 4.57, 0.37, 4.59, 5.81, 4.10, 8.57, + 4.78, 0.96, 6.62, 2.32, 3.14, 2.33, 3.89, 5.94, 5.43, 7.67, 0.09, 2.47, 1.02, 7.42, 0.36, 8.85, 0.05, 0.10, 7.28, 8.11, + 0.37, 5.14, 3.77, 8.37, 2.07, 4.95, 8.90, 6.06, 0.15, 1.93, 2.66, 2.98, 8.05, 5.07, 6.60, 5.64, 0.50, 5.79, 7.17, 1.38, + 7.03, 1.52, 3.19, 0.56, 5.88, 1.90, 8.08, 3.72, 2.51, 5.83, 5.08, 0.65, 1.41, 3.97, 1.95, 5.02, 4.80, 6.62, 0.35, 7.29, + 5.00, 2.05, 1.19, 4.11, 7.30, 2.66, 3.51, 7.14, 3.45, 7.41, 4.02, 3.28, 8.06, 7.07, 8.07, 6.27, 5.45, 1.85, 0.64, 4.57, + 4.70, 1.93, 5.13, 3.92, 6.10, 5.60, 4.06, 1.37, 1.38, 4.90, 3.85, 4.61, 1.56, 3.51, 6.31, 2.62, 5.65, 6.45, 0.49, 7.97, + 5.82, 2.34, 6.16, 2.99, 4.17, 6.70, 7.28, 7.95, 5.71, 8.20, 4.43, 3.71, 7.63, 5.14, 2.37, 7.97, 8.65, 3.62, 0.56, 1.90, + 5.52, 5.59, 6.68, 7.29, 6.85, 5.69, 8.10, 3.69, 6.46, 2.30, 0.29, 5.66, 7.83, 1.27, 1.14, 1.37, 0.22, 4.99, 5.66, 3.93, + 4.48, 7.18, 2.91, 1.41, 3.71, 1.14, 1.10, 7.41, 3.19, 1.97, 8.15, 3.07, 4.59, 7.97, 4.91, 4.85, 5.53, 8.60, 8.89, 0.95, + 5.13, 8.91, 7.27, 6.57, 3.67, 7.07, 8.66, 5.77, 2.65, 3.40, 4.94, 2.09, 6.57, 6.03, 2.52, 8.00, 5.60, 5.35, 0.12, 6.07, + 8.45, 1.70, 1.19, 0.47, 7.02, 7.67, 7.12, 3.71, 2.12, 4.70, 0.23, 6.80, 1.13, 4.67, 4.77, 4.75, 7.33, 2.72, 4.15, 2.38, + 5.10, 4.23, 8.58, 3.67, 5.12, 7.99, 1.79, 3.29, 5.38, 8.91, 7.17, 5.95, 4.69, 8.01, 7.40, 7.28, 2.08, 1.69, 4.45, 3.23, + 3.53, 0.07, 5.23, 3.83, 3.26, 0.80, 6.63, 7.90, 8.66, 4.49, 6.61, 2.77, 3.20, 7.78, 1.93, 7.40, 1.23, 7.54, 7.75, 6.10, + 7.97, 7.96, 1.60, 7.29, 7.91, 3.56, 7.82, 2.91, 2.81, 4.78, 5.76, 0.85, 3.80, 1.70, 6.03, 6.59, 1.21, 8.72, 2.94, 2.68, + 3.66, 0.30, 6.69, 2.71, 2.71, 2.86, 6.51, 6.81, 7.85, 5.84, 0.58, 2.22, 3.77, 8.14, 7.31, 2.05, 2.28, 4.98, 1.03, 0.99, + 1.26, 4.95, 3.18, 8.57, 7.09, 7.12, 8.55, 8.61, 2.32, 0.72, 7.17, 3.22, 0.08, 7.44, 5.00, 6.19, 2.83, 4.43, 1.70, 7.83, + 1.92, 1.50, 8.48, 0.47, 6.59, 4.34, 5.89, 5.48, 0.80, 4.70, 6.58, 2.48, 6.96, 2.36, 2.79, 8.70, 7.93, 5.25, 1.56, 3.61, + 7.65, 7.82, 6.41, 2.91, 7.18, 6.47, 7.70, 6.77, 8.84, 3.58, 1.58, 3.61, 4.72, 1.53, 4.83, 1.09, 3.77, 7.73, 5.07, 0.08, + 0.28, 4.94, 7.70, 5.15, 6.61, 5.32, 3.66, 1.77, 0.74, 6.51, 7.90, 8.99, 8.21, 3.88, 3.94, 0.40, 0.86, 3.38, 6.35, 7.12, + 1.89, 0.69, 7.99, 5.62, 2.48, 7.58, 5.57, 2.34, 7.63, 2.98, 1.37, 7.74, 1.52, 0.06, 4.27, 6.26, 7.11, 1.65, 6.04, 2.77, + 0.58, 3.14, 3.02, 1.61, 1.52, 8.03, 1.02, 0.88, 7.93, 4.00, 4.95, 4.80, 1.15, 4.91, 1.95, 4.99, 4.32, 4.41, 6.85, 0.41, + 1.11, 6.84, 8.05, 2.11, 4.74, 6.03, 5.02, 7.47, 8.73, 4.27, 3.87, 3.62, 3.11, 3.85, 6.73, 8.75, 1.40, 0.29, 7.93, 1.64, + 3.67, 8.66, 4.29, 7.35, 2.10, 8.87, 0.27, 8.09, 3.30, 4.63, 5.91, 0.48, 2.66, 2.80, 4.27, 3.26, 7.25, 2.28, 3.95, 4.02, + 7.57, 8.97, 6.51, 0.85, 0.92, 7.64, 6.25, 3.34, 4.99, 1.43, 3.31, 6.78, 0.68, 0.15, 6.54, 4.59, 7.18, 1.56, 6.34, 2.37, + 2.86, 5.65, 6.24, 3.14, 7.42, 4.20, 3.49, 3.62, 3.42, 1.72, 4.09, 3.17, 0.33, 8.51, 8.70, 7.60, 1.94, 6.92, 7.44, 8.53, + 7.03, 2.13, 3.64, 8.30, 4.89, 5.81, 4.06, 6.16, 4.57, 1.60, 8.34, 5.44, 0.39, 2.95, 6.95, 1.97, 2.62, 2.41, 7.19, 4.06, + 4.85, 6.02, 7.41, 8.90, 0.24, 8.97, 7.86, 4.79, 5.25, 1.83, 7.32, 6.32, 7.40, 2.34, 0.10, 5.32, 0.94, 0.02, 6.48, 0.32, + 3.35, 2.63, 6.52, 8.43, 0.16, 5.53, 3.43, 1.45, 3.23, 7.38, 5.75, 7.34, 8.84, 8.15, 7.04, 8.80, 1.30, 3.26, 5.50, 2.62, + 6.08, 7.89, 4.86, 1.65, 2.89, 7.95, 5.57, 7.66, 2.67, 6.81, 7.05, 5.05, 7.82, 2.06, 6.86, 2.53, 1.41, 8.61, 8.23, 1.02, + 8.88, 0.39, 8.64, 4.76, 5.01, 6.19, 8.72, 8.28, 7.75, 0.98, 2.00, 5.26, 3.03, 2.82, 4.99, 7.59, 8.26, 2.64, 4.98, 5.55, + 7.01, 6.81, 5.19, 4.30, 3.07, 4.95, 7.88, 7.87, 6.73, 4.69, 2.21, 8.50, 8.02, 6.06, 4.86, 1.02, 2.31, 1.35, 0.52, 3.98, + 2.76, 6.49, 2.59, 4.84, 7.59, 1.65, 6.84, 5.86, 7.49, 3.02, 6.80, 4.71, 3.97, 8.38, 4.34, 3.58, 5.86, 3.29, 7.82, 5.61, + 5.70, 5.68, 4.92, 1.70, 2.30, 4.60, 6.57, 5.41, 4.18, 7.28, 5.77, 4.48, 0.43, 8.22, 7.59, 4.60, 1.89, 8.09, 3.29, 8.55, + 6.32, 8.03, 6.88, 0.60, 7.01, 4.08, 3.03, 6.77, 0.68, 2.34, 4.93, 7.23, 5.75, 4.46, 3.25, 0.24, 6.24, 8.32, 5.07, 7.18, + 3.97, 7.57, 3.29, 8.22, 1.00, 6.25, 4.85, 8.42, 6.70, 4.08, 0.72, 5.14, 6.06, 4.56, 8.48, 8.93, 4.57, 1.26, 6.22, 4.14, + 4.15, 4.45, 0.14, 0.16, 2.30, 1.54, 8.33, 4.74, 4.18, 5.41, 0.90, 7.22, 0.67, 5.60, 2.81, 1.63, 2.34, 6.12, 0.57, 3.51, + 7.67, 4.73, 5.04, 1.71, 6.57, 2.33, 8.57, 8.47, 3.90, 1.06, 2.85, 7.69, 5.55, 3.88, 1.88, 3.63, 5.13, 7.09, 6.66, 1.14, + 8.37, 4.93, 0.34, 6.92, 7.81, 4.53, 5.70, 4.66, 4.63, 5.92, 7.19, 8.34, 0.87, 7.32, 0.93, 8.45, 2.60, 8.05, 4.39, 3.06, + 5.11, 6.50, 8.71, 7.69, 8.70, 2.12, 6.18, 0.68, 4.00, 0.15, 3.49, 3.34, 2.40, 3.05, 5.04, 8.37, 1.66, 7.61, 3.93, 1.37, + 8.34, 3.59, 6.69, 5.90, 4.49, 5.74, 5.38, 2.43, 0.28, 1.76, 2.21, 4.85, 4.51, 5.94, 3.50, 3.49, 4.06, 7.22, 6.10, 7.58, + 8.54, 7.08, 5.48, 8.05, 3.90, 5.62, 3.93, 7.71, 6.69, 2.71, 8.26, 7.91, 5.50, 6.52, 6.08, 5.13, 0.86, 7.04, 6.45, 0.55, + 8.91, 5.51, 1.44, 1.89, 0.13, 3.72, 5.13, 0.58, 6.05, 8.57, 3.25, 1.39, 0.35, 2.35, 5.60, 5.91, 3.36, 7.84, 3.44, 8.80, + 3.23, 3.13, 6.68, 7.68, 0.10, 7.32, 5.08, 5.65, 6.71, 5.30, 3.29, 8.81, 8.03, 1.20, 7.87, 8.84, 8.59, 8.10, 2.37, 0.88, + 2.67, 7.82, 3.72, 2.77, 4.43, 0.43, 6.25, 3.90, 4.39, 3.35, 5.87, 3.14, 8.42, 0.64, 6.14, 5.77, 3.83, 6.95, 2.15, 0.70, + 1.68, 2.76, 3.40, 0.76, 6.62, 3.76, 4.25, 3.05, 3.09, 3.40, 6.60, 4.32, 6.33, 7.05, 7.16, 8.10, 0.72, 6.12, 8.65, 4.89, + 3.05, 4.46, 8.11, 5.97, 6.38, 1.72, 4.51, 4.64, 7.10, 4.01, 2.71, 0.38, 3.04, 6.09, 4.15, 6.33, 5.74, 1.49, 4.07, 6.79, + 6.81, 5.44, 6.94, 3.63, 7.95, 8.27, 7.13, 4.80, 0.06, 2.93, 4.51, 7.55, 5.54, 1.64, 2.53, 4.71, 6.71, 3.16, 0.73, 0.04, + 6.17, 4.31, 2.64, 3.08, 7.70, 7.10, 3.54, 4.74, 8.21, 6.73, 8.62, 0.78, 8.41, 2.18, 8.57, 8.38, 5.29, 6.06, 2.74, 6.94, + 5.28, 6.87, 5.89, 8.47, 3.08, 6.29, 7.17, 8.62, 6.09, 5.84, 7.35, 6.21, 5.71, 5.72, 0.98, 5.23, 8.48, 1.50, 4.23, 8.78, + 3.72, 0.71, 2.30, 2.01, 5.84, 4.66, 1.28, 8.33, 6.58, 0.56, 3.50, 3.03, 1.57, 5.42, 5.36, 6.52, 3.13, 5.77, 8.14, 1.65, + 6.29, 3.74, 2.15, 2.30, 5.46, 3.18, 5.97, 4.24, 3.61, 1.07, 1.80, 7.28, 1.05, 6.72, 4.12, 8.71, 7.47, 1.12, 2.36, 1.93, + 0.31, 3.65, 0.41, 5.17, 3.11, 6.74, 1.38, 0.45, 8.72, 1.64, 3.33, 5.62, 7.32, 2.26, 8.15, 7.04, 7.21, 5.10, 7.24, 3.69, + 8.46, 2.98, 2.26, 8.90, 8.67, 3.46, 4.56, 1.64, 8.33, 3.49, 2.60, 0.19, 8.39, 2.36, 2.33, 1.31, 2.95, 1.13, 7.96, 6.80, + 0.14, 5.15, 3.31, 1.63, 2.87, 2.73, 4.78, 2.70, 6.05, 6.87, 4.29, 2.83, 6.54, 6.37, 5.83, 7.07, 8.44, 2.68, 3.57, 1.64, + 4.70, 5.98, 4.69, 5.66, 6.45, 5.65, 2.63, 8.92, 6.14, 5.82, 3.53, 7.97, 8.88, 8.05, 7.50, 6.69, 5.05, 7.23, 3.37, 5.22, + 1.81, 2.70, 1.29, 6.29, 1.77, 4.26, 1.94, 1.27, 3.73, 3.11, 5.90, 3.36, 1.95, 0.04, 0.77, 2.81, 8.44, 3.29, 1.99, 4.78, + 2.11, 3.89, 8.09, 1.62, 4.74, 0.54, 0.60, 8.61, 8.23, 7.62, 7.82, 1.71, 3.76, 8.72, 3.97, 0.01, 0.99, 4.62, 2.51, 2.50, + 6.63, 0.52, 0.61, 1.33, 6.57, 0.52, 6.24, 4.54, 0.48, 8.05, 6.54, 1.04, 2.27, 2.51, 0.61, 7.30, 1.24, 0.58, 5.25, 2.19, + 0.33, 3.82, 4.56, 7.07, 1.66, 7.24, 0.95, 1.48, 7.66, 8.71, 5.47, 5.04, 0.53, 0.16, 5.92, 0.20, 2.48, 2.05, 5.87, 1.98, + 2.97, 1.20, 1.21, 6.64, 7.91, 3.46, 0.67, 3.25, 1.30, 4.35, 1.99, 0.58, 3.19, 6.38, 8.77, 5.95, 1.87, 1.38, 1.15, 4.18, + 8.93, 0.70, 5.51, 5.43, 3.85, 4.35, 8.22, 0.29, 1.61, 0.75, 1.11, 6.60, 8.91, 6.17, 6.38, 8.80, 7.33, 2.77, 8.32, 0.62, + 8.16, 2.07, 4.37, 3.94, 7.29, 5.22, 4.84, 4.92, 2.93, 8.86, 1.58, 5.34, 0.84, 2.54, 7.11, 5.71, 1.16, 2.43, 2.36, 3.33, + 6.74, 0.14, 5.69, 4.44, 5.51, 2.49, 1.67, 1.95, 2.18, 1.78, 0.28, 2.75, 2.49, 4.93, 1.46, 6.35, 7.69, 3.70, 6.03, 5.91, + 0.19, 4.10, 2.28, 8.81, 6.82, 5.00, 3.79, 0.95, 2.35, 7.80, 7.23, 2.53, 3.49, 1.26, 7.42, 2.73, 7.01, 4.01, 5.11, 0.74, + 0.14, 2.35, 0.27, 2.82, 2.83, 2.43, 1.42, 4.95, 6.19, 0.94, 8.47, 8.89, 1.82, 6.48, 5.60, 3.39, 8.50, 0.12, 4.66, 4.93, + 5.27, 7.40, 2.54, 1.82, 8.72, 4.14, 4.30, 6.67, 8.83, 4.33, 1.47, 1.42, 0.75, 4.30, 7.71, 1.75, 2.23, 2.82, 5.51, 2.35, + 6.80, 3.29, 1.35, 7.79, 2.04, 9.00, 8.63, 6.18, 4.63, 6.71, 0.14, 6.20, 5.42, 3.27, 2.88, 1.37, 4.01, 2.44, 6.82, 7.46, + 6.86, 5.52, 7.89, 8.40, 1.56, 5.17, 0.56, 1.27, 6.19, 3.93, 2.21, 2.24, 4.42, 2.18, 6.37, 6.69, 1.57, 8.01, 7.02, 0.37, + 0.39, 8.27, 2.03, 7.28, 8.06, 2.47, 7.99, 3.42, 6.54, 7.36, 6.56, 8.66, 1.07, 4.01, 6.71, 0.13, 6.50, 2.19, 3.49, 8.30, + 0.78, 2.09, 8.68, 7.37, 2.77, 8.14, 2.45, 2.26, 3.35, 8.35, 0.85, 1.18, 7.86, 1.08, 4.73, 3.15, 6.44, 0.22, 0.35, 2.22, + 7.12, 1.82, 1.00, 0.70, 1.36, 5.86, 6.62, 5.14, 0.49, 5.51, 5.27, 5.58, 4.07, 3.48, 6.40, 1.61, 7.57, 6.07, 5.66, 4.39, + 1.53, 3.64, 2.99, 7.03, 3.80, 8.52, 2.77, 7.02, 7.34, 1.26, 7.92, 3.37, 0.53, 4.86, 2.63, 0.71, 8.67, 8.16, 7.00, 0.40, + 7.36, 8.68, 4.40, 5.54, 2.76, 1.56, 5.10, 6.40, 4.02, 2.82, 7.46, 5.20, 8.64, 3.86, 4.48, 7.09, 6.60, 7.73, 1.61, 6.32, + 4.88, 7.48, 7.26, 0.32, 0.02, 3.32, 5.25, 4.58, 7.29, 0.72, 0.51, 0.90, 5.91, 6.36, 3.01, 7.41, 8.12, 1.89, 0.97, 4.39, + 8.43, 4.94, 5.15, 4.17, 4.14, 2.17, 5.32, 8.89, 2.61, 2.41, 3.60, 1.93, 1.52, 7.84, 8.76, 7.15, 0.22, 2.73, 6.56, 4.22, + 4.47, 6.05, 4.98, 7.50, 1.37, 5.31, 3.01, 1.58, 6.13, 4.11, 0.00, 0.35, 5.22, 7.75, 7.54, 8.57, 2.07, 6.96, 2.46, 5.36, + 0.55, 7.94, 5.28, 4.65, 4.36, 6.48, 0.24, 3.59, 5.11, 8.51, 5.98, 7.19, 0.30, 4.54, 7.53, 1.99, 8.93, 1.64, 4.47, 3.24, + 8.91, 4.19, 7.77, 3.28, 3.05, 4.63, 6.94, 0.15, 4.03, 4.23, 7.02, 7.02, 7.34, 2.75, 5.90, 7.02, 5.68, 8.09, 0.71, 8.29, + 4.41, 0.37, 4.75, 4.43, 4.73, 5.91, 0.89, 7.46, 3.70, 5.24, 6.25, 7.23, 0.32, 7.96, 3.26, 1.87, 3.29, 7.51, 7.34, 3.10, + 8.45, 3.08, 0.74, 4.41, 6.03, 7.89, 0.17, 2.22, 1.69, 5.57, 8.44, 1.35, 6.07, 7.95, 8.24, 3.38, 2.99, 5.87, 4.04, 6.86, + 7.79, 3.54, 8.91, 8.16, 0.93, 1.87, 5.08, 5.09, 6.72, 6.74, 0.88, 1.16, 3.99, 2.60, 2.80, 4.86 +}; + +float verify_data[ARRAY_SIZE] = +{ + 1354.01, 1395.87, 1543.01, 1599.53, 1344.29, 1352.43, 1217.77, 1342.96, 1258.09, 1233.96, 1257.44, 1240.52, 1417.05, 1133.66, 1303.01, 1394.43, 1397.95, 1498.21, 1297.75, 1314.17, + 1267.56, 1570.65, 1350.75, 1214.41, 1293.15, 1281.52, 1383.14, 1328.95, 1376.30, 1474.75, 1233.98, 1467.32, 1385.80, 1516.00, 1383.32, 1498.40, 1349.81, 1387.99, 1407.33, 1276.53, + 1346.93, 1398.80, 1512.83, 1286.52, 1361.78, 1434.00, 1346.92, 1349.11, 1168.83, 1159.40, 1665.83, 1344.38, 1467.49, 1415.67, 1419.02, 1570.37, 1301.99, 1414.36, 1520.39, 1306.54, + 1094.96, 1373.59, 1448.26, 1375.64, 1258.80, 1185.72, 1350.71, 1563.55, 1316.17, 1301.19, 1161.06, 1230.95, 1212.56, 1154.43, 1151.65, 1135.04, 1347.27, 1181.36, 1228.32, 1167.81, + 1156.78, 1400.19, 1281.56, 1208.90, 1142.65, 1360.37, 1253.98, 1222.83, 1280.18, 1338.35, 1283.13, 1329.33, 1251.23, 1359.60, 1233.32, 1306.39, 1272.46, 1390.59, 1328.05, 1409.97, + 1267.51, 1339.74, 1282.41, 1220.99, 1298.74, 1220.26, 1411.56, 1343.96, 1225.86, 1372.56, 1276.61, 1267.04, 1131.05, 1256.09, 1469.12, 1268.12, 1476.59, 1405.91, 1301.43, 1389.66, + 1273.65, 1288.05, 1571.70, 1269.64, 1112.05, 1363.37, 1378.76, 1304.14, 1396.36, 1336.56, 1370.00, 1644.75, 1315.29, 1396.68, 1281.25, 1262.70, 1299.40, 1249.69, 1175.23, 1181.40, + 1454.54, 1216.33, 1207.56, 1376.62, 1143.42, 1534.02, 1401.90, 1323.66, 1178.84, 1410.94, 1260.04, 1289.08, 1394.97, 1377.33, 1317.83, 1439.55, 1349.56, 1435.91, 1333.42, 1428.67, + 1296.20, 1504.97, 1349.81, 1435.84, 1453.81, 1455.28, 1336.01, 1281.53, 1344.39, 1378.58, 1520.28, 1362.65, 1349.20, 1461.86, 1258.32, 1233.64, 1244.44, 1205.92, 1618.34, 1355.04, + 1562.53, 1473.65, 1461.36, 1521.75, 1228.12, 1506.90, 1493.48, 1374.98, 1185.69, 1493.79, 1345.46, 1369.70, 1161.75, 1116.09, 1290.69, 1477.64, 1140.02, 1264.17, 1074.87, 1269.37, + 1056.11, 1127.10, 1090.32, 1055.62, 1302.05, 1118.96, 1092.37, 1273.94, 1075.51, 1266.97, 1125.54, 1136.88, 1098.92, 1359.13, 1142.29, 1101.04, 1308.78, 1291.21, 1182.88, 1179.02, + 1114.94, 1287.37, 1059.56, 1279.27, 1250.69, 1275.44, 1288.61, 1145.96, 1235.53, 1291.31, 1188.66, 1052.27, 1174.23, 1190.70, 1397.36, 1275.87, 1317.88, 1243.39, 1131.48, 1260.10, + 1192.54, 1178.11, 1432.50, 1106.75, 1343.19, 1255.30, 1263.46, 1388.74, 1137.68, 1257.01, 1350.52, 1180.76, 1066.27, 1314.34, 1193.60, 1265.57, 1210.52, 1183.99, 1230.33, 1387.46, + 1151.10, 1077.39, 1149.84, 1215.06, 1119.25, 1199.23, 977.74, 1111.13, 1335.71, 1168.84, 1036.50, 1005.27, 1178.64, 1275.66, 1208.78, 1075.36, 1100.36, 1163.28, 1075.87, 1190.77, + 1176.13, 1074.33, 1152.84, 1062.11, 1314.44, 1298.88, 1192.93, 1199.16, 1043.27, 1263.14, 1123.87, 1159.83, 1233.00, 1222.81, 1054.01, 1078.97, 1233.10, 1122.61, 1260.10, 1132.02, + 1169.08, 1203.75, 1166.90, 1081.17, 1092.89, 1127.70, 1311.74, 1267.25, 1353.53, 1251.22, 1208.01, 1377.83, 1170.55, 1183.10, 1210.08, 1079.78, 1022.47, 1267.79, 1280.86, 1107.99, + 1220.63, 1231.38, 1297.16, 1349.99, 1132.89, 1057.39, 1167.18, 1238.74, 1058.25, 1242.15, 966.69, 1056.35, 1312.60, 1080.69, 1157.51, 1057.53, 1096.31, 1256.06, 1222.67, 1225.06, + 1084.64, 1147.07, 1166.91, 1215.04, 1214.49, 1119.43, 1151.76, 1214.63, 1167.99, 1353.90, 1138.60, 1258.90, 1082.25, 1209.09, 1209.70, 1129.26, 1276.81, 1264.27, 1085.23, 927.81, + 1128.21, 1080.52, 1231.94, 1182.54, 1235.60, 1292.99, 1235.59, 1127.82, 1124.34, 1079.43, 1432.82, 1249.15, 1327.01, 1301.50, 1246.96, 1376.32, 1061.28, 1204.55, 1329.92, 1103.78, + 931.53, 1368.76, 1190.03, 1163.34, 1396.89, 1433.26, 1527.05, 1598.78, 1278.53, 1415.12, 1430.83, 1481.94, 1199.17, 1329.99, 1335.39, 1231.51, 1470.62, 1375.58, 1375.26, 1395.02, + 1399.26, 1608.00, 1308.94, 1431.51, 1243.43, 1463.41, 1403.81, 1364.34, 1434.32, 1417.88, 1495.77, 1363.22, 1464.28, 1487.78, 1364.68, 1381.91, 1349.18, 1528.36, 1396.53, 1392.29, + 1414.73, 1422.36, 1300.79, 1310.37, 1443.54, 1385.04, 1608.70, 1404.34, 1432.32, 1504.10, 1442.82, 1397.85, 1334.88, 1305.33, 1663.19, 1432.12, 1613.45, 1523.58, 1466.45, 1595.38, + 1366.08, 1411.41, 1496.29, 1258.22, 1156.74, 1532.48, 1488.98, 1406.65, 1397.03, 1292.21, 1440.31, 1634.74, 1358.90, 1495.89, 1347.00, 1449.85, 1225.68, 1390.38, 1157.20, 1369.11, + 1596.16, 1259.06, 1245.06, 1294.82, 1291.60, 1576.38, 1369.14, 1234.77, 1202.91, 1557.84, 1329.85, 1203.48, 1415.17, 1392.83, 1405.60, 1427.19, 1375.85, 1442.91, 1349.33, 1454.88, + 1281.60, 1469.46, 1358.83, 1380.14, 1363.64, 1431.13, 1262.43, 1334.68, 1399.66, 1290.28, 1658.62, 1332.18, 1351.59, 1357.42, 1313.97, 1315.74, 1291.34, 1297.74, 1686.54, 1265.94, + 1589.24, 1458.80, 1414.98, 1572.02, 1366.07, 1427.09, 1438.33, 1344.23, 1277.32, 1518.03, 1472.18, 1351.37, 1392.20, 1374.39, 1377.64, 1568.39, 1282.97, 1253.27, 1246.33, 1311.90, + 1251.72, 1266.76, 1139.97, 1291.31, 1397.95, 1124.47, 1260.95, 1227.31, 1269.12, 1472.09, 1282.62, 1179.06, 1169.98, 1488.49, 1313.12, 1263.70, 1286.53, 1276.45, 1351.07, 1313.12, + 1345.65, 1366.31, 1250.39, 1330.61, 1358.94, 1406.88, 1390.62, 1382.66, 1355.59, 1434.79, 1347.25, 1215.57, 1313.64, 1212.06, 1420.40, 1374.99, 1314.28, 1419.94, 1318.03, 1268.17, + 1195.18, 1278.23, 1604.11, 1276.18, 1558.91, 1450.96, 1279.83, 1608.46, 1258.74, 1380.00, 1459.37, 1229.32, 1127.80, 1465.53, 1372.71, 1288.84, 1245.17, 1363.43, 1340.75, 1485.38, + 1282.79, 1323.81, 1342.04, 1389.78, 1172.57, 1267.06, 1203.23, 1199.95, 1461.08, 1151.50, 1148.56, 1246.64, 1194.17, 1419.16, 1151.19, 1225.54, 1172.39, 1268.26, 1279.08, 1214.26, + 1226.21, 1323.91, 1293.96, 1211.01, 1359.67, 1416.99, 1218.85, 1342.10, 1183.49, 1412.17, 1238.21, 1387.83, 1378.53, 1284.84, 1299.25, 1096.53, 1269.18, 1288.36, 1405.23, 1299.46, + 1245.22, 1327.05, 1261.93, 1215.82, 1264.44, 1239.77, 1552.56, 1296.11, 1442.32, 1384.22, 1359.94, 1383.29, 1203.91, 1374.08, 1441.88, 1189.57, 1146.06, 1315.69, 1348.47, 1322.45, + 1128.66, 1214.98, 1316.18, 1357.55, 1261.46, 1285.64, 1171.37, 1352.30, 1057.03, 1180.40, 1092.10, 1083.04, 1337.04, 1212.64, 1229.50, 1245.28, 1176.11, 1333.82, 1325.87, 1200.51, + 1102.30, 1266.74, 1114.25, 1287.98, 1317.99, 1273.57, 1255.38, 1221.25, 1239.90, 1380.25, 1289.36, 1247.62, 1260.22, 1373.04, 1228.45, 1228.69, 1353.32, 1330.31, 1104.74, 1049.00, + 1242.65, 1136.09, 1402.20, 1293.11, 1203.44, 1333.25, 1239.05, 1229.50, 1209.23, 1146.20, 1358.72, 1395.66, 1338.24, 1310.86, 1255.35, 1384.90, 1158.04, 1198.98, 1440.59, 1127.60, + 957.27, 1348.18, 1362.57, 1180.99, 1464.68, 1386.78, 1512.22, 1534.28, 1327.25, 1431.83, 1344.34, 1485.21, 1271.82, 1323.19, 1236.09, 1315.75, 1519.97, 1242.57, 1318.09, 1376.85, + 1278.51, 1533.16, 1460.59, 1224.81, 1236.72, 1474.99, 1366.45, 1269.97, 1357.90, 1400.97, 1495.44, 1403.39, 1435.75, 1531.07, 1341.67, 1358.59, 1247.33, 1505.51, 1388.59, 1505.12, + 1464.88, 1423.19, 1310.46, 1278.27, 1401.25, 1310.40, 1581.57, 1427.85, 1367.65, 1463.46, 1476.53, 1409.38, 1257.88, 1299.85, 1625.04, 1442.07, 1532.34, 1497.04, 1437.51, 1624.79, + 1230.74, 1367.82, 1534.68, 1330.36, 1135.18, 1501.52, 1490.87, 1358.10, 1286.56, 1358.83, 1356.88, 1512.96, 1250.52, 1272.49, 1274.92, 1305.45, 1227.33, 1135.43, 1162.45, 1230.09, + 1385.53, 1230.82, 1243.73, 1297.78, 1234.57, 1488.49, 1293.94, 1251.93, 1145.57, 1356.51, 1208.46, 1241.36, 1273.63, 1288.38, 1365.52, 1321.69, 1331.95, 1379.18, 1281.63, 1354.01, + 1224.44, 1440.92, 1317.49, 1362.65, 1403.81, 1372.31, 1383.65, 1115.44, 1327.92, 1296.24, 1512.29, 1343.31, 1283.19, 1404.62, 1263.54, 1228.75, 1174.57, 1171.94, 1559.27, 1376.76, + 1456.71, 1345.08, 1380.05, 1459.01, 1212.10, 1348.34, 1492.67, 1287.52, 1112.90, 1499.50, 1326.50, 1268.42, 1039.32, 1159.37, 1261.43, 1324.98, 1100.77, 1171.99, 1087.34, 1102.53, + 1122.55, 1021.05, 1056.53, 1142.89, 1269.32, 1112.13, 1015.51, 1135.11, 1092.82, 1237.04, 1076.18, 1128.87, 1048.15, 1195.04, 1015.79, 1190.58, 1164.24, 1212.17, 1172.98, 1075.36, + 1228.39, 1240.92, 1150.23, 1237.26, 1086.94, 1254.15, 1132.80, 1164.63, 1162.59, 1136.61, 1173.39, 965.03, 1177.22, 1131.64, 1254.41, 1214.57, 1089.64, 1239.24, 1106.76, 1037.27, + 962.49, 1034.46, 1297.65, 1254.56, 1207.93, 1216.06, 1119.13, 1312.59, 1112.75, 1097.98, 1307.74, 1192.41, 973.53, 1387.04, 1157.31, 1099.13, 1311.17, 1378.00, 1469.13, 1590.78, + 1333.74, 1336.15, 1297.78, 1473.36, 1289.06, 1302.42, 1201.01, 1266.29, 1503.54, 1312.87, 1262.47, 1275.63, 1395.36, 1476.57, 1312.36, 1262.03, 1233.52, 1395.29, 1228.28, 1409.59, + 1387.55, 1403.12, 1430.41, 1272.49, 1428.01, 1479.15, 1339.01, 1457.99, 1369.05, 1393.67, 1413.85, 1431.64, 1376.41, 1390.82, 1314.10, 1180.77, 1298.37, 1343.59, 1467.81, 1361.09, + 1431.13, 1478.41, 1348.23, 1394.75, 1246.04, 1296.82, 1526.66, 1458.45, 1473.05, 1495.85, 1282.82, 1599.32, 1427.10, 1350.46, 1464.37, 1271.35, 1181.11, 1559.64, 1561.56, 1389.35, + 1369.84, 1419.83, 1451.45, 1681.61, 1436.44, 1348.12, 1308.13, 1388.24, 1301.13, 1385.31, 1220.28, 1341.28, 1601.04, 1331.48, 1325.58, 1290.60, 1232.76, 1642.37, 1411.39, 1377.22, + 1156.76, 1466.42, 1375.66, 1325.09, 1408.20, 1437.40, 1412.27, 1474.78, 1429.78, 1518.94, 1426.34, 1495.92, 1366.96, 1532.46, 1439.96, 1388.39, 1398.59, 1562.84, 1378.79, 1331.36, + 1412.45, 1305.85, 1580.16, 1359.08, 1343.40, 1530.16, 1364.59, 1285.68, 1317.68, 1368.55, 1723.86, 1409.11, 1699.95, 1580.27, 1439.28, 1528.99, 1482.09, 1450.39, 1640.19, 1379.11, + 1242.22, 1607.38, 1529.27, 1414.70, 1266.13, 1260.65, 1279.51, 1502.70, 1164.50, 1270.53, 1223.93, 1280.00, 1210.34, 1181.94, 1027.15, 1218.78, 1401.17, 1092.32, 1098.36, 1086.59, + 1176.60, 1377.04, 1199.74, 1119.22, 1191.42, 1411.57, 1248.73, 1205.67, 1231.78, 1151.91, 1239.38, 1347.67, 1253.05, 1343.59, 1284.73, 1303.14, 1126.30, 1303.28, 1197.07, 1290.40, + 1222.08, 1269.38, 1281.51, 1188.44, 1311.67, 1214.92, 1432.29, 1174.58, 1265.55, 1298.27, 1154.89, 1243.58, 1042.13, 1102.71, 1476.41, 1204.74, 1360.13, 1397.41, 1231.77, 1429.69, + 1197.13, 1276.24, 1299.34, 1187.89, 1114.67, 1363.68, 1379.29, 1171.70, 1313.87, 1352.24, 1441.85, 1667.44, 1351.17, 1313.45, 1240.02, 1208.08, 1192.24, 1235.72, 1178.14, 1183.12, + 1403.52, 1250.37, 1238.65, 1235.05, 1119.69, 1466.08, 1381.23, 1271.59, 988.59, 1354.66, 1345.17, 1279.41, 1295.76, 1272.77, 1376.11, 1406.65, 1285.50, 1477.70, 1328.50, 1429.22, + 1224.42, 1448.28, 1261.41, 1336.04, 1378.87, 1335.38, 1327.60, 1199.76, 1155.44, 1160.00, 1452.01, 1382.43, 1341.91, 1450.36, 1302.41, 1351.84, 1158.69, 1319.26, 1543.70, 1357.04, + 1533.51, 1426.15, 1387.27, 1526.33, 1228.63, 1320.55, 1432.95, 1315.83, 1049.43, 1500.71, 1353.63, 1368.97, 1139.31, 1157.17, 1384.59, 1380.63, 1311.81, 1234.87, 1312.66, 1303.28, + 1059.96, 1117.79, 1070.43, 1129.95, 1432.29, 1153.08, 1187.14, 1287.10, 1165.82, 1348.58, 1212.90, 1204.39, 1174.20, 1272.09, 1173.52, 1162.60, 1233.63, 1305.57, 1338.09, 1172.95, + 1323.86, 1324.07, 1243.67, 1266.72, 1170.81, 1398.73, 1119.67, 1331.76, 1175.22, 1201.22, 1211.26, 1127.93, 1328.62, 1271.81, 1474.22, 1339.07, 1270.04, 1259.59, 1228.70, 1161.23, + 1210.48, 1133.59, 1493.76, 1271.63, 1328.03, 1254.34, 1389.44, 1334.65, 1232.48, 1347.65, 1322.99, 1186.21, 1086.77, 1415.26, 1294.45, 1282.19, 1531.11, 1471.22, 1581.93, 1722.80, + 1505.51, 1453.34, 1412.37, 1422.03, 1293.06, 1310.27, 1294.47, 1416.66, 1600.64, 1341.85, 1341.85, 1451.51, 1367.89, 1716.03, 1573.49, 1361.98, 1197.26, 1473.62, 1355.35, 1361.63, + 1471.37, 1457.78, 1473.47, 1400.30, 1457.48, 1598.43, 1502.65, 1578.03, 1451.60, 1657.89, 1427.07, 1526.75, 1508.23, 1608.07, 1512.20, 1345.54, 1450.02, 1373.91, 1709.84, 1510.90, + 1468.48, 1554.60, 1447.69, 1403.40, 1439.40, 1364.05, 1649.56, 1519.12, 1662.38, 1580.64, 1521.50, 1648.85, 1473.95, 1537.87, 1603.35, 1405.32, 1277.63, 1635.12, 1530.58, 1527.68, + 1376.14, 1259.62, 1404.31, 1491.97, 1331.98, 1323.84, 1261.00, 1340.33, 1212.09, 1272.78, 1149.12, 1251.68, 1474.67, 1215.21, 1209.61, 1208.81, 1223.37, 1440.41, 1299.06, 1191.88, + 1159.34, 1391.74, 1411.92, 1238.45, 1366.96, 1326.26, 1374.60, 1281.97, 1335.22, 1429.39, 1234.86, 1347.17, 1296.84, 1441.90, 1285.37, 1323.53, 1295.99, 1417.08, 1297.75, 1166.38, + 1345.28, 1205.89, 1508.88, 1352.85, 1387.88, 1397.88, 1360.48, 1318.44, 1183.16, 1290.36, 1548.41, 1268.90, 1491.98, 1406.27, 1336.20, 1491.58, 1320.34, 1336.40, 1423.83, 1315.12, + 1140.91, 1435.46, 1362.80, 1367.75, 1208.92, 1214.60, 1291.40, 1393.45, 1352.84, 1177.35, 1233.46, 1243.24, 1202.87, 1152.15, 1102.70, 1135.41, 1311.41, 1209.16, 1166.73, 1153.12, + 1082.47, 1368.74, 1272.80, 1247.51, 972.26, 1268.29, 1180.56, 1139.86, 1160.60, 1213.71, 1159.53, 1298.88, 1185.02, 1340.95, 1207.52, 1320.85, 1165.75, 1343.30, 1320.00, 1267.42, + 1284.86, 1303.08, 1196.86, 1109.66, 1177.52, 1129.73, 1377.07, 1293.27, 1104.89, 1318.76, 1217.58, 1159.26, 1134.64, 1227.63, 1465.98, 1179.33, 1349.20, 1310.41, 1333.38, 1341.44, + 1204.24, 1234.32, 1426.88, 1212.51, 1090.72, 1367.31, 1306.05, 1198.97, 1324.78, 1346.77, 1413.33, 1636.98, 1448.15, 1362.02, 1289.33, 1392.20, 1303.17, 1337.15, 1208.25, 1255.99, + 1570.02, 1285.29, 1254.08, 1266.47, 1371.72, 1524.30, 1318.69, 1309.52, 1280.95, 1448.40, 1241.72, 1305.67, 1428.22, 1313.74, 1429.82, 1245.78, 1457.28, 1413.81, 1374.30, 1425.78, + 1386.56, 1480.91, 1370.04, 1377.77, 1448.03, 1484.91, 1440.71, 1135.39, 1430.11, 1296.96, 1528.05, 1457.42, 1443.13, 1488.35, 1343.99, 1363.68, 1292.27, 1385.99, 1610.51, 1429.82, + 1581.36, 1555.99, 1405.08, 1588.68, 1483.02, 1433.00, 1484.10, 1337.65, 1216.33, 1530.77, 1414.60, 1352.93, 1410.85, 1404.43, 1499.88, 1654.33, 1419.27, 1381.92, 1446.47, 1313.75, + 1230.75, 1311.00, 1281.90, 1336.07, 1486.57, 1303.81, 1283.26, 1203.40, 1251.23, 1607.85, 1466.10, 1354.93, 1139.88, 1361.32, 1332.28, 1256.61, 1325.96, 1293.50, 1383.11, 1380.59, + 1410.64, 1503.91, 1421.53, 1431.41, 1325.24, 1542.63, 1332.45, 1445.11, 1361.08, 1475.89, 1355.22, 1261.77, 1358.17, 1276.94, 1568.52, 1461.70, 1382.64, 1434.41, 1416.95, 1289.51, + 1280.10, 1333.82, 1592.15, 1440.51, 1596.76, 1593.17, 1441.33, 1553.98, 1355.84, 1444.55, 1554.09, 1333.92, 1217.44, 1539.21, 1425.98, 1438.95, 1326.11, 1337.20, 1418.70, 1565.13, + 1346.15, 1290.62, 1390.47, 1296.12, 1222.93, 1208.62, 1157.11, 1232.63, 1431.54, 1168.34, 1209.56, 1266.56, 1335.13, 1510.47, 1218.02, 1308.08, 1163.80, 1395.41, 1241.01, 1233.40, + 1319.51, 1337.43, 1331.33, 1363.23, 1294.18, 1421.20, 1315.08, 1406.64, 1342.14, 1419.83, 1328.49, 1338.51, 1319.43, 1378.65, 1317.56, 1178.78, 1314.38, 1281.70, 1528.55, 1248.40, + 1287.56, 1396.60, 1304.52, 1274.46, 1270.10, 1141.44, 1508.64, 1261.97, 1498.70, 1296.16, 1294.33, 1447.11, 1317.39, 1387.30, 1419.28, 1175.32, 1093.19, 1393.37, 1432.13, 1394.91, + 1339.44, 1451.46, 1471.60, 1647.16, 1395.21, 1329.47, 1212.87, 1280.47, 1242.28, 1256.06, 1229.93, 1290.29, 1501.08, 1217.36, 1260.44, 1325.51, 1175.00, 1555.52, 1382.92, 1311.71, + 1136.58, 1354.00, 1299.64, 1349.04, 1383.59, 1351.55, 1450.07, 1263.82, 1348.83, 1480.50, 1323.08, 1472.22, 1313.66, 1503.74, 1278.77, 1374.14, 1383.02, 1426.02, 1387.34, 1283.57, + 1391.57, 1202.51, 1506.87, 1435.41, 1387.86, 1495.19, 1337.06, 1342.56, 1313.18, 1388.45, 1549.16, 1501.64, 1582.78, 1457.61, 1393.05, 1532.14, 1296.13, 1417.10, 1538.59, 1331.41, + 1146.52, 1483.76, 1364.16, 1342.58, 1339.84, 1231.51, 1392.19, 1541.26, 1379.06, 1284.47, 1333.99, 1168.79, 1240.25, 1243.38, 1225.68, 1192.46, 1478.92, 1143.23, 1194.31, 1184.91, + 1244.84, 1460.50, 1353.63, 1309.48, 1198.55, 1343.88, 1285.32, 1183.00, 1285.77, 1329.35, 1249.94, 1336.30, 1272.53, 1475.49, 1341.50, 1462.93, 1289.21, 1460.03, 1274.86, 1412.97, + 1309.66, 1320.84, 1207.50, 1154.06, 1326.60, 1294.83, 1430.91, 1303.30, 1412.77, 1334.93, 1417.29, 1186.29, 1167.63, 1136.88, 1547.47, 1292.33, 1537.90, 1413.62, 1477.22, 1370.40, + 1266.79, 1468.12, 1541.73, 1280.70, 1099.87, 1431.57, 1370.73, 1430.16, 1287.15, 1302.94, 1367.50, 1479.61, 1183.45, 1271.03, 1104.45, 1254.57, 1067.91, 1055.56, 1147.17, 1099.07, + 1412.01, 1175.60, 1122.21, 1168.64, 1217.95, 1435.20, 1244.95, 1174.28, 1037.30, 1346.03, 1126.56, 1133.71, 1207.31, 1213.28, 1396.69, 1246.52, 1310.06, 1341.45, 1199.27, 1302.28, + 1193.38, 1415.50, 1300.40, 1293.62, 1265.19, 1312.18, 1194.04, 1070.98, 1200.29, 1231.26, 1382.38, 1245.62, 1289.17, 1253.46, 1203.08, 1216.75, 1216.75, 1113.40, 1511.99, 1333.84, + 1491.33, 1364.50, 1252.77, 1389.22, 1266.92, 1262.67, 1308.35, 1139.02, 1095.95, 1250.58, 1256.60, 1207.54, 1258.37, 1222.83, 1387.63, 1565.40, 1286.28, 1378.77, 1202.50, 1226.40, + 1233.51, 1272.39, 1135.10, 1272.53, 1450.78, 1205.86, 1172.64, 1251.87, 1293.64, 1408.35, 1253.49, 1169.40, 1094.99, 1473.96, 1156.60, 1152.69, 1240.37, 1336.59, 1256.09, 1270.34, + 1379.24, 1264.01, 1305.27, 1316.17, 1293.57, 1354.00, 1248.79, 1230.31, 1220.46, 1266.96, 1321.42, 1161.22, 1321.67, 1215.86, 1477.98, 1247.61, 1280.55, 1396.92, 1217.64, 1290.41, + 1120.19, 1274.98, 1522.36, 1319.65, 1452.76, 1448.01, 1346.93, 1538.98, 1387.19, 1302.15, 1393.31, 1255.87, 1105.50, 1455.56, 1369.93, 1209.40, 1381.89, 1430.12, 1450.82, 1635.71, + 1437.24, 1390.56, 1342.80, 1428.70, 1304.14, 1425.51, 1222.89, 1303.49, 1524.84, 1368.17, 1254.39, 1262.64, 1289.81, 1553.24, 1336.51, 1305.66, 1175.94, 1402.50, 1383.16, 1314.48, + 1333.52, 1364.53, 1348.77, 1331.30, 1485.87, 1504.13, 1293.29, 1503.41, 1250.85, 1495.27, 1310.55, 1416.37, 1483.68, 1408.91, 1391.24, 1197.45, 1403.04, 1310.95, 1529.08, 1376.88, + 1411.55, 1494.99, 1419.20, 1348.40, 1245.18, 1339.69, 1672.18, 1481.88, 1471.30, 1589.93, 1510.08, 1591.33, 1434.29, 1500.06, 1437.97, 1336.17, 1210.29, 1496.89, 1431.74, 1434.55, + 1109.32, 1160.85, 1183.75, 1317.10, 1136.56, 1202.62, 1257.64, 1211.35, 960.97, 1102.03, 1035.43, 1094.03, 1322.79, 1109.01, 1178.40, 1103.12, 1115.55, 1351.82, 1180.03, 1116.25, + 1067.68, 1210.60, 1141.34, 1138.26, 1164.25, 1188.62, 1145.14, 1166.63, 1151.11, 1266.50, 1196.94, 1283.88, 1029.97, 1290.98, 1111.12, 1167.39, 1194.87, 1163.32, 1146.74, 980.08, + 1133.81, 1213.24, 1390.11, 1235.55, 1185.48, 1129.37, 1195.50, 1057.05, 1045.65, 1150.77, 1310.88, 1207.02, 1306.82, 1266.99, 1191.95, 1332.92, 1186.43, 1196.87, 1277.65, 1113.34, + 997.77, 1325.07, 1240.91, 1192.01, 1328.43, 1524.76, 1378.11, 1655.42, 1482.31, 1257.37, 1371.89, 1391.01, 1290.70, 1320.22, 1278.98, 1259.12, 1517.19, 1396.03, 1312.04, 1322.48, + 1342.52, 1615.32, 1338.23, 1323.15, 1259.52, 1392.80, 1297.01, 1396.00, 1374.56, 1369.10, 1377.74, 1341.32, 1343.13, 1494.14, 1353.10, 1539.29, 1394.78, 1554.40, 1437.57, 1392.17, + 1436.09, 1462.98, 1462.19, 1287.17, 1353.18, 1347.42, 1494.53, 1417.34, 1416.12, 1472.78, 1293.32, 1307.72, 1291.17, 1426.14, 1707.64, 1393.30, 1626.75, 1552.00, 1554.54, 1585.40, + 1462.09, 1566.27, 1554.21, 1355.06, 1247.11, 1530.26, 1509.97, 1483.55, 1157.37, 1224.96, 1303.57, 1373.71, 1108.41, 1151.40, 1128.28, 1104.19, 1036.39, 1078.01, 1126.44, 1077.43, + 1260.49, 1049.67, 1093.87, 1150.62, 1191.45, 1340.40, 1063.97, 1177.66, 1092.67, 1192.58, 1171.95, 1114.64, 1132.36, 1187.56, 1184.95, 1098.46, 1242.38, 1252.91, 1146.14, 1213.53, + 1151.48, 1302.51, 1210.09, 1277.25, 1212.93, 1169.25, 1232.64, 1013.59, 1131.25, 1181.94, 1195.44, 1222.64, 1227.38, 1262.32, 1169.22, 1110.55, 1056.72, 1113.43, 1372.05, 1172.92, + 1341.51, 1333.83, 1318.03, 1297.42, 1128.36, 1286.40, 1432.39, 1234.76, 960.27, 1262.17, 1230.64, 1289.61, 1178.74, 1322.92, 1365.09, 1560.18, 1240.06, 1298.16, 1270.39, 1380.29, + 1178.59, 1282.83, 1131.41, 1247.39, 1454.86, 1299.12, 1234.57, 1251.17, 1226.32, 1393.81, 1315.78, 1187.97, 1116.85, 1296.71, 1258.36, 1319.93, 1404.14, 1256.31, 1250.91, 1225.50, + 1318.11, 1406.80, 1374.43, 1321.74, 1271.49, 1367.09, 1280.77, 1216.35, 1378.19, 1344.02, 1280.09, 1266.72, 1361.90, 1082.34, 1467.46, 1247.23, 1225.47, 1397.46, 1170.62, 1280.63, + 1215.11, 1305.35, 1472.73, 1402.19, 1438.47, 1387.88, 1343.98, 1551.27, 1286.53, 1306.61, 1473.54, 1268.90, 1026.88, 1435.20, 1338.70, 1201.07, 1205.67, 1180.31, 1277.09, 1487.67, + 1275.37, 1205.90, 1168.27, 1151.28, 1266.29, 1223.82, 1025.42, 1126.89, 1418.77, 1258.73, 1151.18, 1185.15, 1201.54, 1305.38, 1224.83, 1195.85, 1156.78, 1236.28, 1140.40, 1218.58, + 1264.79, 1310.85, 1267.30, 1276.64, 1345.50, 1424.70, 1313.61, 1274.54, 1094.44, 1262.35, 1244.23, 1306.83, 1273.37, 1289.96, 1211.66, 1111.85, 1231.99, 1238.70, 1388.57, 1291.91, + 1313.12, 1363.81, 1206.82, 1224.65, 1157.49, 1166.88, 1407.36, 1380.27, 1427.48, 1442.76, 1246.20, 1427.56, 1280.26, 1204.75, 1406.67, 1269.74, 1098.59, 1504.81, 1333.90, 1320.63, + 1439.39, 1500.46, 1521.08, 1643.49, 1370.21, 1362.21, 1399.55, 1373.25, 1288.44, 1307.67, 1256.60, 1368.86, 1587.53, 1351.12, 1269.76, 1298.72, 1277.12, 1573.40, 1379.21, 1313.94, + 1350.92, 1346.48, 1358.60, 1362.78, 1385.25, 1415.82, 1417.94, 1276.20, 1399.87, 1503.54, 1365.93, 1488.50, 1229.29, 1605.94, 1378.20, 1407.51, 1463.04, 1487.27, 1308.27, 1295.92, + 1479.90, 1329.27, 1537.17, 1375.43, 1384.39, 1498.94, 1355.79, 1248.86, 1266.85, 1343.97, 1577.34, 1492.68, 1574.08, 1540.48, 1430.11, 1616.07, 1314.66, 1394.15, 1547.96, 1343.40, + 1238.82, 1453.75, 1400.22, 1411.65, 1266.02, 1414.66, 1393.70, 1586.89, 1439.13, 1147.83, 1388.78, 1205.49, 1210.84, 1220.89, 1086.58, 1282.55, 1383.51, 1173.76, 1187.24, 1206.61, + 1189.22, 1466.96, 1221.41, 1281.40, 1112.21, 1303.78, 1244.05, 1199.54, 1150.01, 1291.89, 1187.27, 1271.99, 1300.04, 1388.98, 1249.89, 1377.25, 1331.37, 1344.50, 1185.39, 1369.23, + 1297.42, 1346.96, 1344.56, 1085.52, 1322.79, 1161.28, 1369.76, 1327.06, 1254.11, 1295.80, 1175.43, 1147.85, 1186.42, 1235.36, 1547.78, 1293.41, 1462.35, 1358.42, 1280.40, 1305.61, + 1284.39, 1322.74, 1458.59, 1227.66, 1242.84, 1422.63, 1283.41, 1293.64, 1236.86, 1238.83, 1325.46, 1339.01, 1243.56, 1276.09, 1223.38, 1317.69, 1026.85, 1158.69, 1102.14, 1115.35, + 1243.15, 1152.42, 1207.79, 1174.65, 1257.85, 1356.79, 1174.03, 1151.82, 1116.41, 1320.78, 1188.24, 1150.60, 1187.63, 1218.89, 1267.38, 1132.95, 1250.98, 1318.38, 1122.67, 1235.94, + 1204.07, 1331.33, 1247.02, 1269.95, 1240.11, 1262.19, 1126.53, 1030.14, 1222.95, 1211.25, 1363.31, 1343.91, 1257.16, 1283.36, 1396.42, 1256.45, 1195.48, 1121.06, 1473.56, 1234.76, + 1363.67, 1305.92, 1345.16, 1403.26, 1201.26, 1268.59, 1298.15, 1035.01, 1016.79, 1252.66, 1301.61, 1217.53, 1294.85, 1272.48, 1438.89, 1559.17, 1373.48, 1459.73, 1309.49, 1395.41, + 1253.73, 1330.35, 1170.63, 1251.99, 1459.50, 1183.12, 1196.73, 1321.25, 1313.51, 1423.84, 1327.71, 1202.91, 1222.77, 1513.00, 1291.28, 1205.45, 1366.21, 1464.72, 1368.94, 1347.14, + 1408.92, 1530.45, 1289.40, 1376.09, 1313.88, 1407.88, 1279.27, 1403.69, 1335.38, 1386.07, 1362.59, 1073.05, 1270.84, 1284.84, 1526.29, 1415.24, 1394.95, 1447.69, 1398.90, 1305.83, + 1274.60, 1252.84, 1587.27, 1371.74, 1467.79, 1434.15, 1375.48, 1545.78, 1266.71, 1317.48, 1572.39, 1244.32, 1174.21, 1468.65, 1413.09, 1290.17, 1197.21, 1155.17, 1263.35, 1275.64, + 1172.47, 1166.75, 1044.69, 1269.30, 1050.90, 1086.32, 1023.80, 1087.59, 1323.49, 973.71, 1130.29, 1094.06, 1026.61, 1277.66, 1148.16, 1004.99, 1077.11, 1247.31, 1140.63, 1135.91, + 1193.23, 1158.95, 1238.92, 1111.04, 1119.26, 1365.83, 1098.28, 1154.73, 1024.14, 1265.05, 1204.07, 1293.20, 1264.65, 1157.76, 1059.30, 1018.65, 1143.54, 1143.00, 1259.12, 1201.64, + 1150.86, 1251.88, 1317.65, 1162.50, 992.08, 1126.13, 1323.76, 1158.03, 1267.61, 1293.64, 1237.19, 1384.30, 1025.94, 1139.64, 1297.74, 1216.18, 993.00, 1300.77, 1218.99, 1093.70, + 1311.48, 1379.92, 1391.74, 1445.09, 1292.05, 1323.08, 1298.06, 1391.88, 1159.64, 1262.33, 1149.94, 1219.13, 1434.55, 1241.38, 1228.38, 1255.36, 1287.72, 1541.03, 1349.55, 1235.28, + 1182.24, 1330.28, 1208.99, 1294.62, 1384.90, 1249.50, 1334.11, 1137.09, 1360.42, 1419.80, 1252.52, 1460.52, 1364.99, 1483.29, 1262.38, 1290.85, 1393.34, 1474.44, 1301.33, 1126.24, + 1332.38, 1186.72, 1429.03, 1304.63, 1254.23, 1479.85, 1226.02, 1171.24, 1321.09, 1285.88, 1477.04, 1426.97, 1464.75, 1483.92, 1313.67, 1615.16, 1302.34, 1412.35, 1390.38, 1185.07, + 1031.23, 1431.41, 1362.11, 1279.65, 1147.52, 1265.17, 1338.69, 1294.82, 1081.53, 1155.02, 1171.38, 1284.06, 996.85, 1085.68, 1079.02, 1035.53, 1365.52, 1111.12, 1050.53, 1170.60, + 1154.94, 1401.82, 1131.67, 1165.38, 1080.77, 1251.29, 1187.41, 1202.82, 1161.96, 1166.27, 1264.96, 1224.00, 1232.78, 1356.04, 1235.77, 1367.99, 1080.91, 1395.61, 1116.94, 1197.89, + 1152.28, 1282.20, 1265.43, 1105.87, 1160.68, 1185.00, 1377.18, 1160.41, 1237.22, 1369.00, 1172.74, 1143.98, 1164.60, 1059.15, 1490.22, 1281.17, 1272.72, 1306.11, 1257.99, 1435.04, + 1156.08, 1275.73, 1268.04, 1056.30, 962.94, 1269.43, 1272.12, 1262.24, 1212.76, 1148.18, 1322.38, 1439.61, 1326.34, 1348.20, 1146.04, 1213.72, 1202.08, 1253.69, 1144.32, 1217.91, + 1487.40, 1187.52, 1089.16, 1188.73, 1165.73, 1402.32, 1221.57, 1045.12, 1064.80, 1326.59, 1127.45, 1105.51, 1205.64, 1341.33, 1306.25, 1205.99, 1321.27, 1307.26, 1239.29, 1379.26, + 1220.08, 1373.86, 1274.71, 1285.41, 1272.40, 1249.75, 1264.54, 1089.46, 1183.74, 1163.74, 1415.27, 1413.09, 1297.57, 1262.34, 1355.14, 1284.73, 1208.88, 1302.79, 1486.06, 1227.25, + 1438.54, 1249.08, 1329.12, 1497.28, 1315.91, 1372.41, 1364.22, 1205.45, 1057.81, 1386.32, 1352.89, 1294.29, 1325.27, 1230.70, 1321.97, 1486.89, 1399.78, 1294.22, 1267.40, 1343.29, + 1235.20, 1270.54, 1121.95, 1250.46, 1478.94, 1205.37, 1219.79, 1152.37, 1161.98, 1466.89, 1362.33, 1232.15, 1071.75, 1374.74, 1195.27, 1254.65, 1194.23, 1331.21, 1282.74, 1387.72, + 1327.09, 1451.54, 1293.32, 1388.75, 1173.54, 1410.52, 1246.23, 1421.01, 1352.69, 1347.36, 1225.86, 1172.25, 1214.56, 1218.43, 1476.12, 1327.09, 1228.78, 1331.55, 1374.88, 1216.15, + 1184.61, 1275.82, 1542.57, 1276.47, 1440.43, 1462.71, 1422.04, 1461.29, 1230.16, 1392.49, 1467.53, 1279.27, 1118.19, 1440.74, 1458.13, 1403.59, 1368.83, 1301.71, 1410.11, 1550.70, + 1329.09, 1376.40, 1284.55, 1321.19, 1211.98, 1352.49, 1185.79, 1269.39, 1571.69, 1236.95, 1198.81, 1316.00, 1245.78, 1465.14, 1349.26, 1275.25, 1176.92, 1332.87, 1268.57, 1195.62, + 1258.48, 1351.58, 1365.71, 1308.49, 1346.47, 1406.09, 1215.81, 1464.78, 1268.32, 1487.75, 1278.61, 1384.99, 1346.72, 1299.86, 1301.33, 1129.20, 1267.63, 1200.91, 1519.21, 1366.10, + 1359.52, 1400.78, 1292.35, 1266.57, 1199.34, 1314.76, 1593.66, 1317.76, 1464.75, 1440.56, 1359.43, 1498.53, 1235.95, 1396.02, 1470.29, 1225.62, 1121.64, 1508.88, 1415.02, 1354.13, + 1094.40, 1256.05, 1306.23, 1484.59, 1159.38, 1184.43, 1160.58, 1239.94, 1066.13, 1120.31, 1084.26, 1107.13, 1232.42, 1185.27, 1122.73, 1218.90, 1158.50, 1390.26, 1222.39, 1203.27, + 1045.68, 1255.68, 1168.27, 1176.79, 1298.02, 1267.50, 1307.26, 1289.89, 1247.03, 1287.59, 1222.51, 1262.53, 1148.63, 1271.35, 1245.51, 1187.88, 1234.49, 1307.71, 1249.04, 1116.37, + 1219.62, 1218.57, 1349.69, 1204.77, 1223.39, 1327.52, 1178.79, 1126.71, 1144.74, 1082.20, 1503.34, 1301.65, 1392.24, 1318.44, 1260.89, 1274.02, 1282.23, 1266.53, 1428.87, 1171.14, + 1111.19, 1426.06, 1228.13, 1162.35, 1290.22, 1234.24, 1447.04, 1554.34, 1329.19, 1395.15, 1224.29, 1368.36, 1262.15, 1235.36, 1078.19, 1217.33, 1493.90, 1206.57, 1278.17, 1261.99, + 1207.40, 1527.35, 1164.25, 1225.90, 1209.26, 1448.77, 1186.13, 1225.96, 1427.34, 1285.64, 1345.22, 1242.62, 1319.73, 1382.43, 1353.37, 1346.72, 1312.13, 1358.70, 1315.08, 1232.98, + 1254.44, 1394.73, 1317.85, 1135.92, 1376.34, 1246.70, 1506.46, 1352.52, 1373.02, 1465.13, 1343.40, 1325.84, 1297.73, 1252.62, 1522.17, 1325.26, 1533.99, 1484.58, 1420.57, 1539.40, + 1309.14, 1336.26, 1459.18, 1308.33, 1187.05, 1544.99, 1431.61, 1252.38, 1297.08, 1386.36, 1534.82, 1508.74, 1322.47, 1439.91, 1396.94, 1350.46, 1277.41, 1225.67, 1333.70, 1327.48, + 1505.64, 1263.33, 1252.28, 1351.43, 1316.36, 1539.11, 1348.90, 1296.86, 1176.41, 1429.35, 1293.29, 1275.66, 1397.76, 1408.99, 1357.66, 1318.09, 1363.31, 1513.22, 1427.17, 1492.98, + 1366.35, 1582.13, 1356.30, 1444.21, 1382.33, 1365.70, 1420.20, 1217.78, 1432.58, 1228.45, 1616.54, 1409.56, 1307.97, 1475.86, 1318.09, 1367.11, 1286.74, 1257.13, 1573.40, 1372.58, + 1447.57, 1427.08, 1471.14, 1566.62, 1257.12, 1423.67, 1589.79, 1344.49, 1130.92, 1498.77, 1430.68, 1448.58, 1273.37, 1187.48, 1364.40, 1523.23, 1134.45, 1280.58, 1181.08, 1208.90, + 1122.63, 1174.70, 1126.42, 1201.24, 1346.38, 1141.12, 1131.35, 1126.39, 1096.53, 1371.79, 1273.42, 1263.91, 1027.28, 1217.60, 1233.67, 1146.90, 1230.50, 1199.41, 1100.08, 1152.27, + 1273.63, 1323.58, 1214.36, 1346.47, 1135.80, 1375.39, 1235.42, 1336.22, 1267.26, 1262.96, 1092.23, 1234.82, 1264.79, 1214.61, 1348.77, 1253.45, 1122.38, 1239.97, 1224.84, 1152.76, + 1134.34, 1142.76, 1429.84, 1189.04, 1387.07, 1278.77, 1361.50, 1392.18, 1206.86, 1334.71, 1346.73, 1242.13, 1050.60, 1341.34, 1260.75, 1238.45, 1259.03, 1452.68, 1421.62, 1570.44, + 1251.15, 1244.67, 1329.80, 1327.47, 1172.33, 1235.11, 1245.45, 1199.66, 1397.00, 1148.54, 1301.25, 1264.99, 1293.76, 1468.17, 1340.31, 1238.17, 1251.76, 1361.59, 1341.50, 1352.14, + 1323.34, 1308.28, 1426.95, 1417.59, 1269.54, 1456.13, 1317.12, 1445.25, 1312.21, 1459.87, 1347.29, 1358.24, 1396.66, 1443.73, 1350.70, 1268.52, 1365.85, 1364.99, 1421.07, 1307.91, + 1352.22, 1391.29, 1355.71, 1216.58, 1176.76, 1202.96, 1642.02, 1413.84, 1638.88, 1448.85, 1415.71, 1453.51, 1356.51, 1397.14, 1551.89, 1241.79, 1051.81, 1481.01, 1375.11, 1306.43, + 1391.90, 1448.82, 1525.69, 1650.86, 1352.60, 1398.71, 1409.39, 1522.05, 1223.15, 1417.08, 1140.56, 1282.95, 1512.92, 1306.01, 1310.24, 1293.54, 1347.89, 1517.58, 1384.35, 1324.97, + 1246.73, 1380.81, 1304.58, 1326.74, 1381.90, 1365.68, 1340.00, 1292.61, 1463.39, 1444.67, 1343.18, 1426.27, 1341.80, 1491.57, 1423.12, 1381.26, 1448.98, 1411.46, 1300.85, 1256.10, + 1367.57, 1251.11, 1535.47, 1420.20, 1447.88, 1459.55, 1441.55, 1314.46, 1233.96, 1360.85, 1603.25, 1477.07, 1444.84, 1500.80, 1486.72, 1601.72, 1338.91, 1511.31, 1509.19, 1342.63, + 1213.00, 1555.80, 1461.04, 1324.73, 1350.26, 1407.60, 1553.58, 1622.25, 1309.04, 1278.07, 1257.23, 1263.75, 1204.42, 1237.60, 1135.64, 1323.82, 1440.34, 1206.64, 1147.32, 1284.33, + 1298.69, 1563.46, 1245.16, 1371.08, 1110.77, 1353.32, 1272.94, 1376.96, 1393.38, 1327.03, 1390.54, 1231.77, 1391.41, 1334.24, 1462.92, 1495.89, 1396.69, 1501.23, 1343.75, 1252.75, + 1338.90, 1593.07, 1375.33, 1226.33, 1407.39, 1229.39, 1527.84, 1289.46, 1396.80, 1388.67, 1198.63, 1211.68, 1330.36, 1218.02, 1483.55, 1494.09, 1524.05, 1427.59, 1263.21, 1483.71, + 1281.09, 1329.57, 1457.08, 1284.94, 1185.33, 1443.42, 1330.63, 1430.03, 1214.06, 1219.89, 1347.54, 1421.58, 1180.42, 1272.71, 1211.46, 1326.81, 1037.82, 1082.19, 1161.71, 1141.40, + 1350.77, 1189.16, 1100.50, 1203.64, 1121.20, 1380.45, 1222.09, 1115.74, 1117.06, 1254.62, 1148.37, 1123.30, 1181.78, 1308.93, 1173.63, 1212.08, 1175.13, 1206.51, 1158.92, 1354.48, + 1187.28, 1432.28, 1261.04, 1279.24, 1216.02, 1300.33, 1216.19, 1091.07, 1235.87, 1242.67, 1378.27, 1250.20, 1229.67, 1274.75, 1192.17, 1186.72, 1065.46, 1210.51, 1413.41, 1192.26, + 1319.02, 1308.81, 1343.64, 1323.26, 1216.37, 1278.10, 1388.78, 1165.99, 1078.57, 1239.04, 1337.30, 1274.60, 1349.44, 1467.96, 1499.66, 1723.01, 1394.09, 1391.72, 1456.78, 1508.54, + 1285.27, 1410.21, 1227.75, 1258.55, 1568.65, 1294.37, 1346.73, 1355.97, 1291.39, 1491.92, 1433.87, 1383.22, 1234.42, 1480.98, 1431.55, 1394.94, 1451.04, 1461.42, 1480.30, 1390.20, + 1451.88, 1559.52, 1316.89, 1396.52, 1385.16, 1549.24, 1376.21, 1352.67, 1490.72, 1377.56, 1324.12, 1288.39, 1486.11, 1401.94, 1597.30, 1393.09, 1393.10, 1527.19, 1346.17, 1403.61, + 1329.84, 1428.33, 1697.28, 1486.74, 1610.30, 1524.46, 1536.59, 1601.98, 1406.43, 1537.88, 1518.79, 1379.87, 1151.81, 1615.09, 1448.84, 1386.40, 1198.14, 1206.61, 1238.94, 1358.98, + 1104.33, 1060.02, 1132.03, 1218.76, 1148.86, 1139.73, 1011.63, 1011.10, 1253.39, 1145.71, 1046.80, 1098.42, 1133.10, 1332.54, 1114.50, 1108.41, 1095.69, 1186.49, 1088.61, 1177.96, + 1179.91, 1080.40, 1232.01, 1178.43, 1295.16, 1337.88, 1089.30, 1138.30, 982.34, 1238.16, 1193.96, 1128.41, 1226.30, 1110.66, 1201.22, 1026.73, 1099.94, 1082.45, 1286.87, 1182.08, + 1161.86, 1229.94, 1118.10, 1169.49, 1059.97, 1106.63, 1337.81, 1198.73, 1338.76, 1140.70, 1176.55, 1411.23, 1066.54, 1225.73, 1285.37, 1105.53, 995.55, 1251.52, 1296.70, 1183.81, + 1336.82, 1359.41, 1531.23, 1506.89, 1277.25, 1341.98, 1207.09, 1441.27, 1245.61, 1279.99, 1171.33, 1203.39, 1552.78, 1221.36, 1278.65, 1229.00, 1212.91, 1567.53, 1327.70, 1240.24, + 1221.25, 1366.21, 1299.23, 1329.50, 1364.06, 1221.40, 1345.24, 1276.10, 1358.50, 1499.46, 1370.30, 1533.58, 1307.25, 1541.06, 1373.60, 1256.80, 1411.07, 1472.58, 1381.63, 1209.79, + 1385.44, 1228.53, 1579.26, 1332.83, 1430.57, 1425.45, 1391.60, 1288.74, 1244.24, 1275.17, 1516.60, 1474.56, 1448.48, 1489.99, 1368.60, 1592.46, 1335.75, 1411.22, 1432.70, 1267.68, + 1041.35, 1491.54, 1498.69, 1323.89, 1179.47, 1288.17, 1343.09, 1495.42, 1190.80, 1208.26, 1233.67, 1266.03, 1009.92, 1189.92, 1079.33, 1226.48, 1415.04, 1174.65, 1095.22, 1124.00, + 1118.95, 1334.79, 1243.54, 1187.79, 1081.39, 1204.17, 1153.96, 1225.61, 1165.12, 1278.03, 1207.02, 1105.44, 1266.90, 1290.10, 1156.28, 1332.57, 1130.42, 1364.51, 1124.01, 1162.57, + 1257.70, 1224.27, 1163.35, 1089.64, 1331.68, 1111.06, 1321.76, 1210.18, 1203.34, 1320.04, 1119.50, 1162.15, 1211.72, 1226.56, 1418.76, 1345.12, 1364.04, 1344.66, 1322.72, 1369.63, + 1197.77, 1342.54, 1295.97, 1116.95, 1010.17, 1336.54, 1207.94, 1273.88, 1234.22, 1145.59, 1273.48, 1352.87, 1111.27, 1229.25, 1105.41, 1236.72, 1114.96, 1128.70, 1001.74, 1106.89, + 1306.04, 1147.72, 1139.74, 1197.38, 1101.79, 1346.01, 1193.67, 1053.84, 997.60, 1243.23, 1132.20, 1140.96, 1188.55, 1128.00, 1141.85, 1152.23, 1186.89, 1293.55, 1165.47, 1241.90, + 1114.40, 1382.10, 1174.74, 1128.36, 1206.13, 1252.88, 1163.47, 1058.72, 1157.54, 1136.36, 1452.71, 1189.00, 1158.47, 1286.42, 1087.34, 1117.48, 1059.71, 1200.30, 1363.05, 1194.97, + 1287.62, 1371.77, 1242.62, 1381.55, 1162.41, 1153.85, 1296.64, 1183.91, 1104.32, 1302.69, 1248.47, 1127.57, 1541.65, 1449.79, 1543.72, 1669.84, 1552.41, 1442.87, 1419.15, 1516.45, + 1365.70, 1418.19, 1283.35, 1397.02, 1636.63, 1330.73, 1354.17, 1396.58, 1343.54, 1676.34, 1545.03, 1346.49, 1205.89, 1582.05, 1492.58, 1339.30, 1505.07, 1445.89, 1521.83, 1438.11, + 1514.20, 1537.87, 1457.46, 1563.90, 1380.61, 1640.16, 1372.38, 1522.58, 1470.40, 1587.96, 1514.42, 1344.65, 1492.48, 1285.49, 1721.76, 1459.99, 1440.06, 1547.91, 1372.78, 1443.99, + 1427.05, 1452.09, 1730.53, 1504.18, 1661.41, 1506.44, 1466.96, 1729.20, 1424.56, 1526.45, 1623.14, 1377.34, 1328.57, 1535.54, 1486.59, 1426.21, 1251.77, 1271.32, 1385.16, 1513.24, + 1214.50, 1329.88, 1281.79, 1400.95, 1181.91, 1193.78, 1112.89, 1162.70, 1409.60, 1309.09, 1324.74, 1200.69, 1270.76, 1404.72, 1270.69, 1247.59, 1133.68, 1276.68, 1301.66, 1287.50, + 1245.47, 1231.10, 1338.69, 1224.15, 1459.25, 1460.39, 1298.97, 1267.27, 1198.90, 1420.61, 1242.62, 1373.64, 1278.89, 1310.16, 1265.24, 1162.40, 1356.80, 1323.82, 1486.75, 1340.86, + 1272.36, 1425.28, 1252.32, 1345.57, 1290.27, 1190.63, 1562.44, 1439.95, 1476.36, 1440.54, 1413.98, 1475.85, 1274.13, 1332.14, 1366.48, 1104.44, 1112.21, 1401.95, 1403.46, 1325.29, + 1319.27, 1331.63, 1332.49, 1472.21, 1325.58, 1311.89, 1312.22, 1480.80, 1108.58, 1245.66, 1143.69, 1163.06, 1536.72, 1239.62, 1193.78, 1265.51, 1140.02, 1461.12, 1311.68, 1260.50, + 1243.53, 1288.05, 1197.69, 1253.15, 1319.70, 1266.22, 1272.58, 1219.48, 1293.98, 1487.47, 1178.02, 1344.72, 1268.21, 1537.06, 1283.91, 1289.73, 1395.59, 1376.58, 1319.33, 1045.68, + 1310.65, 1386.68, 1532.68, 1377.28, 1279.59, 1366.86, 1403.80, 1200.92, 1189.43, 1248.40, 1591.06, 1355.88, 1377.70, 1451.58, 1480.72, 1472.42, 1246.27, 1399.85, 1400.35, 1235.28, + 1124.89, 1407.01, 1319.83, 1301.32, 1415.13, 1365.13, 1452.19, 1604.11, 1500.89, 1435.12, 1385.70, 1390.88, 1370.55, 1371.05, 1134.74, 1227.42, 1515.15, 1335.13, 1326.54, 1236.30, + 1336.05, 1528.68, 1271.89, 1289.61, 1315.37, 1554.50, 1310.00, 1258.95, 1371.55, 1340.63, 1338.41, 1482.49, 1431.91, 1526.41, 1323.51, 1506.38, 1300.72, 1450.18, 1375.10, 1555.41, + 1385.68, 1408.90, 1439.56, 1172.49, 1303.00, 1284.11, 1561.57, 1510.37, 1392.96, 1444.72, 1355.37, 1344.74, 1334.03, 1237.49, 1698.61, 1301.14, 1501.12, 1497.12, 1406.61, 1668.88, + 1271.92, 1409.82, 1568.31, 1247.27, 1268.28, 1506.07, 1487.85, 1331.96, 1308.11, 1153.87, 1349.43, 1394.82, 1370.40, 1305.67, 1238.26, 1244.13, 1212.34, 1214.01, 1057.37, 1222.82, + 1462.63, 1146.31, 1176.44, 1233.37, 1219.87, 1417.39, 1256.23, 1141.71, 1104.27, 1342.60, 1107.36, 1166.71, 1269.03, 1296.78, 1394.75, 1203.71, 1303.12, 1292.80, 1349.62, 1268.20, + 1282.37, 1365.87, 1257.10, 1301.37, 1223.24, 1357.85, 1295.40, 1080.32, 1259.42, 1103.25, 1505.06, 1378.76, 1259.55, 1407.08, 1277.81, 1274.20, 1239.76, 1259.26, 1419.32, 1290.93, + 1461.62, 1392.77, 1208.72, 1487.44, 1233.27, 1167.01, 1408.25, 1166.39, 1115.86, 1476.19, 1408.85, 1255.06, 1318.64, 1417.57, 1440.11, 1502.85, 1377.80, 1417.09, 1331.16, 1321.85, + 1168.14, 1336.71, 1255.18, 1308.91, 1564.34, 1217.88, 1191.89, 1256.18, 1238.63, 1484.72, 1428.50, 1188.80, 1197.03, 1352.54, 1233.73, 1210.42, 1334.10, 1343.73, 1344.27, 1247.66, + 1422.34, 1501.63, 1308.65, 1456.09, 1333.68, 1538.77, 1309.99, 1554.85, 1368.45, 1371.48, 1286.55, 1192.83, 1372.63, 1244.44, 1486.45, 1447.41, 1312.79, 1416.11, 1354.57, 1335.71, + 1289.82, 1212.67, 1601.19, 1401.01, 1527.72, 1468.40, 1434.39, 1541.73, 1275.53, 1436.32, 1532.78, 1246.52, 1183.33, 1431.59, 1398.14, 1389.18 +}; + diff --git a/benchmarks/vec-matmul/dataset_test.h b/benchmarks/vec-matmul/dataset_test.h new file mode 100644 index 0000000..8934cc8 --- /dev/null +++ b/benchmarks/vec-matmul/dataset_test.h @@ -0,0 +1,39 @@ + +#define ARRAY_SIZE 4 + + +#define DIM_SIZE 2 + +#if 1 +float input1_data[ARRAY_SIZE] = +{ + 0.37, 7.51, 5.09, 1.69 +}; + +float input2_data[ARRAY_SIZE] = +{ + 4.09, 3.02, 0.02, 8.91 +}; + +float verify_data[ARRAY_SIZE] = +{ + 1.65, 68.11, 20.84, 30.44 +}; +#endif +#if 0 +float input1_data[ARRAY_SIZE] = +{ + 1.0, 0.0, 0.0, 0.0 +}; + +float input2_data[ARRAY_SIZE] = +{ + 1.0, 0.0, 0.0, 1.0 +}; + +float verify_data[ARRAY_SIZE] = +{ + 1.0, 0.0, 0.0, 0.0 +}; +#endif + diff --git a/benchmarks/vec-matmul/matmul_gendata.pl b/benchmarks/vec-matmul/matmul_gendata.pl new file mode 100755 index 0000000..c9d0ac7 --- /dev/null +++ b/benchmarks/vec-matmul/matmul_gendata.pl @@ -0,0 +1,200 @@ +#!/usr/bin/perl -w +#========================================================================== +# matmul_gendata.pl +# +# Author : Christopher Batten (cbatten@mit.edu) +# Date : April 29, 2005 +# +(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm; +# +# Simple script which creates an input data set and the reference data +# for the matmul benchmark. +# +ENDMSG + +use strict "vars"; +use warnings; +no warnings("once"); +use Getopt::Long; + +#-------------------------------------------------------------------------- +# Command line processing +#-------------------------------------------------------------------------- + +our %opts; + +sub usage() +{ + + print "\n"; + print " Usage: matmul_gendata.pl [options] \n"; + print "\n"; + print " Options:\n"; + print " --help print this message\n"; + print " --size size of input data [1000]\n"; + print " --seed random seed [1]\n"; + print "$usageMsg"; + + exit(); +} + +sub processCommandLine() +{ + + $opts{"help"} = 0; + $opts{"size"} = 1000; + $opts{"seed"} = 1; + Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage(); + $opts{"help"} and usage(); + +} + +#-------------------------------------------------------------------------- +# Helper Functions +#-------------------------------------------------------------------------- + +sub printArray +{ + my $arrayName = $_[0]; + my $arrayRef = $_[1]; + + my $numCols = 20; + my $arrayLen = scalar(@{$arrayRef}); + + print "float ".$arrayName."[ARRAY_SIZE] = \n"; + print "{\n"; + + if ( $arrayLen <= $numCols ) { + print " "; + for ( my $i = 0; $i < $arrayLen; $i++ ) { + print sprintf("%3.2f",$arrayRef->[$i]); + if ( $i != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + else { + my $numRows = int($arrayLen/$numCols); + for ( my $j = 0; $j < $numRows; $j++ ) { + print " "; + for ( my $i = 0; $i < $numCols; $i++ ) { + my $index = $j*$numCols + $i; + print sprintf("%3.2f",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + if ( $arrayLen > ($numRows*$numCols) ) { + print " "; + for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) { + my $index = $numCols*$numRows + $i; + print sprintf("%3.2f",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + } + + print "};\n\n"; +} + + + +#-------------------------------------------------------------------------- +# Matmul +#-------------------------------------------------------------------------- + +# http://answers.oreilly.com/topic/418-how-to-multiply-matrices-in-perl/ + +sub mmult { + my ($m1,$m2) = @_; + my ($m1rows,$m1cols) = matdim($m1); + my ($m2rows,$m2cols) = matdim($m2); + + my $result = [ ]; + my ($i, $j, $k); + + for $i (range($m1rows)) { + for $j (range($m2cols)) { + for $k (range($m1cols)) { + $result->[$i][$j] += $m1->[$i][$k] * $m2->[$k][$j]; + } + } + } + return $result; +} + +sub range { 0 .. ($_[0] - 1) } + + +sub veclen { + my $ary_ref = $_[0]; + my $type = ref $ary_ref; + if ($type ne "ARRAY") { die "$type is bad array ref for $ary_ref" } + return scalar(@$ary_ref); +} + +sub matdim { + my $matrix = $_[0]; + my $rows = veclen($matrix); + my $cols = veclen($matrix->[0]); + return ($rows, $cols); +} + +#-------------------------------------------------------------------------- +# Main +#-------------------------------------------------------------------------- + +sub main() +{ + + processCommandLine(); + srand($opts{"seed"}); + + # create random input arrays + my $mat_values1; + my $mat_values2; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + for ( my $j = 0; $j < $opts{"size"}; $j++ ) { + $mat_values1->[$i][$j] = (rand(9)); + $mat_values2->[$i][$j] = (rand(9)); + } + } + + # perform matmul + my $mat_results = mmult( $mat_values1, $mat_values2 ); + + # translate 2d arrays to 1d-somethings (I don't know how to code in perl - Chris) + my @values1; + my @values2; + my @results; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + for ( my $j = 0; $j < $opts{"size"}; $j++ ) { + my $value1 = $mat_values1->[$i][$j]; + my $value2 = $mat_values2->[$i][$j]; + my $result = $mat_results->[$i][$j]; + push( @values1, $value1 ); + push( @values2, $value2 ); + push( @results, $result ); + } + } + + print "\n\#define ARRAY_SIZE ".($opts{"size"}*$opts{"size"})." \n\n"; + print "\n\#define DIM_SIZE ".$opts{"size"}." \n\n"; + + printArray( "input1_data", \@values1 ); + printArray( "input2_data", \@values2 ); + printArray( "verify_data", \@results); + +} + +main(); + diff --git a/benchmarks/vec-matmul/vec_matmul_asm.S b/benchmarks/vec-matmul/vec_matmul_asm.S new file mode 100644 index 0000000..f14d186 --- /dev/null +++ b/benchmarks/vec-matmul/vec_matmul_asm.S @@ -0,0 +1,345 @@ +#***************************************************************************** +# matmul function (assembly version) +#----------------------------------------------------------------------------- + + +#-------------------------------------------------------------------------- +# Headers and Defines +#-------------------------------------------------------------------------- + +# Here are some defines that make writing assembly code easier. + +# I'm using the knowledge that rLda will be placed in register a0, rA will be +# placed into register a1, etc., based on the calling convention for functions. + +#define rN a0 +#define rLda a0 +#define rA a1 +#define rB a2 +#define rC a3 +#define rATmp2 v0 +#define rBTmp2 s0 + + +# given vector-length +#define rVlen a7 + +# address of VT function +#define rVTAddr v1 +#define rTemp0 a8 + +# desired app vector length (number of elements to vectorize) +#define rNum a9 + +#define rATemp a10 +#define rBTemp a11 +#define rCTemp a12 +#define rI a13 +#define rJ s1 +#define rK s2 +#define rLda4 a4 +#define rK4 a5 +#define rI4 a6 + +# WARNING: do not write to the s0,...,s9 registers without first saving them to +# the stack! + +#-------------------------------------------------------------------------- +# void scalar_matmul_asm( int n, float a[], float b[], float c[] ) +#-------------------------------------------------------------------------- + + .text + .align 2 + .globl scalar_matmul_asm + .type scalar_matmul_asm,@function + +scalar_matmul_asm: + + # ***** Scalar Example ***** + + blez rLda, done # exit early if lda < 0 + + move rJ, zero +loopj: + move rI, zero +loopi: + move rK, zero +loopk: + mul rTemp0, rJ, rLda # calculate indices... I'm being SUPER naive here: + add rATemp, rK, rTemp0 # this could be a lot more clever! + slli rATemp, rATemp, 2 + add rATemp, rA, rATemp + + mul rTemp0, rK, rLda + add rBTemp, rI, rTemp0 + slli rBTemp, rBTemp, 2 + add rBTemp, rB, rBTemp + + mul rTemp0, rJ, rLda + add rCTemp, rI, rTemp0 + slli rCTemp, rCTemp, 2 + add rCTemp, rC, rCTemp + + flw f2, 0(rATemp) # again, I'm being very lazy... + # I can lift this out of the inner loop! + flw f3, 0(rBTemp) + flw f4, 0(rCTemp) + fmul.s f3, f2, f3 + fadd.s f4, f4, f3 + fsw f4, 0(rCTemp) +endk: + addi rK, rK, 1 + blt rK, rLda, loopk +endi: + addi rI, rI, 1 + blt rI, rLda, loopi +endj: + addi rJ, rJ, 1 + blt rJ, rLda, loopj +done: + ret + + +#-------------------------------------------------------------------------- +# void vt_matmul_asm( int n, float a[], float b[], float c[] ) +#-------------------------------------------------------------------------- + + + # ***** Vector-Thread Example ***** + + .globl vt_matmul_asm + .type vt_matmul_asm,@function + +vt_matmul_asm: + addi sp, sp, -24 + sd s0, 0(sp) + sd s1, 8(sp) + sd s2, 16(sp) + + + # turn on vector unit + mfpcr a13,cr0 + ori a13,a13,4 + mtpcr x0,a13,cr0 + + blez rLda, cpdone # exit early if lda < 0 + + + la rVTAddr, vtcode + slli rLda4, rLda, 2 + + #for starters ask for all the registers. We shouldn't need this many + #but we'll trim it when we have correctness in hand + vvcfgivl rVlen, rNum, 1, 5 + + + move rJ, zero +vec_loopj: + move rI, zero +vec_loopi: + slli rI4, rI, 2 + + sub rNum, rN, rI # book keeping + vsetvl rVlen, rNum # set the vector length + # rN is the desired (application) vector length + # rVlen is what vector length we were given + + ##################################### + # LOADS FOR C # + ##################################### + mul rTemp0, rJ, rLda4 + add rCTemp, rI4, rTemp0 + + add rCTemp, rC, rCTemp + vflw vf2, rCTemp + + add rCTemp, rCTemp, rLda4 + vflw vf4, rCTemp + + + ################################# + # address calculation lifts # + ################################# + mul rTemp0, rJ, rLda4 + add rATmp2, rA, rTemp0 + + add rBTmp2, rI4, rB + move rK, zero +vec_loopk: + slli rK4, rK, 2 + + ##################################### + # LOADS FOR A # + ##################################### + + add rATemp, rK4, rATmp2 + vflstw vf0, rATemp, zero + + add rATemp, rATemp, rLda4 + vflstw vf3, rATemp, zero + + + ##################################### + # LOADS FOR B # + ##################################### + mul rTemp0, rK, rLda4 + add rBTemp, rBTmp2, rTemp0 + vflw vf1, rBTemp + vf 0(rVTAddr) + + ##################################### + # LOADS FOR A # + ##################################### + add rATemp, rK4, rATmp2 + addi rATemp, rATemp, 4 + vflstw vf0, rATemp, zero + + add rATemp, rATemp, rLda4 + vflstw vf3, rATemp, zero + + + ##################################### + # LOADS FOR B # + ##################################### + add rBTemp, rBTemp, rLda4 + vflw vf1, rBTemp + vf 0(rVTAddr) + + ##################################### + # LOADS FOR A # + ##################################### + add rATemp, rK4, rATmp2 + addi rATemp, rATemp, 8 + vflstw vf0, rATemp, zero + + add rATemp, rATemp, rLda4 + vflstw vf3, rATemp, zero + + + ##################################### + # LOADS FOR B # + ##################################### + add rBTemp, rBTemp, rLda4 + vflw vf1, rBTemp + vf 0(rVTAddr) + + + ##################################### + # LOADS FOR A # + ##################################### + add rATemp, rK4, rATmp2 + addi rATemp, rATemp, 12 + vflstw vf0, rATemp, zero + + add rATemp, rATemp, rLda4 + vflstw vf3, rATemp, zero + + + ##################################### + # LOADS FOR B # + ##################################### + add rBTemp, rBTemp, rLda4 + vflw vf1, rBTemp + vf 0(rVTAddr) + +vec_endk: + addi rK, rK, 4 + blt rK, rLda, vec_loopk + +vec_endi: + ##################################### + # STORES FOR C # + ##################################### + vfsw vf4, rCTemp + sub rCTemp, rCTemp, rLda4 + vfsw vf2, rCTemp + + add rI, rI, rVlen + blt rI, rLda, vec_loopi +vec_endj: + addi rJ, rJ, 2 +# fence.v.l + blt rJ, rLda, vec_loopj + + +cpdone: + fence.v.l + ld s0, 0(sp) + ld s1, 8(sp) + ld s2, 16(sp) + addi sp, sp, 24 + + + ret + +vtcode: + # ADD YOUR VECTOR-ELEMENT CODE HERE ... + + #TODO: hit this with a fused multiply add. + + fmadd.s f2, f0, f1, f2 + fmadd.s f4, f3, f1, f4 + #fmadd.s f6, f5, f1, f6 + #fmadd.s f8, f7, f1, f8 + + + #fmul.s f1, f0, f1 + #fadd.s f2, f2, f1 + stop + +transpose: + # turn on vector unit + mfpcr a13,cr0 + ori a13,a13,4 + mtpcr x0,a13,cr0 + + + blez rLda, cpdone # exit early if lda < 0 + vvcfgivl rVlen, rNum, 1, 1 + + move rI, zero +tloopi: + sub rNum, rLda, rI + vsetvl rVlen, rNum + + move rJ, zero +tloopj: + + mul rTemp0, rJ, rLda + add rATemp, rI, rTemp0 + slli rATemp, rATemp, 2 + add rATemp, rA, rATemp + + mul rTemp0, rI, rLda + add rBTemp, rJ, rTemp0 + slli rBTemp, rBTemp, 2 + add rBTemp, rB, rBTemp + + #flw f0, 0(rBTemp) + #fsw f0, 0(rATemp) + vflstw vf0, rBTemp, rLda4 + vfsw vf0, rATemp + +tendj: + addi rJ, rJ, 1 + blt rJ, rLda, tloopj +tendi: + #addi rI, rI, 1 + add rI, rI, rVlen + blt rI, rLda, tloopi + + ret + # The C code uses a jalr instruction to call this function + # so we can use a jr to return back to where the function + # was called. Also known as "ret", for "return". + + ret + + + +##################################### +# NOPS TO AVOID OVERPREFETCH # +##################################### +# srli rTemp0, rLda, 4 +#nop_lp: addi rTemp0, rTemp0, -1 +# bgez rTemp0, nop_lp diff --git a/benchmarks/vec-matmul/vec_matmul_main.c b/benchmarks/vec-matmul/vec_matmul_main.c new file mode 100644 index 0000000..5de377e --- /dev/null +++ b/benchmarks/vec-matmul/vec_matmul_main.c @@ -0,0 +1,260 @@ +//************************************************************************** +// Vector-Thread Vector Matrix Multiply benchmark +//-------------------------------------------------------------------------- +// +// This benchmark multiplies two 2-D arrays together and writes the results to +// a third vector. The input data (and reference data) should be generated +// using the matmul_gendata.pl perl script and dumped to a file named +// dataset.h. The riscv-gcc toolchain does not support system calls so printf's +// can only be used on a host system, not on the riscv-v processor simulator +// itself. +// +// HOWEVER: printstr() and printhex() are provided, for a primitive form of +// printing strings and hexadecimal values to stdout. + + +// Choose which implementation you wish to test... but leave only one on! +// (only the first one will be executed). +//#define SCALAR_C +//#define SCALAR_ASM +#define VT_ASM + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +//-------------------------------------------------------------------------- +// Host Platform Includes + +#if HOST_DEBUG + #include + #include +#else +void printstr(const char*); +void exit(); +#endif + + +//-------------------------------------------------------------------------- +// Input/Reference Data + +//#include "dataset_test.h" +#include "dataset.h" + +//-------------------------------------------------------------------------- +// Helper functions + +int verify( int n, float test[], float correct[] ) +{ + int i; + for ( i = 0; i < n; i++ ) { + if ( test[i] > 1.02*correct[i] + || test[i] < 0.98*correct[i]) { +#if HOST_DEBUG + printf(" test[%d] : %3.2f\n", i, test[i]); + printf(" corr[%d] : %3.2f\n", i, correct[i]); +#endif + // tell us which index fails + 2 + // (so that if i==0,i==1 fails, we don't + // think it was a 'not-finished yet' or pass) + return i+10; + } + } + return 1; +} + +#if HOST_DEBUG +void printArray( char name[], int n, float arr[] ) +{ + int i; + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " %03.2f ", arr[i] ); + printf( "\n" ); +} +#endif + + +void finishTest( int correct, long long num_cycles, long long num_retired ) +{ + int toHostValue = correct; +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + // we no longer run in -testrun mode, which means we can't use + // the tohost register to communicate "test is done" and "test results" + // so instead we will communicate through print* functions! + if ( correct == 1 ) + { + printstr( "*** PASSED *** (num_cycles = 0x" ); + printhex(num_cycles); + printstr( ", num_inst_retired = 0x"); + printhex(num_retired); + printstr( ")\n" ); + } + else + { + printstr( "*** FAILED *** (num_cycles = 0x"); + printhex(num_cycles); + printstr( ", num_inst_retired = 0x"); + printhex(num_retired); + printstr( ")\n" ); + } + exit(); +#endif +} + + +// deprecated - cr10/stats-enable register no longer exists +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +long long getCycles() +{ + long long cycles = 1337; +#if ( !HOST_DEBUG && SET_STATS ) + __asm__ __volatile__( "rdcycle %0" : "=r" (cycles) ); +#endif + return cycles; +} + +long long getInstRetired() +{ + long long inst_retired = 1338; +#if ( !HOST_DEBUG && SET_STATS ) + __asm__ __volatile__( "rdinstret %0" : "=r" (inst_retired) ); +#endif + return inst_retired; +} + +//-------------------------------------------------------------------------- +// matmul function + +// scalar C implementation +void matmul(const int lda, const float A[], const float B[], float C[] ) +{ + int i, j, k; + + for ( j = 0; j < lda; j++ ) + for ( i = 0; i < lda; i++ ) + { + float cij = C[i + j*lda]; + for ( k = 0; k < lda; k++ ) + { + cij += A[j*lda + k] * B[k*lda + i]; + } + C[i + j*lda] = cij; + } +} + + +// assembly implementations can be found in *_asm.S + +//-------------------------------------------------------------------------- +// Main + +int main( int argc, char* argv[] ) +{ + int i,j; + long long start_cycles = 0; + long long stop_cycles = 0; + long long num_cycles; + long long start_retired = 0; + long long stop_retired = 0; + long long num_retired; + + float results_data[ARRAY_SIZE]; + for ( i = 0; i < DIM_SIZE; i++ ) + for ( j = 0; j < DIM_SIZE; j++ ) + results_data[i + j*DIM_SIZE] = 0.0f; + + // Output the input array + +#if HOST_DEBUG + printArray( "input1", ARRAY_SIZE, input1_data ); + printArray( "input2", ARRAY_SIZE, input2_data ); + printArray( "verify", ARRAY_SIZE, verify_data ); + printArray( "results", ARRAY_SIZE, results_data ); +#endif + + // -------------------------------------------------- + // If needed we preallocate everything in the caches + +#if PREALLOCATE + + + +#endif + + // -------------------------------------------------- + // Do the matmul + start_cycles = getCycles(); + start_retired = getInstRetired(); + +#ifdef SCALAR_C + matmul( DIM_SIZE, input1_data, input2_data, results_data ); +#else +#ifdef SCALAR_ASM + #if HOST_DEBUG==0 + scalar_matmul_asm( DIM_SIZE, input1_data, input2_data, results_data ); + #endif +#else +#ifdef VT_ASM + #if HOST_DEBUG==0 + vt_matmul_asm( DIM_SIZE, input1_data, input2_data, results_data ); + #endif +#endif +#endif +#endif + + + stop_cycles = getCycles(); + stop_retired = getInstRetired(); + num_cycles = stop_cycles - start_cycles; + num_retired = stop_retired - start_retired; + + + // -------------------------------------------------- + // Print out the results + +#if HOST_DEBUG + printArray( "results", ARRAY_SIZE, results_data ); +#endif + + + // -------------------------------------------------- + // Check the results + int correct = verify( ARRAY_SIZE, results_data, verify_data ); + finishTest(correct, num_cycles, num_retired); +} diff --git a/benchmarks/vec-vvadd/bmark.mk b/benchmarks/vec-vvadd/bmark.mk new file mode 100644 index 0000000..78ebff2 --- /dev/null +++ b/benchmarks/vec-vvadd/bmark.mk @@ -0,0 +1,30 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +vec_vvadd_c_src = \ + vec_vvadd_main.c \ + +vec_vvadd_riscv_src = \ + crt.S \ + vec_vvadd_asm.S + +vec_vvadd_c_objs = $(patsubst %.c, %.o, $(vec_vvadd_c_src)) +vec_vvadd_riscv_objs = $(patsubst %.S, %.o, $(vec_vvadd_riscv_src)) + +vec_vvadd_host_bin = vec-vvadd.host +$(vec_vvadd_host_bin) : $(vec_vvadd_c_src) + $(HOST_COMP) $^ -o $(vec_vvadd_host_bin) + +vec_vvadd_riscv_bin = vec-vvadd.riscv +$(vec_vvadd_riscv_bin) : $(vec_vvadd_c_objs) $(vec_vvadd_riscv_objs) + $(RISCV_LINK) $(RISCV_LINK_SYSCALL) $(vec_vvadd_c_objs) $(vec_vvadd_riscv_objs) -o $(vec_vvadd_riscv_bin) + +junk += $(vec_vvadd_c_objs) $(vec_vvadd_riscv_objs) \ + $(vec_vvadd_host_bin) $(vec_vvadd_riscv_bin) diff --git a/benchmarks/vec-vvadd/dataset.h b/benchmarks/vec-vvadd/dataset.h new file mode 100644 index 0000000..83fc6b7 --- /dev/null +++ b/benchmarks/vec-vvadd/dataset.h @@ -0,0 +1,171 @@ + +#define DATA_SIZE 1024 + +float input1_data[DATA_SIZE] = +{ + 41.59, 833.98, 564.92, 187.40, 749.75, 350.86, 132.42, 949.90, 584.06, 805.70, 621.44, 6.57, 931.73, 890.19, 392.50, 694.30, 961.50, 110.85, 116.64, 296.64, + 426.15, 314.26, 659.38, 774.03, 319.50, 678.95, 875.15, 376.99, 474.52, 938.39, 539.64, 569.21, 203.10, 280.59, 759.17, 606.49, 511.73, 657.85, 195.14, 81.76, + 267.13, 229.11, 337.80, 944.31, 902.33, 241.76, 913.03, 826.41, 933.10, 985.95, 195.94, 960.23, 566.85, 350.87, 649.08, 657.11, 181.07, 111.93, 859.03, 65.38, + 288.41, 349.32, 141.62, 905.27, 886.09, 264.13, 576.69, 979.62, 761.15, 241.01, 478.77, 499.56, 403.08, 222.09, 444.00, 721.13, 676.11, 317.98, 224.02, 937.91, + 288.16, 119.49, 615.12, 606.02, 389.63, 351.17, 455.08, 278.19, 367.94, 358.65, 584.29, 62.81, 985.38, 403.31, 346.66, 517.64, 559.24, 908.23, 775.53, 255.22, + 778.76, 598.70, 143.67, 33.87, 125.22, 941.32, 933.58, 799.68, 553.00, 431.48, 648.92, 952.26, 287.81, 19.55, 49.85, 86.34, 95.37, 441.32, 587.26, 614.94, + 382.15, 280.93, 808.48, 971.60, 819.34, 344.75, 450.92, 512.61, 965.23, 347.78, 808.67, 882.45, 537.55, 946.57, 701.25, 356.05, 567.96, 891.59, 22.08, 568.05, + 665.92, 423.06, 434.34, 158.95, 2.47, 84.01, 247.70, 49.41, 435.28, 792.95, 869.12, 486.44, 414.24, 369.14, 548.71, 518.09, 888.38, 682.27, 284.83, 264.53, + 499.48, 290.72, 897.15, 215.27, 731.10, 688.62, 251.21, 786.26, 555.77, 302.26, 528.37, 544.63, 322.31, 947.49, 287.49, 824.15, 304.91, 788.79, 733.63, 959.89, + 366.53, 722.70, 294.29, 975.54, 653.47, 748.94, 91.37, 378.81, 105.56, 102.96, 381.89, 651.77, 825.56, 840.65, 356.91, 148.28, 54.55, 140.19, 955.46, 343.09, + 533.74, 757.52, 521.69, 837.60, 592.30, 13.14, 173.27, 63.12, 121.08, 133.74, 758.23, 372.02, 951.71, 39.51, 129.91, 110.98, 847.87, 437.05, 255.51, 269.43, + 409.58, 628.32, 399.16, 549.49, 753.43, 564.11, 171.44, 19.41, 727.43, 501.57, 777.90, 43.09, 753.99, 81.39, 202.47, 853.24, 153.74, 760.34, 357.21, 943.33, + 922.66, 328.36, 496.72, 442.71, 516.93, 641.63, 276.71, 786.16, 113.96, 842.51, 907.08, 275.40, 237.13, 32.98, 784.54, 565.19, 357.36, 803.66, 819.14, 751.19, + 280.22, 85.45, 458.79, 454.92, 710.83, 459.50, 41.90, 253.04, 377.89, 508.40, 700.13, 860.38, 480.43, 741.22, 499.72, 709.19, 49.82, 371.43, 873.84, 945.74, + 992.29, 526.88, 721.83, 435.40, 232.94, 497.20, 697.84, 30.97, 348.62, 250.71, 350.43, 250.94, 573.58, 784.02, 749.08, 502.35, 823.63, 826.56, 170.19, 160.43, + 674.95, 32.57, 202.49, 143.61, 853.30, 90.19, 394.67, 107.54, 855.13, 106.95, 157.48, 6.02, 765.70, 204.09, 194.97, 574.49, 218.68, 526.07, 177.51, 239.54, + 698.98, 757.04, 706.64, 49.59, 84.46, 799.94, 893.26, 512.93, 373.43, 492.61, 14.70, 621.34, 83.22, 103.52, 794.61, 921.52, 643.16, 880.32, 834.18, 239.95, + 462.18, 114.13, 561.17, 529.93, 10.30, 997.07, 904.66, 387.08, 407.57, 105.47, 559.17, 936.96, 512.84, 409.16, 302.62, 202.29, 427.86, 613.96, 359.16, 521.47, + 684.36, 22.07, 185.67, 312.54, 107.15, 274.79, 387.52, 242.91, 486.42, 105.59, 698.95, 899.65, 770.03, 644.88, 80.86, 161.95, 407.27, 946.13, 30.14, 768.55, + 870.70, 113.84, 148.93, 62.24, 147.22, 838.37, 845.09, 432.80, 141.35, 211.37, 817.36, 821.24, 562.79, 364.45, 615.83, 495.66, 812.02, 916.81, 159.62, 430.76, + 803.39, 180.32, 544.52, 840.69, 458.36, 786.87, 872.83, 795.63, 806.35, 758.10, 104.71, 401.72, 254.16, 984.58, 136.35, 729.51, 584.46, 794.56, 414.82, 528.59, + 707.41, 554.08, 378.44, 766.91, 977.14, 236.84, 947.69, 229.98, 165.43, 505.78, 105.10, 704.89, 796.28, 140.34, 303.80, 795.40, 635.19, 560.05, 119.19, 8.94, + 532.12, 814.18, 37.37, 584.99, 739.88, 619.35, 767.29, 478.11, 57.63, 958.75, 784.42, 985.67, 837.44, 307.64, 67.92, 824.29, 996.62, 749.22, 171.61, 826.01, + 621.55, 155.29, 826.10, 43.35, 694.11, 80.98, 236.29, 747.66, 744.26, 265.92, 124.29, 731.39, 941.95, 425.61, 370.26, 320.28, 269.25, 542.98, 763.36, 752.33, + 915.79, 14.49, 1.02, 906.26, 995.56, 809.80, 560.98, 873.76, 972.51, 289.40, 509.58, 558.76, 970.08, 405.61, 579.55, 293.55, 251.18, 849.74, 129.09, 452.87, + 716.20, 86.61, 678.77, 181.77, 240.86, 335.99, 793.87, 641.72, 1.47, 320.21, 987.27, 646.93, 754.87, 958.84, 203.62, 142.11, 180.16, 299.98, 165.92, 761.46, + 974.39, 646.84, 559.81, 619.82, 422.99, 260.82, 565.90, 542.16, 492.49, 991.70, 745.63, 207.65, 372.46, 932.61, 664.40, 34.84, 533.95, 478.47, 908.95, 203.05, + 33.64, 214.19, 365.78, 892.41, 781.43, 680.21, 705.21, 688.64, 947.17, 386.39, 50.40, 101.30, 474.97, 399.09, 679.01, 330.13, 952.98, 471.66, 477.47, 725.77, + 713.76, 937.76, 529.17, 870.41, 77.99, 545.34, 907.70, 853.57, 143.68, 979.57, 239.21, 105.80, 365.64, 98.64, 54.56, 98.04, 440.05, 764.95, 315.62, 336.77, + 697.12, 774.98, 726.37, 324.62, 282.73, 536.06, 622.47, 594.54, 890.74, 75.13, 290.61, 496.26, 726.27, 449.55, 548.04, 135.51, 644.61, 838.43, 290.24, 767.27, + 162.90, 415.87, 491.71, 985.23, 116.70, 617.91, 859.64, 235.61, 282.59, 571.64, 913.20, 560.56, 194.94, 242.05, 782.79, 985.66, 728.32, 344.06, 430.86, 613.14, + 759.90, 176.81, 309.64, 333.97, 354.41, 310.11, 699.67, 46.29, 487.22, 503.74, 100.74, 393.42, 268.61, 314.32, 75.11, 345.99, 987.79, 600.60, 908.74, 384.95, + 92.09, 545.17, 277.13, 668.55, 351.48, 853.73, 863.11, 312.76, 100.68, 532.50, 567.78, 836.25, 370.79, 989.97, 461.42, 912.55, 182.04, 268.37, 160.27, 771.80, + 22.69, 854.15, 644.93, 17.22, 779.43, 911.42, 855.52, 137.54, 983.70, 717.12, 565.26, 719.22, 253.48, 785.55, 154.54, 196.92, 253.81, 447.04, 899.47, 5.34, + 325.97, 616.42, 309.07, 175.28, 159.88, 123.45, 838.83, 715.65, 550.54, 230.32, 82.39, 627.26, 324.56, 927.11, 103.12, 17.97, 966.92, 159.09, 177.28, 593.36, + 372.91, 393.86, 599.09, 745.91, 377.05, 865.47, 591.44, 553.27, 440.27, 345.91, 593.69, 290.57, 908.14, 544.77, 377.87, 456.22, 781.05, 110.18, 495.91, 896.30, + 806.64, 700.92, 548.12, 340.34, 29.42, 829.88, 630.52, 546.09, 613.55, 972.27, 116.31, 313.81, 904.18, 971.17, 607.11, 794.60, 169.61, 896.60, 507.27, 916.31, + 431.26, 339.73, 147.92, 224.85, 112.36, 580.34, 834.44, 134.00, 948.54, 201.62, 488.69, 396.03, 797.99, 478.84, 769.12, 574.12, 485.10, 339.64, 721.39, 451.01, + 821.46, 744.32, 0.32, 594.88, 277.92, 120.10, 680.48, 757.52, 555.46, 847.72, 517.32, 379.19, 505.76, 904.86, 246.20, 243.02, 394.14, 430.59, 214.70, 244.51, + 524.70, 399.78, 172.96, 304.80, 620.47, 594.89, 535.34, 698.85, 159.58, 750.18, 809.80, 454.71, 76.00, 93.16, 167.76, 16.56, 853.29, 494.86, 324.64, 78.75, + 52.12, 112.44, 10.83, 342.60, 730.66, 680.71, 287.57, 961.30, 92.22, 626.09, 912.54, 616.39, 860.45, 744.11, 744.54, 478.60, 615.31, 508.17, 914.51, 810.39, + 288.65, 974.52, 129.30, 581.07, 548.96, 868.10, 981.49, 270.03, 623.03, 653.03, 626.15, 990.32, 386.70, 323.86, 472.86, 164.65, 239.77, 189.69, 865.12, 231.99, + 356.20, 152.84, 825.88, 328.59, 390.54, 848.08, 38.56, 402.90, 616.86, 546.07, 206.41, 2.50, 783.35, 890.15, 815.17, 831.95, 665.61, 410.53, 94.20, 246.60, + 422.12, 211.55, 675.13, 9.90, 374.19, 426.82, 64.89, 53.51, 758.63, 811.88, 500.64, 437.97, 335.95, 328.20, 237.48, 415.70, 468.47, 684.52, 565.24, 305.75, + 449.18, 597.90, 136.86, 882.80, 383.10, 938.05, 268.60, 115.02, 908.44, 50.25, 952.61, 366.36, 397.07, 257.43, 231.61, 667.39, 35.32, 990.98, 443.25, 213.68, + 389.05, 13.39, 621.15, 52.84, 612.70, 934.69, 953.51, 828.93, 462.31, 621.74, 812.65, 522.67, 672.37, 57.38, 313.44, 352.52, 55.66, 972.52, 753.45, 416.32, + 879.66, 864.63, 572.40, 163.63, 721.06, 12.23, 643.51, 507.11, 968.33, 781.67, 840.17, 242.23, 630.38, 810.57, 795.03, 435.93, 885.97, 599.49, 696.83, 643.98, + 93.08, 710.36, 785.04, 112.34, 581.66, 12.82, 923.01, 615.98, 652.77, 359.69, 261.90, 233.64, 609.49, 686.46, 539.88, 118.11, 560.80, 739.29, 20.45, 317.91, + 976.37, 573.39, 386.70, 772.54, 663.59, 504.89, 212.06, 888.98, 907.19, 420.67, 737.06, 516.55, 25.06, 219.92, 798.00, 716.93, 452.20, 692.03, 683.97, 459.81, + 815.55, 323.78, 612.76, 247.55, 116.16, 352.60, 281.43, 738.83, 290.13, 909.66, 645.24, 625.86, 932.73, 220.19, 685.31, 373.01, 876.04, 646.60, 412.10, 955.61, + 664.07, 850.22, 783.40, 392.65, 707.73, 422.19, 523.39, 682.29, 37.63, 156.05, 43.20, 767.99, 124.71, 549.18, 814.54, 251.25, 214.66, 212.34, 572.71, 898.81, + 956.34, 608.88, 651.21, 434.82 +}; + +float input2_data[DATA_SIZE] = +{ + 454.04, 335.65, 1.77, 989.44, 365.91, 572.77, 64.10, 153.41, 216.37, 140.33, 210.68, 572.73, 339.99, 593.28, 898.42, 228.37, 12.04, 883.21, 750.17, 646.05, + 500.44, 436.35, 701.84, 812.45, 981.34, 150.82, 696.06, 564.27, 272.22, 258.80, 647.13, 509.06, 88.49, 703.96, 669.95, 375.24, 551.64, 936.95, 592.64, 569.16, + 952.14, 800.96, 584.36, 643.10, 368.06, 489.01, 328.85, 313.03, 592.75, 388.47, 543.97, 649.72, 979.53, 997.36, 814.30, 79.21, 208.54, 998.28, 629.87, 847.38, + 704.44, 997.07, 253.56, 715.50, 430.09, 415.56, 538.54, 700.34, 4.53, 494.85, 100.03, 864.77, 693.83, 416.61, 296.87, 285.92, 620.97, 78.51, 351.59, 540.87, + 646.76, 169.92, 527.62, 289.32, 796.30, 801.60, 720.50, 758.92, 745.48, 92.20, 989.02, 271.26, 853.35, 788.60, 531.96, 222.70, 461.08, 241.60, 358.39, 332.17, + 684.58, 740.02, 446.29, 311.97, 743.59, 557.40, 479.07, 557.42, 925.39, 796.31, 357.74, 891.05, 666.07, 514.82, 557.92, 870.02, 853.32, 440.22, 61.13, 678.78, + 396.53, 9.60, 17.28, 170.59, 291.21, 380.26, 536.10, 185.83, 917.13, 539.78, 983.16, 887.64, 54.78, 612.25, 951.51, 479.91, 151.50, 7.63, 641.97, 335.43, + 730.12, 95.14, 728.36, 280.47, 395.18, 688.69, 911.04, 476.88, 815.06, 729.61, 265.14, 127.81, 236.25, 214.41, 180.89, 6.46, 503.57, 596.12, 173.66, 643.66, + 346.93, 599.78, 68.90, 849.86, 658.43, 619.45, 121.67, 131.85, 828.62, 667.11, 433.76, 487.96, 753.88, 125.79, 626.75, 14.42, 10.59, 403.62, 106.00, 703.45, + 818.16, 964.09, 406.41, 874.40, 856.38, 86.58, 60.48, 660.95, 667.96, 153.07, 121.32, 98.11, 412.62, 236.34, 12.41, 423.64, 965.21, 216.22, 621.17, 361.66, + 921.78, 715.22, 647.63, 299.72, 886.82, 682.62, 36.45, 493.97, 551.05, 537.23, 969.91, 643.13, 434.31, 415.39, 303.19, 438.67, 860.46, 203.12, 478.66, 988.42, + 675.20, 719.24, 990.64, 338.47, 450.81, 633.17, 155.33, 646.75, 452.99, 427.23, 509.17, 988.99, 426.10, 12.74, 483.26, 142.23, 339.79, 390.81, 50.95, 171.16, + 601.54, 105.47, 968.89, 121.26, 879.98, 81.89, 870.32, 600.55, 603.29, 871.73, 887.50, 610.56, 404.65, 234.16, 745.69, 526.44, 275.51, 441.57, 226.96, 752.86, + 943.47, 726.29, 709.63, 201.25, 54.32, 758.41, 53.13, 397.79, 41.32, 141.48, 416.24, 747.81, 219.98, 478.11, 770.83, 180.06, 482.88, 691.56, 725.10, 173.62, + 186.07, 914.28, 1.64, 963.17, 248.00, 464.70, 362.43, 521.93, 233.68, 120.84, 40.89, 779.34, 195.43, 161.24, 743.15, 439.32, 355.84, 403.26, 141.52, 633.14, + 289.43, 782.40, 320.03, 636.26, 118.73, 852.98, 70.84, 816.16, 388.16, 954.73, 36.04, 16.68, 698.34, 695.97, 677.21, 598.79, 883.95, 824.68, 746.81, 462.54, + 511.64, 534.37, 440.30, 428.71, 732.86, 726.51, 702.51, 547.02, 86.52, 798.67, 215.32, 21.88, 651.12, 59.56, 429.73, 657.72, 96.84, 973.02, 659.46, 966.03, + 524.36, 62.55, 625.28, 303.09, 714.64, 409.32, 55.49, 728.91, 305.61, 436.34, 901.67, 592.86, 691.16, 796.54, 497.10, 177.90, 940.76, 995.51, 480.97, 158.27, + 822.18, 611.21, 680.54, 14.69, 111.64, 797.48, 185.26, 0.42, 718.99, 96.96, 749.66, 739.06, 814.08, 435.19, 326.74, 37.87, 33.93, 605.81, 935.30, 27.08, + 88.64, 441.48, 339.35, 344.49, 554.29, 365.36, 954.73, 639.24, 396.74, 991.69, 249.37, 338.14, 832.96, 974.16, 393.61, 266.20, 470.51, 348.21, 336.49, 419.51, + 249.26, 215.93, 542.52, 903.45, 636.50, 729.85, 581.11, 820.51, 671.78, 979.39, 418.16, 670.72, 920.09, 568.34, 745.07, 662.81, 139.00, 385.86, 927.79, 173.18, + 457.31, 316.41, 183.92, 477.45, 196.33, 399.89, 416.39, 805.73, 996.26, 270.14, 735.50, 696.71, 825.63, 528.63, 50.72, 623.80, 537.51, 87.46, 294.50, 867.57, + 110.26, 398.60, 781.21, 646.64, 375.13, 943.34, 897.04, 589.48, 44.54, 288.17, 845.33, 742.83, 99.00, 522.57, 443.74, 432.33, 165.91, 930.88, 28.94, 461.66, + 323.98, 272.51, 376.62, 340.73, 898.14, 158.37, 168.75, 443.51, 193.73, 631.20, 935.89, 274.02, 781.65, 185.57, 619.86, 292.35, 933.33, 156.41, 827.37, 88.76, + 987.54, 629.48, 649.02, 32.15, 1.18, 744.89, 399.21, 915.37, 791.96, 554.59, 984.10, 530.66, 600.58, 401.77, 683.13, 540.36, 903.94, 120.85, 995.87, 521.86, + 622.16, 224.65, 895.32, 530.33, 820.81, 651.71, 226.16, 96.13, 262.91, 569.20, 238.65, 126.49, 610.86, 191.60, 238.92, 796.97, 884.59, 573.09, 108.00, 140.59, + 789.76, 852.96, 23.71, 704.58, 890.76, 480.51, 52.78, 372.43, 201.01, 546.61, 408.85, 119.89, 645.63, 464.84, 81.80, 293.26, 52.40, 880.11, 224.02, 744.84, + 735.53, 886.00, 167.35, 1.88, 532.19, 321.39, 169.10, 485.71, 101.72, 177.67, 42.92, 708.17, 654.57, 915.79, 625.69, 242.14, 822.84, 795.34, 641.04, 252.42, + 245.63, 151.34, 876.43, 333.05, 601.06, 938.92, 775.05, 397.50, 233.79, 755.78, 454.06, 424.44, 210.01, 962.37, 900.93, 923.02, 655.46, 529.87, 595.01, 90.89, + 464.89, 685.58, 70.44, 754.90, 32.51, 494.81, 25.80, 389.38, 488.21, 37.40, 409.08, 639.86, 27.63, 950.87, 539.51, 80.51, 303.34, 723.69, 734.88, 125.98, + 552.69, 248.59, 107.29, 362.31, 48.68, 869.57, 144.74, 841.18, 724.89, 335.10, 470.53, 263.38, 343.02, 809.49, 677.01, 339.36, 336.03, 410.43, 465.15, 56.81, + 590.66, 485.63, 406.57, 993.51, 746.33, 238.91, 525.16, 336.30, 256.11, 134.76, 546.41, 722.96, 367.62, 943.94, 106.51, 629.33, 396.50, 208.74, 429.60, 523.82, + 130.87, 355.83, 990.83, 673.36, 991.28, 719.97, 449.14, 84.94, 616.26, 211.40, 707.51, 737.36, 847.35, 452.81, 316.11, 974.19, 746.34, 796.57, 522.31, 618.19, + 115.11, 727.59, 226.00, 165.86, 200.08, 830.23, 742.47, 187.65, 705.02, 671.77, 785.22, 886.33, 962.57, 657.86, 293.97, 620.08, 144.34, 173.29, 796.21, 72.50, + 678.01, 80.06, 793.33, 685.03, 637.56, 967.37, 241.53, 898.52, 693.00, 372.64, 601.23, 721.30, 398.50, 553.18, 72.92, 174.85, 978.42, 325.01, 558.77, 185.25, + 505.93, 860.00, 651.31, 573.60, 321.32, 349.19, 400.24, 890.35, 844.52, 885.04, 933.02, 980.84, 448.61, 989.45, 50.53, 332.36, 900.28, 716.93, 747.86, 444.23, + 6.62, 394.55, 285.73, 703.44, 450.70, 652.55, 771.82, 485.17, 534.56, 559.01, 481.51, 507.24, 434.52, 343.63, 42.42, 784.26, 865.65, 421.89, 415.22, 871.79, + 539.58, 162.47, 105.09, 481.92, 595.44, 115.11, 350.01, 964.58, 287.38, 232.55, 154.11, 602.37, 539.48, 943.16, 872.17, 121.26, 652.20, 811.95, 747.88, 362.25, + 340.41, 910.73, 206.71, 572.95, 505.78, 973.87, 961.61, 354.74, 627.25, 849.72, 971.69, 910.80, 410.29, 770.61, 63.75, 874.84, 396.21, 482.65, 619.93, 646.52, + 557.70, 328.81, 67.74, 884.16, 512.52, 972.25, 6.13, 513.12, 882.90, 562.88, 764.78, 366.50, 506.01, 786.96, 831.46, 382.69, 638.33, 452.86, 72.80, 83.99, + 59.48, 932.56, 929.17, 924.31, 961.79, 69.09, 797.94, 985.49, 854.03, 885.08, 600.77, 389.36, 232.77, 793.58, 179.91, 773.67, 689.88, 775.80, 494.89, 139.65, + 234.41, 431.79, 780.34, 371.94, 22.47, 653.95, 741.81, 815.30, 429.00, 139.33, 603.92, 315.04, 344.80, 889.48, 317.27, 260.28, 861.63, 377.78, 511.76, 304.06, + 70.19, 35.87, 854.09, 576.98, 490.35, 326.55, 303.50, 431.21, 813.10, 708.96, 388.67, 962.18, 967.95, 442.52, 49.02, 831.49, 251.65, 321.36, 741.45, 179.51, + 176.27, 117.00, 523.73, 764.26, 952.82, 704.67, 531.80, 804.94, 23.61, 611.10, 846.79, 375.26, 854.69, 971.77, 24.05, 639.17, 318.66, 723.53, 662.84, 647.47, + 281.11, 158.85, 294.58, 885.85, 734.06, 866.60, 471.06, 296.09, 673.55, 472.93, 439.09, 5.93, 155.39, 506.79, 948.50, 600.40, 445.21, 222.05, 784.59, 349.77, + 943.37, 150.14, 366.16, 444.22, 604.60, 720.40, 340.70, 972.58, 911.45, 321.49, 435.22, 50.43, 78.96, 761.04, 950.33, 238.41, 27.06, 226.17, 201.43, 176.53, + 877.51, 450.94, 879.63, 99.89, 143.28, 31.66, 812.36, 771.31, 527.29, 488.63, 797.10, 194.25, 293.72, 966.52, 276.35, 345.26, 413.02, 197.52, 386.04, 116.36, + 322.72, 680.35, 538.15, 554.00, 960.31, 874.79, 48.72, 506.93, 898.24, 539.71, 495.50, 764.01, 805.12, 286.44, 432.09, 836.98, 192.15, 825.36, 778.42, 586.55, + 359.37, 352.70, 746.78, 11.34, 749.69, 5.98, 408.76, 643.32, 441.94, 368.15, 97.74, 169.62, 359.25, 527.49, 672.31, 69.39, 880.66, 298.11, 300.84, 327.09, + 923.83, 829.55, 816.51, 497.50, 243.91, 981.12, 917.21, 713.38, 653.91, 503.75, 406.65, 543.57, 108.87, 304.66, 464.10, 954.74, 86.37, 802.71, 446.02, 28.16, + 539.76, 655.37, 28.71, 470.59, 735.85, 941.08, 610.37, 451.33, 672.34, 237.47, 766.04, 713.35, 409.69, 869.06, 186.75, 475.83, 568.73, 44.08, 997.88, 139.85, + 456.29, 470.05, 566.52, 408.79 +}; + +float verify_data[DATA_SIZE] = +{ + 495.63, 1169.63, 566.69, 1176.85, 1115.65, 923.63, 196.52, 1103.31, 800.44, 946.03, 832.12, 579.30, 1271.72, 1483.47, 1290.93, 922.67, 973.54, 994.06, 866.81, 942.68, + 926.59, 750.61, 1361.22, 1586.49, 1300.84, 829.78, 1571.21, 941.26, 746.74, 1197.19, 1186.78, 1078.26, 291.58, 984.55, 1429.12, 981.74, 1063.38, 1594.80, 787.78, 650.92, + 1219.28, 1030.07, 922.15, 1587.41, 1270.39, 730.77, 1241.89, 1139.44, 1525.85, 1374.42, 739.91, 1609.95, 1546.39, 1348.24, 1463.38, 736.32, 389.61, 1110.21, 1488.91, 912.76, + 992.84, 1346.40, 395.18, 1620.78, 1316.18, 679.69, 1115.23, 1679.96, 765.68, 735.85, 578.79, 1364.33, 1096.91, 638.70, 740.87, 1007.04, 1297.08, 396.49, 575.61, 1478.78, + 934.92, 289.41, 1142.74, 895.34, 1185.93, 1152.77, 1175.57, 1037.12, 1113.42, 450.84, 1573.31, 334.07, 1838.73, 1191.90, 878.61, 740.34, 1020.32, 1149.83, 1133.92, 587.39, + 1463.34, 1338.72, 589.95, 345.84, 868.80, 1498.73, 1412.65, 1357.10, 1478.39, 1227.79, 1006.65, 1843.31, 953.88, 534.37, 607.77, 956.35, 948.69, 881.54, 648.39, 1293.73, + 778.68, 290.54, 825.76, 1142.18, 1110.55, 725.01, 987.02, 698.44, 1882.36, 887.56, 1791.84, 1770.09, 592.34, 1558.82, 1652.77, 835.96, 719.46, 899.23, 664.05, 903.48, + 1396.04, 518.20, 1162.70, 439.42, 397.65, 772.71, 1158.74, 526.29, 1250.34, 1522.57, 1134.26, 614.25, 650.49, 583.54, 729.60, 524.55, 1391.95, 1278.39, 458.49, 908.20, + 846.41, 890.50, 966.06, 1065.12, 1389.53, 1308.07, 372.88, 918.11, 1384.40, 969.38, 962.13, 1032.60, 1076.19, 1073.28, 914.24, 838.56, 315.50, 1192.41, 839.63, 1663.34, + 1184.70, 1686.79, 700.69, 1849.94, 1509.85, 835.52, 151.84, 1039.76, 773.51, 256.03, 503.21, 749.88, 1238.18, 1076.99, 369.33, 571.92, 1019.76, 356.41, 1576.64, 704.75, + 1455.51, 1472.74, 1169.31, 1137.32, 1479.12, 695.76, 209.72, 557.09, 672.13, 670.97, 1728.14, 1015.15, 1386.02, 454.90, 433.10, 549.65, 1708.33, 640.17, 734.17, 1257.85, + 1084.79, 1347.56, 1389.80, 887.96, 1204.24, 1197.28, 326.78, 666.15, 1180.43, 928.80, 1287.07, 1032.07, 1180.09, 94.13, 685.73, 995.48, 493.52, 1151.15, 408.17, 1114.49, + 1524.20, 433.83, 1465.62, 563.97, 1396.91, 723.51, 1147.02, 1386.71, 717.25, 1714.24, 1794.58, 885.95, 641.78, 267.14, 1530.24, 1091.63, 632.86, 1245.24, 1046.10, 1504.05, + 1223.69, 811.73, 1168.43, 656.17, 765.15, 1217.91, 95.02, 650.84, 419.21, 649.88, 1116.37, 1608.19, 700.41, 1219.33, 1270.55, 889.25, 532.70, 1062.99, 1598.94, 1119.37, + 1178.37, 1441.16, 723.46, 1398.57, 480.94, 961.90, 1060.27, 552.90, 582.30, 371.55, 391.32, 1030.28, 769.01, 945.25, 1492.23, 941.67, 1179.47, 1229.81, 311.71, 793.56, + 964.38, 814.96, 522.52, 779.87, 972.03, 943.17, 465.51, 923.71, 1243.30, 1061.68, 193.53, 22.70, 1464.04, 900.06, 872.18, 1173.28, 1102.63, 1350.75, 924.32, 702.08, + 1210.63, 1291.41, 1146.94, 478.30, 817.32, 1526.45, 1595.77, 1059.94, 459.94, 1291.29, 230.02, 643.22, 734.35, 163.08, 1224.35, 1579.24, 739.99, 1853.34, 1493.65, 1205.98, + 986.54, 176.68, 1186.45, 833.02, 724.94, 1406.38, 960.15, 1115.99, 713.18, 541.81, 1460.84, 1529.83, 1204.00, 1205.70, 799.72, 380.19, 1368.62, 1609.47, 840.13, 679.74, + 1506.54, 633.28, 866.21, 327.23, 218.80, 1072.27, 572.78, 243.33, 1205.41, 202.56, 1448.61, 1638.72, 1584.11, 1080.07, 407.61, 199.82, 441.20, 1551.94, 965.44, 795.64, + 959.34, 555.31, 488.27, 406.73, 701.51, 1203.74, 1799.83, 1072.04, 538.08, 1203.05, 1066.74, 1159.37, 1395.75, 1338.61, 1009.44, 761.86, 1282.53, 1265.02, 496.10, 850.27, + 1052.65, 396.25, 1087.04, 1744.14, 1094.86, 1516.72, 1453.94, 1616.13, 1478.13, 1737.48, 522.87, 1072.44, 1174.25, 1552.93, 881.42, 1392.32, 723.46, 1180.41, 1342.61, 701.77, + 1164.72, 870.50, 562.36, 1244.36, 1173.48, 636.73, 1364.08, 1035.71, 1161.69, 775.92, 840.61, 1401.61, 1621.91, 668.97, 354.52, 1419.21, 1172.70, 647.51, 413.69, 876.51, + 642.38, 1212.78, 818.58, 1231.63, 1115.00, 1562.69, 1664.33, 1067.59, 102.18, 1246.92, 1629.75, 1728.50, 936.44, 830.21, 511.66, 1256.62, 1162.52, 1680.10, 200.55, 1287.67, + 945.54, 427.81, 1202.72, 384.08, 1592.24, 239.35, 405.04, 1191.17, 937.99, 897.12, 1060.18, 1005.41, 1723.60, 611.18, 990.11, 612.63, 1202.58, 699.39, 1590.74, 841.09, + 1903.33, 643.97, 650.04, 938.41, 996.74, 1554.70, 960.19, 1789.12, 1764.47, 843.99, 1493.67, 1089.42, 1570.66, 807.37, 1262.68, 833.91, 1155.12, 970.59, 1124.96, 974.72, + 1338.35, 311.26, 1574.08, 712.10, 1061.67, 987.70, 1020.03, 737.85, 264.38, 889.41, 1225.92, 773.42, 1365.73, 1150.43, 442.54, 939.08, 1064.75, 873.07, 273.93, 902.05, + 1764.15, 1499.80, 583.52, 1324.39, 1313.75, 741.33, 618.68, 914.59, 693.50, 1538.31, 1154.48, 327.54, 1018.09, 1397.45, 746.21, 328.09, 586.35, 1358.57, 1132.98, 947.89, + 769.17, 1100.19, 533.13, 894.29, 1313.62, 1001.59, 874.31, 1174.35, 1048.89, 564.06, 93.33, 809.48, 1129.55, 1314.88, 1304.70, 572.27, 1775.82, 1267.01, 1118.51, 978.19, + 959.40, 1089.10, 1405.59, 1203.46, 679.05, 1484.27, 1682.75, 1251.06, 377.47, 1735.35, 693.27, 530.23, 575.65, 1061.01, 955.49, 1021.06, 1095.51, 1294.81, 910.64, 427.66, + 1162.01, 1460.55, 796.81, 1079.52, 315.24, 1030.87, 648.27, 983.92, 1378.95, 112.53, 699.70, 1136.13, 753.89, 1400.42, 1087.55, 216.02, 947.95, 1562.12, 1025.12, 893.25, + 715.59, 664.46, 599.00, 1347.54, 165.38, 1487.48, 1004.37, 1076.79, 1007.48, 906.74, 1383.74, 823.94, 537.97, 1051.54, 1459.79, 1325.02, 1064.35, 754.49, 896.01, 669.95, + 1350.57, 662.43, 716.21, 1327.48, 1100.74, 549.02, 1224.82, 382.59, 743.32, 638.50, 647.15, 1116.38, 636.23, 1258.26, 181.62, 975.32, 1384.29, 809.34, 1338.34, 908.77, + 222.96, 901.00, 1267.96, 1341.91, 1342.76, 1573.69, 1312.25, 397.71, 716.94, 743.90, 1275.29, 1573.61, 1218.13, 1442.78, 777.53, 1886.74, 928.38, 1064.95, 682.57, 1389.99, + 137.80, 1581.75, 870.93, 183.08, 979.51, 1741.65, 1598.00, 325.19, 1688.71, 1388.89, 1350.48, 1605.55, 1216.06, 1443.41, 448.51, 816.99, 398.15, 620.33, 1695.69, 77.84, + 1003.98, 696.49, 1102.40, 860.31, 797.44, 1090.82, 1080.36, 1614.18, 1243.54, 602.96, 683.61, 1348.56, 723.06, 1480.29, 176.04, 192.82, 1945.34, 484.10, 736.05, 778.60, + 878.83, 1253.86, 1250.40, 1319.50, 698.36, 1214.66, 991.67, 1443.62, 1284.79, 1230.94, 1526.71, 1271.40, 1356.76, 1534.22, 428.41, 788.58, 1681.33, 827.11, 1243.77, 1340.54, + 813.27, 1095.47, 833.86, 1043.78, 480.13, 1482.43, 1402.35, 1031.26, 1148.11, 1531.28, 597.82, 821.05, 1338.69, 1314.80, 649.53, 1578.87, 1035.26, 1318.49, 922.49, 1788.10, + 970.84, 502.20, 253.02, 706.77, 707.80, 695.45, 1184.45, 1098.58, 1235.92, 434.17, 642.81, 998.40, 1337.46, 1422.00, 1641.30, 695.39, 1137.30, 1151.58, 1469.27, 813.26, + 1161.87, 1655.05, 207.04, 1167.83, 783.70, 1093.98, 1642.08, 1112.26, 1182.71, 1697.44, 1489.02, 1289.98, 916.05, 1675.47, 309.95, 1117.86, 790.35, 913.24, 834.63, 891.03, + 1082.40, 728.59, 240.69, 1188.95, 1132.99, 1567.14, 541.47, 1211.96, 1042.48, 1313.06, 1574.58, 821.21, 582.01, 880.12, 999.23, 399.25, 1491.61, 947.72, 397.45, 162.75, + 111.60, 1045.00, 940.01, 1266.90, 1692.45, 749.80, 1085.51, 1946.78, 946.25, 1511.17, 1513.31, 1005.75, 1093.23, 1537.69, 924.45, 1252.27, 1305.19, 1283.97, 1409.40, 950.03, + 523.06, 1406.31, 909.64, 953.01, 571.43, 1522.05, 1723.30, 1085.33, 1052.03, 792.36, 1230.06, 1305.36, 731.50, 1213.35, 790.13, 424.94, 1101.40, 567.48, 1376.87, 536.06, + 426.39, 188.71, 1679.97, 905.57, 880.88, 1174.62, 342.05, 834.11, 1429.95, 1255.03, 595.08, 964.68, 1751.30, 1332.67, 864.20, 1663.44, 917.26, 731.89, 835.65, 426.11, + 598.39, 328.55, 1198.86, 774.17, 1327.00, 1131.50, 596.69, 858.45, 782.24, 1422.98, 1347.43, 813.23, 1190.64, 1299.97, 261.53, 1054.87, 787.13, 1408.05, 1228.08, 953.22, + 730.28, 756.75, 431.44, 1768.64, 1117.16, 1804.65, 739.66, 411.11, 1581.98, 523.18, 1391.70, 372.29, 552.46, 764.22, 1180.11, 1267.78, 480.53, 1213.03, 1227.84, 563.46, + 1332.42, 163.53, 987.30, 497.06, 1217.30, 1655.09, 1294.21, 1801.51, 1373.76, 943.23, 1247.88, 573.11, 751.33, 818.42, 1263.77, 590.93, 82.72, 1198.69, 954.88, 592.85, + 1757.16, 1315.57, 1452.03, 263.52, 864.34, 43.90, 1455.87, 1278.42, 1495.61, 1270.29, 1637.27, 436.48, 924.10, 1777.09, 1071.38, 781.19, 1298.99, 797.01, 1082.87, 760.34, + 415.80, 1390.71, 1323.19, 666.33, 1541.97, 887.62, 971.73, 1122.91, 1551.00, 899.40, 757.40, 997.65, 1414.61, 972.90, 971.97, 955.10, 752.96, 1564.64, 798.87, 904.46, + 1335.73, 926.08, 1133.48, 783.88, 1413.28, 510.87, 620.83, 1532.29, 1349.13, 788.82, 834.80, 686.17, 384.31, 747.41, 1470.31, 786.32, 1332.86, 990.15, 984.81, 786.91, + 1739.38, 1153.33, 1429.27, 745.05, 360.07, 1333.72, 1198.64, 1452.21, 944.04, 1413.41, 1051.90, 1169.43, 1041.60, 524.85, 1149.41, 1327.75, 962.41, 1449.32, 858.12, 983.77, + 1203.83, 1505.59, 812.11, 863.24, 1443.57, 1363.27, 1133.76, 1133.62, 709.97, 393.53, 809.24, 1481.34, 534.41, 1418.23, 1001.29, 727.08, 783.39, 256.43, 1570.59, 1038.65, + 1412.63, 1078.93, 1217.72, 843.61 +}; + diff --git a/benchmarks/vec-vvadd/dataset_test.h b/benchmarks/vec-vvadd/dataset_test.h new file mode 100644 index 0000000..5917aea --- /dev/null +++ b/benchmarks/vec-vvadd/dataset_test.h @@ -0,0 +1,18 @@ + +#define DATA_SIZE 4 + +float input1_data[DATA_SIZE] = +{ + 41.59, 833.98, 564.92, 187.40 +}; + +float input2_data[DATA_SIZE] = +{ + 454.04, 335.65, 1.77, 989.44 +}; + +float verify_data[DATA_SIZE] = +{ + 495.63, 1169.63, 566.69, 1176.85 +}; + diff --git a/benchmarks/vec-vvadd/vec_vvadd_asm.S b/benchmarks/vec-vvadd/vec_vvadd_asm.S new file mode 100644 index 0000000..2e74436 --- /dev/null +++ b/benchmarks/vec-vvadd/vec_vvadd_asm.S @@ -0,0 +1,108 @@ +#***************************************************************************** +# vvadd function (assembly version) +#----------------------------------------------------------------------------- + + +#-------------------------------------------------------------------------- +# Headers and Defines +#-------------------------------------------------------------------------- + +# Here are some defines that make writing assembly code easier. + +# I'm using the knowledge that rN will be placed in register a0, rA will be +# placed into register a1, etc., based on the calling convention for functions. + +#define rN a0 +#define rA a1 +#define rB a2 +#define rC a3 + +#define rVLen a4 + +# WARNING: do not write to the s0,...,s9 registers without first saving them to +# the stack. + +#-------------------------------------------------------------------------- +# void scalar_vvadd_asm( int n, float a[], float b[], float c[] ) +#-------------------------------------------------------------------------- + + .text + .align 2 + .globl scalar_vvadd_asm + .type scalar_vvadd_asm,@function + +scalar_vvadd_asm: + + # ***** Scalar Example ***** + + beq rN, zero, done # exit early if n == 0 + +loop: + flw f2, 0(rA) + flw f3, 0(rB) + fadd.s f2, f2, f3 + fsw f2, 0(rC) + addi rN, rN, -1 + addi rA, rA, 4 + addi rB, rB, 4 + addi rC, rC, 4 + bne rN, zero, loop +done: + ret + + +#-------------------------------------------------------------------------- +# void vt_vvadd_asm( int n, float a[], float b[], float c[] ) +#-------------------------------------------------------------------------- + + + # ***** Vector-Thread Example ***** + + .globl vt_vvadd_asm + .type vt_vvadd_asm,@function + +vt_vvadd_asm: + + beq rN, zero, cpdone + la a5, vtcode + + # First, configure the vector unit. + # rd (given vlen), desired vlen, num of x-regs, num of f-regs + # For vvadd, we do not need to use any x-registers, and only two + # floating point registers. By using fewer registers, hwacha can give us a longer vector length! + # But make sure to use registers starting from x0, f0! + # WARNING: there is a BUG if you tell it you want 0 registers of any type! + # So here I'm asking for 1 x-register, even though I don't use any of them. + vvcfgivl rVLen, rN, 1, 2 + + +stripmineloop: + vsetvl rVLen, rN # set the vector length + # rN is the desired (application) vector length + # rVLen is what vector length we were given + + vflw vf0, rA # vector loads + vflw vf1, rB + vf 0(a5) # jump to vector-fetch code + vfsw vf0, rC # vector store + + sub rN, rN, rVLen # book keeping + slli a6, rVLen, 2 # turn num_elements into num_bytes + add rA, rA, a6 + add rB, rB, a6 + add rC, rC, a6 + bne rN, zero, stripmineloop + +cpdone: + fence.v.l # make stores visible to the control processor + ret + +vtcode: + fadd.s f0, f0, f1 + stop + + # The C code uses a jalr instruction to call this function + # so we can use a jr to return back to where the function + # was called. Also known as "ret", for "return". + + ret diff --git a/benchmarks/vec-vvadd/vec_vvadd_main.c b/benchmarks/vec-vvadd/vec_vvadd_main.c new file mode 100644 index 0000000..c08e41a --- /dev/null +++ b/benchmarks/vec-vvadd/vec_vvadd_main.c @@ -0,0 +1,255 @@ +//************************************************************************** +// Vector-Thread Vector-vector add benchmark +//-------------------------------------------------------------------------- +// +// This benchmark uses adds to vectors and writes the results to a third +// vector. The input data (and reference data) should be generated using the +// vvadd_gendata.pl perl script and dumped to a file named dataset.h. The +// riscv-gcc toolchain does not support system calls so printf's can only be +// used on a host system, not on the riscv-v processor simulator itself. +// +// HOWEVER: printstr() and printhex() are provided, for a primitive form of +// printing strings and hexadecimal values to stdout. + + +// Choose which implementation you wish to test... but leave only one on! +// (only the first one will be executed). +//#define SCALAR_C +//#define SCALAR_ASM +#define VT_ASM + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +//-------------------------------------------------------------------------- +// Platform Specific Includes + +#if HOST_DEBUG + #include + #include +#else +void printstr(const char*); +void exit(); +#endif + + +//-------------------------------------------------------------------------- +// Input/Reference Data + +//#include "dataset_test.h" +#include "dataset.h" + +//-------------------------------------------------------------------------- +// Helper functions + +int verify( int n, float test[], float correct[] ) +{ + int i; + for ( i = 0; i < n; i++ ) { +// if ( test[i] != correct[i] ) { + if ( test[i] > 1.02*correct[i] + || test[i] < 0.98*correct[i]) { +#if HOST_DEBUG + printf(" test[%d] : %3.2f\n", i, test[i]); + printf(" corr[%d] : %3.2f\n", i, correct[i]); +#endif + // tell us which index fails + 2 + // (so that if i==0,i==1 fails, we don't + // think it was a 'not-finished yet' or pass) +// return i+10; + return 2; + } + } + return 1; +} + +#if HOST_DEBUG +void printArray( char name[], int n, float arr[] ) +{ + int i; + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " %03.2f ", arr[i] ); + printf( "\n" ); +} +#endif + + +void finishTest( int correct, long long num_cycles, long long num_retired ) +{ + int toHostValue = correct; +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + // we no longer run in -testrun mode, which means we can't use + // the tohost register to communicate "test is done" and "test results" + // so instead we will communicate through print* functions! + if ( correct == 1 ) + { + printstr( "*** PASSED *** (num_cycles = 0x" ); + printhex(num_cycles); + printstr( ", num_inst_retired = 0x"); + printhex(num_retired); + printstr( ")\n" ); + } + else + { + printstr( "*** FAILED *** (num_cycles = 0x"); + printhex(num_cycles); + printstr( ", num_inst_retired = 0x"); + printhex(num_retired); + printstr( ")\n" ); + } + exit(); +#endif +} + + +// deprecated - cr10/stats-enable register no longer exists +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +long long getCycles() +{ + long long cycles = 1337; +#if ( !HOST_DEBUG && SET_STATS ) + __asm__ __volatile__( "rdcycle %0" : "=r" (cycles) ); +#endif + return cycles; +} + +long long getInstRetired() +{ + long long inst_retired = 1338; +#if ( !HOST_DEBUG && SET_STATS ) + __asm__ __volatile__( "rdinstret %0" : "=r" (inst_retired) ); +#endif + return inst_retired; +} + +//-------------------------------------------------------------------------- +// vvadd function + +// scalar C implementation +void vvadd( int n, float a[], float b[], float c[] ) +{ + int i; + for ( i = 0; i < n; i++ ) + c[i] = a[i] + b[i]; +} + +// assembly implementations can be found in *_asm.S + +//-------------------------------------------------------------------------- +// Main + +int main( int argc, char* argv[] ) +{ + float results_data[DATA_SIZE]; + long long start_cycles = 0; + long long stop_cycles = 0; + long long num_cycles; + long long start_retired = 0; + long long stop_retired = 0; + long long num_retired; + + // Output the input array + +#if HOST_DEBUG + printArray( "input1", DATA_SIZE, input1_data ); + printArray( "input2", DATA_SIZE, input2_data ); + printArray( "verify", DATA_SIZE, verify_data ); +#endif + + // -------------------------------------------------- + // If needed we preallocate everything in the caches + +#if PREALLOCATE + +#ifdef SCALAR_C + vvadd( DATA_SIZE, input1_data, input2_data, results_data ); +#else +#ifdef SCALAR_ASM + scalar_vvadd_asm( DATA_SIZE, input1_data, input2_data, results_data ); +#else +#ifdef VT_ASM + vt_vvadd_asm( DATA_SIZE, input1_data, input2_data, results_data ); +#endif +#endif +#endif + +#endif + + // -------------------------------------------------- + // Do the vvadd + start_cycles = getCycles(); + start_retired = getInstRetired(); + +#ifdef SCALAR_C + vvadd( DATA_SIZE, input1_data, input2_data, results_data ); +#else +#ifdef SCALAR_ASM + #if HOST_DEBUG==0 + scalar_vvadd_asm( DATA_SIZE, input1_data, input2_data, results_data ); + #endif +#else +#ifdef VT_ASM + #if HOST_DEBUG==0 + vt_vvadd_asm( DATA_SIZE, input1_data, input2_data, results_data ); + #endif +#endif +#endif +#endif + + stop_cycles = getCycles(); + stop_retired = getInstRetired(); + num_cycles = stop_cycles - start_cycles; + num_retired = stop_retired - start_retired; + +// printstr("stop_cycles: "); printhex(stop_cycles); printstr("\n"); +// printstr("star_cycles: "); printhex(start_cycles); printstr("\n"); + + // -------------------------------------------------- + // Print out the results + +#if HOST_DEBUG + printArray( "results", DATA_SIZE, results_data ); +#endif + + // -------------------------------------------------- + // Check the results + int correct = verify( DATA_SIZE, results_data, verify_data ); + finishTest(correct, num_cycles, num_retired); +} diff --git a/benchmarks/vec-vvadd/vvadd_gendata.pl b/benchmarks/vec-vvadd/vvadd_gendata.pl new file mode 100755 index 0000000..10fc4e9 --- /dev/null +++ b/benchmarks/vec-vvadd/vvadd_gendata.pl @@ -0,0 +1,139 @@ +#!/usr/bin/perl -w +#========================================================================== +# vvadd_gendata.pl +# +# Author : Christopher Batten (cbatten@mit.edu) +# Date : April 29, 2005 +# +(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm; +# +# Simple script which creates an input data set and the reference data +# for the vvadd benchmark. +# +ENDMSG + +use strict "vars"; +use warnings; +no warnings("once"); +use Getopt::Long; + +#-------------------------------------------------------------------------- +# Command line processing +#-------------------------------------------------------------------------- + +our %opts; + +sub usage() +{ + + print "\n"; + print " Usage: vvadd_gendata.pl [options] \n"; + print "\n"; + print " Options:\n"; + print " --help print this message\n"; + print " --size size of input data [1000]\n"; + print " --seed random seed [1]\n"; + print "$usageMsg"; + + exit(); +} + +sub processCommandLine() +{ + + $opts{"help"} = 0; + $opts{"size"} = 1000; + $opts{"seed"} = 1; + Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage(); + $opts{"help"} and usage(); + +} + +#-------------------------------------------------------------------------- +# Helper Functions +#-------------------------------------------------------------------------- + +sub printArray +{ + my $arrayName = $_[0]; + my $arrayRef = $_[1]; + + my $numCols = 20; + my $arrayLen = scalar(@{$arrayRef}); + + print "float ".$arrayName."[DATA_SIZE] = \n"; + print "{\n"; + + if ( $arrayLen <= $numCols ) { + print " "; + for ( my $i = 0; $i < $arrayLen; $i++ ) { + print sprintf("%3.2f",$arrayRef->[$i]); + if ( $i != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + else { + my $numRows = int($arrayLen/$numCols); + for ( my $j = 0; $j < $numRows; $j++ ) { + print " "; + for ( my $i = 0; $i < $numCols; $i++ ) { + my $index = $j*$numCols + $i; + print sprintf("%3.2f",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + if ( $arrayLen > ($numRows*$numCols) ) { + print " "; + for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) { + my $index = $numCols*$numRows + $i; + print sprintf("%3.2f",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + } + + print "};\n\n"; +} + +#-------------------------------------------------------------------------- +# Main +#-------------------------------------------------------------------------- + +sub main() +{ + + processCommandLine(); + srand($opts{"seed"}); + + my @values1; + my @values2; + my @sum; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + my $value1 = (rand(999)); + my $value2 = (rand(999)); + push( @values1, $value1 ); + push( @values2, $value2 ); + push( @sum, $value1 + $value2 ); + } + + + print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n"; + printArray( "input1_data", \@values1 ); + printArray( "input2_data", \@values2 ); + printArray( "verify_data", \@sum ); + +} + +main(); + diff --git a/benchmarks/vvadd/bmark.mk b/benchmarks/vvadd/bmark.mk new file mode 100644 index 0000000..d03cb96 --- /dev/null +++ b/benchmarks/vvadd/bmark.mk @@ -0,0 +1,29 @@ +#======================================================================= +# UCB CS250 Makefile fragment for benchmarks +#----------------------------------------------------------------------- +# +# Each benchmark directory should have its own fragment which +# essentially lists what the source files are and how to link them +# into an riscv and/or host executable. All variables should include +# the benchmark name as a prefix so that they are unique. +# + +vvadd_c_src = \ + vvadd_main.c \ + +vvadd_riscv_src = \ + crt.S \ + +vvadd_c_objs = $(patsubst %.c, %.o, $(vvadd_c_src)) +vvadd_riscv_objs = $(patsubst %.S, %.o, $(vvadd_riscv_src)) + +vvadd_host_bin = vvadd.host +$(vvadd_host_bin) : $(vvadd_c_src) + $(HOST_COMP) $^ -o $(vvadd_host_bin) + +vvadd_riscv_bin = vvadd.riscv +$(vvadd_riscv_bin) : $(vvadd_c_objs) $(vvadd_riscv_objs) + $(RISCV_LINK) $(vvadd_c_objs) $(vvadd_riscv_objs) -o $(vvadd_riscv_bin) + +junk += $(vvadd_c_objs) $(vvadd_riscv_objs) \ + $(vvadd_host_bin) $(vvadd_riscv_bin) diff --git a/benchmarks/vvadd/dataset1-large.h b/benchmarks/vvadd/dataset1-large.h new file mode 100644 index 0000000..911e8de --- /dev/null +++ b/benchmarks/vvadd/dataset1-large.h @@ -0,0 +1,165 @@ + +#define DATA_SIZE 1000 + +int input1_data[DATA_SIZE] = +{ + 41, 833, 564, 187, 749, 350, 132, 949, 584, 805, 621, 6, 931, 890, 392, 694, 961, 110, 116, 296, + 426, 314, 659, 774, 319, 678, 875, 376, 474, 938, 539, 569, 203, 280, 759, 606, 511, 657, 195, 81, + 267, 229, 337, 944, 902, 241, 913, 826, 933, 985, 195, 960, 566, 350, 649, 657, 181, 111, 859, 65, + 288, 349, 141, 905, 886, 264, 576, 979, 761, 241, 478, 499, 403, 222, 444, 721, 676, 317, 224, 937, + 288, 119, 615, 606, 389, 351, 455, 278, 367, 358, 584, 62, 985, 403, 346, 517, 559, 908, 775, 255, + 778, 598, 143, 33, 125, 941, 933, 799, 553, 431, 648, 952, 287, 19, 49, 86, 95, 441, 587, 614, + 382, 280, 808, 971, 819, 344, 450, 512, 965, 347, 808, 882, 537, 946, 701, 356, 567, 891, 22, 568, + 665, 423, 434, 158, 2, 84, 247, 49, 435, 792, 869, 486, 414, 369, 548, 518, 888, 682, 284, 264, + 499, 290, 897, 215, 731, 688, 251, 786, 555, 302, 528, 544, 322, 947, 287, 824, 304, 788, 733, 959, + 366, 722, 294, 975, 653, 748, 91, 378, 105, 102, 381, 651, 825, 840, 356, 148, 54, 140, 955, 343, + 533, 757, 521, 837, 592, 13, 173, 63, 121, 133, 758, 372, 951, 39, 129, 110, 847, 437, 255, 269, + 409, 628, 399, 549, 753, 564, 171, 19, 727, 501, 777, 43, 753, 81, 202, 853, 153, 760, 357, 943, + 922, 328, 496, 442, 516, 641, 276, 786, 113, 842, 907, 275, 237, 32, 784, 565, 357, 803, 819, 751, + 280, 85, 458, 454, 710, 459, 41, 253, 377, 508, 700, 860, 480, 741, 499, 709, 49, 371, 873, 945, + 992, 526, 721, 435, 232, 497, 697, 30, 348, 250, 350, 250, 573, 784, 749, 502, 823, 826, 170, 160, + 674, 32, 202, 143, 853, 90, 394, 107, 855, 106, 157, 6, 765, 204, 194, 574, 218, 526, 177, 239, + 698, 757, 706, 49, 84, 799, 893, 512, 373, 492, 14, 621, 83, 103, 794, 921, 643, 880, 834, 239, + 462, 114, 561, 529, 10, 997, 904, 387, 407, 105, 559, 936, 512, 409, 302, 202, 427, 613, 359, 521, + 684, 22, 185, 312, 107, 274, 387, 242, 486, 105, 698, 899, 770, 644, 80, 161, 407, 946, 30, 768, + 870, 113, 148, 62, 147, 838, 845, 432, 141, 211, 817, 821, 562, 364, 615, 495, 812, 916, 159, 430, + 803, 180, 544, 840, 458, 786, 872, 795, 806, 758, 104, 401, 254, 984, 136, 729, 584, 794, 414, 528, + 707, 554, 378, 766, 977, 236, 947, 229, 165, 505, 105, 704, 796, 140, 303, 795, 635, 560, 119, 8, + 532, 814, 37, 584, 739, 619, 767, 478, 57, 958, 784, 985, 837, 307, 67, 824, 996, 749, 171, 826, + 621, 155, 826, 43, 694, 80, 236, 747, 744, 265, 124, 731, 941, 425, 370, 320, 269, 542, 763, 752, + 915, 14, 1, 906, 995, 809, 560, 873, 972, 289, 509, 558, 970, 405, 579, 293, 251, 849, 129, 452, + 716, 86, 678, 181, 240, 335, 793, 641, 1, 320, 987, 646, 754, 958, 203, 142, 180, 299, 165, 761, + 974, 646, 559, 619, 422, 260, 565, 542, 492, 991, 745, 207, 372, 932, 664, 34, 533, 478, 908, 203, + 33, 214, 365, 892, 781, 680, 705, 688, 947, 386, 50, 101, 474, 399, 679, 330, 952, 471, 477, 725, + 713, 937, 529, 870, 77, 545, 907, 853, 143, 979, 239, 105, 365, 98, 54, 98, 440, 764, 315, 336, + 697, 774, 726, 324, 282, 536, 622, 594, 890, 75, 290, 496, 726, 449, 548, 135, 644, 838, 290, 767, + 162, 415, 491, 985, 116, 617, 859, 235, 282, 571, 913, 560, 194, 242, 782, 985, 728, 344, 430, 613, + 759, 176, 309, 333, 354, 310, 699, 46, 487, 503, 100, 393, 268, 314, 75, 345, 987, 600, 908, 384, + 92, 545, 277, 668, 351, 853, 863, 312, 100, 532, 567, 836, 370, 989, 461, 912, 182, 268, 160, 771, + 22, 854, 644, 17, 779, 911, 855, 137, 983, 717, 565, 719, 253, 785, 154, 196, 253, 447, 899, 5, + 325, 616, 309, 175, 159, 123, 838, 715, 550, 230, 82, 627, 324, 927, 103, 17, 966, 159, 177, 593, + 372, 393, 599, 745, 377, 865, 591, 553, 440, 345, 593, 290, 908, 544, 377, 456, 781, 110, 495, 896, + 806, 700, 548, 340, 29, 829, 630, 546, 613, 972, 116, 313, 904, 971, 607, 794, 169, 896, 507, 916, + 431, 339, 147, 224, 112, 580, 834, 134, 948, 201, 488, 396, 797, 478, 769, 574, 485, 339, 721, 451, + 821, 744, 0, 594, 277, 120, 680, 757, 555, 847, 517, 379, 505, 904, 246, 243, 394, 430, 214, 244, + 524, 399, 172, 304, 620, 594, 535, 698, 159, 750, 809, 454, 75, 93, 167, 16, 853, 494, 324, 78, + 52, 112, 10, 342, 730, 680, 287, 961, 92, 626, 912, 616, 860, 744, 744, 478, 615, 508, 914, 810, + 288, 974, 129, 581, 548, 868, 981, 270, 623, 653, 626, 990, 386, 323, 472, 164, 239, 189, 865, 231, + 356, 152, 825, 328, 390, 848, 38, 402, 616, 546, 206, 2, 783, 890, 815, 831, 665, 410, 94, 246, + 422, 211, 675, 9, 374, 426, 64, 53, 758, 811, 500, 437, 335, 328, 237, 415, 468, 684, 565, 305, + 449, 597, 136, 882, 383, 938, 268, 115, 908, 50, 952, 366, 397, 257, 231, 667, 35, 990, 443, 213, + 389, 13, 621, 52, 612, 934, 953, 828, 462, 621, 812, 522, 672, 57, 313, 352, 55, 972, 753, 416, + 879, 864, 572, 163, 721, 12, 643, 507, 968, 781, 840, 242, 630, 810, 795, 435, 885, 599, 696, 643, + 93, 710, 785, 112, 581, 12, 923, 615, 652, 359, 261, 233, 609, 686, 539, 118, 560, 739, 20, 317, + 976, 573, 386, 772, 663, 504, 212, 888, 907, 420, 737, 516, 25, 219, 797, 716, 452, 692, 683, 459, + 815, 323, 612, 247, 116, 352, 281, 738, 290, 909, 645, 625, 932, 220, 685, 373, 876, 646, 412, 955 +}; + +int input2_data[DATA_SIZE] = +{ + 454, 335, 1, 989, 365, 572, 64, 153, 216, 140, 210, 572, 339, 593, 898, 228, 12, 883, 750, 646, + 500, 436, 701, 812, 981, 150, 696, 564, 272, 258, 647, 509, 88, 703, 669, 375, 551, 936, 592, 569, + 952, 800, 584, 643, 368, 489, 328, 313, 592, 388, 543, 649, 979, 997, 814, 79, 208, 998, 629, 847, + 704, 997, 253, 715, 430, 415, 538, 700, 4, 494, 100, 864, 693, 416, 296, 285, 620, 78, 351, 540, + 646, 169, 527, 289, 796, 801, 720, 758, 745, 92, 989, 271, 853, 788, 531, 222, 461, 241, 358, 332, + 684, 740, 446, 311, 743, 557, 479, 557, 925, 796, 357, 891, 666, 514, 557, 870, 853, 440, 61, 678, + 396, 9, 17, 170, 291, 380, 536, 185, 917, 539, 983, 887, 54, 612, 951, 479, 151, 7, 641, 335, + 730, 95, 728, 280, 395, 688, 911, 476, 815, 729, 265, 127, 236, 214, 180, 6, 503, 596, 173, 643, + 346, 599, 68, 849, 658, 619, 121, 131, 828, 667, 433, 487, 753, 125, 626, 14, 10, 403, 106, 703, + 818, 964, 406, 874, 856, 86, 60, 660, 667, 153, 121, 98, 412, 236, 12, 423, 965, 216, 621, 361, + 921, 715, 647, 299, 886, 682, 36, 493, 551, 537, 969, 643, 434, 415, 303, 438, 860, 203, 478, 988, + 675, 719, 990, 338, 450, 633, 155, 646, 452, 427, 509, 988, 426, 12, 483, 142, 339, 390, 50, 171, + 601, 105, 968, 121, 879, 81, 870, 600, 603, 871, 887, 610, 404, 234, 745, 526, 275, 441, 226, 752, + 943, 726, 709, 201, 54, 758, 53, 397, 41, 141, 416, 747, 219, 478, 770, 180, 482, 691, 725, 173, + 186, 914, 1, 963, 247, 464, 362, 521, 233, 120, 40, 779, 195, 161, 743, 439, 355, 403, 141, 633, + 289, 782, 320, 636, 118, 852, 70, 816, 388, 954, 36, 16, 698, 695, 677, 598, 883, 824, 746, 462, + 511, 534, 440, 428, 732, 726, 702, 547, 86, 798, 215, 21, 651, 59, 429, 657, 96, 973, 659, 966, + 524, 62, 625, 303, 714, 409, 55, 728, 305, 436, 901, 592, 691, 796, 497, 177, 940, 995, 480, 158, + 822, 611, 680, 14, 111, 797, 185, 0, 718, 96, 749, 739, 814, 435, 326, 37, 33, 605, 935, 27, + 88, 441, 339, 344, 554, 365, 954, 639, 396, 991, 249, 338, 832, 974, 393, 266, 470, 348, 336, 419, + 249, 215, 542, 903, 636, 729, 581, 820, 671, 979, 418, 670, 920, 568, 745, 662, 139, 385, 927, 173, + 457, 316, 183, 477, 196, 399, 416, 805, 996, 270, 735, 696, 825, 528, 50, 623, 537, 87, 294, 867, + 110, 398, 781, 646, 375, 943, 897, 589, 44, 288, 845, 742, 99, 522, 443, 432, 165, 930, 28, 461, + 323, 272, 376, 340, 898, 158, 168, 443, 193, 631, 935, 274, 781, 185, 619, 292, 933, 156, 827, 88, + 987, 629, 649, 32, 1, 744, 399, 915, 791, 554, 984, 530, 600, 401, 683, 540, 903, 120, 995, 521, + 622, 224, 895, 530, 820, 651, 226, 96, 262, 569, 238, 126, 610, 191, 238, 796, 884, 573, 108, 140, + 789, 852, 23, 704, 890, 480, 52, 372, 201, 546, 408, 119, 645, 464, 81, 293, 52, 880, 224, 744, + 735, 886, 167, 1, 532, 321, 169, 485, 101, 177, 42, 708, 654, 915, 625, 242, 822, 795, 641, 252, + 245, 151, 876, 333, 601, 938, 775, 397, 233, 755, 454, 424, 210, 962, 900, 923, 655, 529, 595, 90, + 464, 685, 70, 754, 32, 494, 25, 389, 488, 37, 409, 639, 27, 950, 539, 80, 303, 723, 734, 125, + 552, 248, 107, 362, 48, 869, 144, 841, 724, 335, 470, 263, 343, 809, 677, 339, 336, 410, 465, 56, + 590, 485, 406, 993, 746, 238, 525, 336, 256, 134, 546, 722, 367, 943, 106, 629, 396, 208, 429, 523, + 130, 355, 990, 673, 991, 719, 449, 84, 616, 211, 707, 737, 847, 452, 316, 974, 746, 796, 522, 618, + 115, 727, 226, 165, 200, 830, 742, 187, 705, 671, 785, 886, 962, 657, 293, 620, 144, 173, 796, 72, + 678, 80, 793, 685, 637, 967, 241, 898, 693, 372, 601, 721, 398, 553, 72, 174, 978, 325, 558, 185, + 505, 859, 651, 573, 321, 349, 400, 890, 844, 885, 933, 980, 448, 989, 50, 332, 900, 716, 747, 444, + 6, 394, 285, 703, 450, 652, 771, 485, 534, 559, 481, 507, 434, 343, 42, 784, 865, 421, 415, 871, + 539, 162, 105, 481, 595, 115, 350, 964, 287, 232, 154, 602, 539, 943, 872, 121, 652, 811, 747, 362, + 340, 910, 206, 572, 505, 973, 961, 354, 627, 849, 971, 910, 410, 770, 63, 874, 396, 482, 619, 646, + 557, 328, 67, 884, 512, 972, 6, 513, 882, 562, 764, 366, 506, 786, 831, 382, 638, 452, 72, 83, + 59, 932, 929, 924, 961, 69, 797, 985, 854, 885, 600, 389, 232, 793, 179, 773, 689, 775, 494, 139, + 234, 431, 780, 371, 22, 653, 741, 815, 428, 139, 603, 315, 344, 889, 317, 260, 861, 377, 511, 304, + 70, 35, 854, 576, 490, 326, 303, 431, 813, 708, 388, 962, 967, 442, 49, 831, 251, 321, 741, 179, + 176, 117, 523, 764, 952, 704, 531, 804, 23, 611, 846, 375, 854, 971, 24, 639, 318, 723, 662, 647, + 281, 158, 294, 885, 734, 866, 471, 296, 673, 472, 439, 5, 155, 506, 948, 600, 445, 222, 784, 349, + 943, 150, 366, 444, 604, 720, 340, 972, 911, 321, 435, 50, 78, 761, 950, 238, 27, 226, 201, 176, + 877, 450, 879, 99, 143, 31, 812, 771, 527, 488, 797, 194, 293, 966, 276, 345, 413, 197, 386, 116, + 322, 680, 538, 553, 960, 874, 48, 506, 898, 539, 495, 764, 805, 286, 432, 836, 192, 825, 778, 586, + 359, 352, 746, 11, 749, 5, 408, 643, 441, 368, 97, 169, 359, 527, 672, 69, 880, 298, 300, 327, + 923, 829, 816, 497, 243, 981, 917, 713, 653, 503, 406, 543, 108, 304, 464, 954, 86, 802, 446, 28 +}; + +int verify_data[DATA_SIZE] = +{ + 495, 1168, 565, 1176, 1114, 922, 196, 1102, 800, 945, 831, 578, 1270, 1483, 1290, 922, 973, 993, 866, 942, + 926, 750, 1360, 1586, 1300, 828, 1571, 940, 746, 1196, 1186, 1078, 291, 983, 1428, 981, 1062, 1593, 787, 650, + 1219, 1029, 921, 1587, 1270, 730, 1241, 1139, 1525, 1373, 738, 1609, 1545, 1347, 1463, 736, 389, 1109, 1488, 912, + 992, 1346, 394, 1620, 1316, 679, 1114, 1679, 765, 735, 578, 1363, 1096, 638, 740, 1006, 1296, 395, 575, 1477, + 934, 288, 1142, 895, 1185, 1152, 1175, 1036, 1112, 450, 1573, 333, 1838, 1191, 877, 739, 1020, 1149, 1133, 587, + 1462, 1338, 589, 344, 868, 1498, 1412, 1356, 1478, 1227, 1005, 1843, 953, 533, 606, 956, 948, 881, 648, 1292, + 778, 289, 825, 1141, 1110, 724, 986, 697, 1882, 886, 1791, 1769, 591, 1558, 1652, 835, 718, 898, 663, 903, + 1395, 518, 1162, 438, 397, 772, 1158, 525, 1250, 1521, 1134, 613, 650, 583, 728, 524, 1391, 1278, 457, 907, + 845, 889, 965, 1064, 1389, 1307, 372, 917, 1383, 969, 961, 1031, 1075, 1072, 913, 838, 314, 1191, 839, 1662, + 1184, 1686, 700, 1849, 1509, 834, 151, 1038, 772, 255, 502, 749, 1237, 1076, 368, 571, 1019, 356, 1576, 704, + 1454, 1472, 1168, 1136, 1478, 695, 209, 556, 672, 670, 1727, 1015, 1385, 454, 432, 548, 1707, 640, 733, 1257, + 1084, 1347, 1389, 887, 1203, 1197, 326, 665, 1179, 928, 1286, 1031, 1179, 93, 685, 995, 492, 1150, 407, 1114, + 1523, 433, 1464, 563, 1395, 722, 1146, 1386, 716, 1713, 1794, 885, 641, 266, 1529, 1091, 632, 1244, 1045, 1503, + 1223, 811, 1167, 655, 764, 1217, 94, 650, 418, 649, 1116, 1607, 699, 1219, 1269, 889, 531, 1062, 1598, 1118, + 1178, 1440, 722, 1398, 479, 961, 1059, 551, 581, 370, 390, 1029, 768, 945, 1492, 941, 1178, 1229, 311, 793, + 963, 814, 522, 779, 971, 942, 464, 923, 1243, 1060, 193, 22, 1463, 899, 871, 1172, 1101, 1350, 923, 701, + 1209, 1291, 1146, 477, 816, 1525, 1595, 1059, 459, 1290, 229, 642, 734, 162, 1223, 1578, 739, 1853, 1493, 1205, + 986, 176, 1186, 832, 724, 1406, 959, 1115, 712, 541, 1460, 1528, 1203, 1205, 799, 379, 1367, 1608, 839, 679, + 1506, 633, 865, 326, 218, 1071, 572, 242, 1204, 201, 1447, 1638, 1584, 1079, 406, 198, 440, 1551, 965, 795, + 958, 554, 487, 406, 701, 1203, 1799, 1071, 537, 1202, 1066, 1159, 1394, 1338, 1008, 761, 1282, 1264, 495, 849, + 1052, 395, 1086, 1743, 1094, 1515, 1453, 1615, 1477, 1737, 522, 1071, 1174, 1552, 881, 1391, 723, 1179, 1341, 701, + 1164, 870, 561, 1243, 1173, 635, 1363, 1034, 1161, 775, 840, 1400, 1621, 668, 353, 1418, 1172, 647, 413, 875, + 642, 1212, 818, 1230, 1114, 1562, 1664, 1067, 101, 1246, 1629, 1727, 936, 829, 510, 1256, 1161, 1679, 199, 1287, + 944, 427, 1202, 383, 1592, 238, 404, 1190, 937, 896, 1059, 1005, 1722, 610, 989, 612, 1202, 698, 1590, 840, + 1902, 643, 650, 938, 996, 1553, 959, 1788, 1763, 843, 1493, 1088, 1570, 806, 1262, 833, 1154, 969, 1124, 973, + 1338, 310, 1573, 711, 1060, 986, 1019, 737, 263, 889, 1225, 772, 1364, 1149, 441, 938, 1064, 872, 273, 901, + 1763, 1498, 582, 1323, 1312, 740, 617, 914, 693, 1537, 1153, 326, 1017, 1396, 745, 327, 585, 1358, 1132, 947, + 768, 1100, 532, 893, 1313, 1001, 874, 1173, 1048, 563, 92, 809, 1128, 1314, 1304, 572, 1774, 1266, 1118, 977, + 958, 1088, 1405, 1203, 678, 1483, 1682, 1250, 376, 1734, 693, 529, 575, 1060, 954, 1021, 1095, 1293, 910, 426, + 1161, 1459, 796, 1078, 314, 1030, 647, 983, 1378, 112, 699, 1135, 753, 1399, 1087, 215, 947, 1561, 1024, 892, + 714, 663, 598, 1347, 164, 1486, 1003, 1076, 1006, 906, 1383, 823, 537, 1051, 1459, 1324, 1064, 754, 895, 669, + 1349, 661, 715, 1326, 1100, 548, 1224, 382, 743, 637, 646, 1115, 635, 1257, 181, 974, 1383, 808, 1337, 907, + 222, 900, 1267, 1341, 1342, 1572, 1312, 396, 716, 743, 1274, 1573, 1217, 1441, 777, 1886, 928, 1064, 682, 1389, + 137, 1581, 870, 182, 979, 1741, 1597, 324, 1688, 1388, 1350, 1605, 1215, 1442, 447, 816, 397, 620, 1695, 77, + 1003, 696, 1102, 860, 796, 1090, 1079, 1613, 1243, 602, 683, 1348, 722, 1480, 175, 191, 1944, 484, 735, 778, + 877, 1252, 1250, 1318, 698, 1214, 991, 1443, 1284, 1230, 1526, 1270, 1356, 1533, 427, 788, 1681, 826, 1242, 1340, + 812, 1094, 833, 1043, 479, 1481, 1401, 1031, 1147, 1531, 597, 820, 1338, 1314, 649, 1578, 1034, 1317, 922, 1787, + 970, 501, 252, 705, 707, 695, 1184, 1098, 1235, 433, 642, 998, 1336, 1421, 1641, 695, 1137, 1150, 1468, 813, + 1161, 1654, 206, 1166, 782, 1093, 1641, 1111, 1182, 1696, 1488, 1289, 915, 1674, 309, 1117, 790, 912, 833, 890, + 1081, 727, 239, 1188, 1132, 1566, 541, 1211, 1041, 1312, 1573, 820, 581, 879, 998, 398, 1491, 946, 396, 161, + 111, 1044, 939, 1266, 1691, 749, 1084, 1946, 946, 1511, 1512, 1005, 1092, 1537, 923, 1251, 1304, 1283, 1408, 949, + 522, 1405, 909, 952, 570, 1521, 1722, 1085, 1051, 792, 1229, 1305, 730, 1212, 789, 424, 1100, 566, 1376, 535, + 426, 187, 1679, 904, 880, 1174, 341, 833, 1429, 1254, 594, 964, 1750, 1332, 864, 1662, 916, 731, 835, 425, + 598, 328, 1198, 773, 1326, 1130, 595, 857, 781, 1422, 1346, 812, 1189, 1299, 261, 1054, 786, 1407, 1227, 952, + 730, 755, 430, 1767, 1117, 1804, 739, 411, 1581, 522, 1391, 371, 552, 763, 1179, 1267, 480, 1212, 1227, 562, + 1332, 163, 987, 496, 1216, 1654, 1293, 1800, 1373, 942, 1247, 572, 750, 818, 1263, 590, 82, 1198, 954, 592, + 1756, 1314, 1451, 262, 864, 43, 1455, 1278, 1495, 1269, 1637, 436, 923, 1776, 1071, 780, 1298, 796, 1082, 759, + 415, 1390, 1323, 665, 1541, 886, 971, 1121, 1550, 898, 756, 997, 1414, 972, 971, 954, 752, 1564, 798, 903, + 1335, 925, 1132, 783, 1412, 509, 620, 1531, 1348, 788, 834, 685, 384, 746, 1469, 785, 1332, 990, 983, 786, + 1738, 1152, 1428, 744, 359, 1333, 1198, 1451, 943, 1412, 1051, 1168, 1040, 524, 1149, 1327, 962, 1448, 858, 983 +}; + diff --git a/benchmarks/vvadd/dataset1.h b/benchmarks/vvadd/dataset1.h new file mode 100644 index 0000000..44f32f2 --- /dev/null +++ b/benchmarks/vvadd/dataset1.h @@ -0,0 +1,60 @@ + +#define DATA_SIZE 300 + +int input1_data[DATA_SIZE] = +{ + 41, 833, 564, 187, 749, 350, 132, 949, 584, 805, 621, 6, 931, 890, 392, 694, 961, 110, 116, 296, + 426, 314, 659, 774, 319, 678, 875, 376, 474, 938, 539, 569, 203, 280, 759, 606, 511, 657, 195, 81, + 267, 229, 337, 944, 902, 241, 913, 826, 933, 985, 195, 960, 566, 350, 649, 657, 181, 111, 859, 65, + 288, 349, 141, 905, 886, 264, 576, 979, 761, 241, 478, 499, 403, 222, 444, 721, 676, 317, 224, 937, + 288, 119, 615, 606, 389, 351, 455, 278, 367, 358, 584, 62, 985, 403, 346, 517, 559, 908, 775, 255, + 778, 598, 143, 33, 125, 941, 933, 799, 553, 431, 648, 952, 287, 19, 49, 86, 95, 441, 587, 614, + 382, 280, 808, 971, 819, 344, 450, 512, 965, 347, 808, 882, 537, 946, 701, 356, 567, 891, 22, 568, + 665, 423, 434, 158, 2, 84, 247, 49, 435, 792, 869, 486, 414, 369, 548, 518, 888, 682, 284, 264, + 499, 290, 897, 215, 731, 688, 251, 786, 555, 302, 528, 544, 322, 947, 287, 824, 304, 788, 733, 959, + 366, 722, 294, 975, 653, 748, 91, 378, 105, 102, 381, 651, 825, 840, 356, 148, 54, 140, 955, 343, + 533, 757, 521, 837, 592, 13, 173, 63, 121, 133, 758, 372, 951, 39, 129, 110, 847, 437, 255, 269, + 409, 628, 399, 549, 753, 564, 171, 19, 727, 501, 777, 43, 753, 81, 202, 853, 153, 760, 357, 943, + 922, 328, 496, 442, 516, 641, 276, 786, 113, 842, 907, 275, 237, 32, 784, 565, 357, 803, 819, 751, + 280, 85, 458, 454, 710, 459, 41, 253, 377, 508, 700, 860, 480, 741, 499, 709, 49, 371, 873, 945, + 992, 526, 721, 435, 232, 497, 697, 30, 348, 250, 350, 250, 573, 784, 749, 502, 823, 826, 170, 160 +}; + +int input2_data[DATA_SIZE] = +{ + 454, 335, 1, 989, 365, 572, 64, 153, 216, 140, 210, 572, 339, 593, 898, 228, 12, 883, 750, 646, + 500, 436, 701, 812, 981, 150, 696, 564, 272, 258, 647, 509, 88, 703, 669, 375, 551, 936, 592, 569, + 952, 800, 584, 643, 368, 489, 328, 313, 592, 388, 543, 649, 979, 997, 814, 79, 208, 998, 629, 847, + 704, 997, 253, 715, 430, 415, 538, 700, 4, 494, 100, 864, 693, 416, 296, 285, 620, 78, 351, 540, + 646, 169, 527, 289, 796, 801, 720, 758, 745, 92, 989, 271, 853, 788, 531, 222, 461, 241, 358, 332, + 684, 740, 446, 311, 743, 557, 479, 557, 925, 796, 357, 891, 666, 514, 557, 870, 853, 440, 61, 678, + 396, 9, 17, 170, 291, 380, 536, 185, 917, 539, 983, 887, 54, 612, 951, 479, 151, 7, 641, 335, + 730, 95, 728, 280, 395, 688, 911, 476, 815, 729, 265, 127, 236, 214, 180, 6, 503, 596, 173, 643, + 346, 599, 68, 849, 658, 619, 121, 131, 828, 667, 433, 487, 753, 125, 626, 14, 10, 403, 106, 703, + 818, 964, 406, 874, 856, 86, 60, 660, 667, 153, 121, 98, 412, 236, 12, 423, 965, 216, 621, 361, + 921, 715, 647, 299, 886, 682, 36, 493, 551, 537, 969, 643, 434, 415, 303, 438, 860, 203, 478, 988, + 675, 719, 990, 338, 450, 633, 155, 646, 452, 427, 509, 988, 426, 12, 483, 142, 339, 390, 50, 171, + 601, 105, 968, 121, 879, 81, 870, 600, 603, 871, 887, 610, 404, 234, 745, 526, 275, 441, 226, 752, + 943, 726, 709, 201, 54, 758, 53, 397, 41, 141, 416, 747, 219, 478, 770, 180, 482, 691, 725, 173, + 186, 914, 1, 963, 247, 464, 362, 521, 233, 120, 40, 779, 195, 161, 743, 439, 355, 403, 141, 633 +}; + +int verify_data[DATA_SIZE] = +{ + 495, 1168, 565, 1176, 1114, 922, 196, 1102, 800, 945, 831, 578, 1270, 1483, 1290, 922, 973, 993, 866, 942, + 926, 750, 1360, 1586, 1300, 828, 1571, 940, 746, 1196, 1186, 1078, 291, 983, 1428, 981, 1062, 1593, 787, 650, + 1219, 1029, 921, 1587, 1270, 730, 1241, 1139, 1525, 1373, 738, 1609, 1545, 1347, 1463, 736, 389, 1109, 1488, 912, + 992, 1346, 394, 1620, 1316, 679, 1114, 1679, 765, 735, 578, 1363, 1096, 638, 740, 1006, 1296, 395, 575, 1477, + 934, 288, 1142, 895, 1185, 1152, 1175, 1036, 1112, 450, 1573, 333, 1838, 1191, 877, 739, 1020, 1149, 1133, 587, + 1462, 1338, 589, 344, 868, 1498, 1412, 1356, 1478, 1227, 1005, 1843, 953, 533, 606, 956, 948, 881, 648, 1292, + 778, 289, 825, 1141, 1110, 724, 986, 697, 1882, 886, 1791, 1769, 591, 1558, 1652, 835, 718, 898, 663, 903, + 1395, 518, 1162, 438, 397, 772, 1158, 525, 1250, 1521, 1134, 613, 650, 583, 728, 524, 1391, 1278, 457, 907, + 845, 889, 965, 1064, 1389, 1307, 372, 917, 1383, 969, 961, 1031, 1075, 1072, 913, 838, 314, 1191, 839, 1662, + 1184, 1686, 700, 1849, 1509, 834, 151, 1038, 772, 255, 502, 749, 1237, 1076, 368, 571, 1019, 356, 1576, 704, + 1454, 1472, 1168, 1136, 1478, 695, 209, 556, 672, 670, 1727, 1015, 1385, 454, 432, 548, 1707, 640, 733, 1257, + 1084, 1347, 1389, 887, 1203, 1197, 326, 665, 1179, 928, 1286, 1031, 1179, 93, 685, 995, 492, 1150, 407, 1114, + 1523, 433, 1464, 563, 1395, 722, 1146, 1386, 716, 1713, 1794, 885, 641, 266, 1529, 1091, 632, 1244, 1045, 1503, + 1223, 811, 1167, 655, 764, 1217, 94, 650, 418, 649, 1116, 1607, 699, 1219, 1269, 889, 531, 1062, 1598, 1118, + 1178, 1440, 722, 1398, 479, 961, 1059, 551, 581, 370, 390, 1029, 768, 945, 1492, 941, 1178, 1229, 311, 793 +}; + diff --git a/benchmarks/vvadd/vvadd_gendata.pl b/benchmarks/vvadd/vvadd_gendata.pl new file mode 100755 index 0000000..f23cdf4 --- /dev/null +++ b/benchmarks/vvadd/vvadd_gendata.pl @@ -0,0 +1,139 @@ +#!/usr/bin/perl -w +#========================================================================== +# vvadd_gendata.pl +# +# Author : Christopher Batten (cbatten@mit.edu) +# Date : April 29, 2005 +# +(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm; +# +# Simple script which creates an input data set and the reference data +# for the vvadd benchmark. +# +ENDMSG + +use strict "vars"; +use warnings; +no warnings("once"); +use Getopt::Long; + +#-------------------------------------------------------------------------- +# Command line processing +#-------------------------------------------------------------------------- + +our %opts; + +sub usage() +{ + + print "\n"; + print " Usage: vvadd_gendata.pl [options] \n"; + print "\n"; + print " Options:\n"; + print " --help print this message\n"; + print " --size size of input data [1000]\n"; + print " --seed random seed [1]\n"; + print "$usageMsg"; + + exit(); +} + +sub processCommandLine() +{ + + $opts{"help"} = 0; + $opts{"size"} = 1000; + $opts{"seed"} = 1; + Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage(); + $opts{"help"} and usage(); + +} + +#-------------------------------------------------------------------------- +# Helper Functions +#-------------------------------------------------------------------------- + +sub printArray +{ + my $arrayName = $_[0]; + my $arrayRef = $_[1]; + + my $numCols = 20; + my $arrayLen = scalar(@{$arrayRef}); + + print "int ".$arrayName."[DATA_SIZE] = \n"; + print "{\n"; + + if ( $arrayLen <= $numCols ) { + print " "; + for ( my $i = 0; $i < $arrayLen; $i++ ) { + print sprintf("%3d",$arrayRef->[$i]); + if ( $i != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + else { + my $numRows = int($arrayLen/$numCols); + for ( my $j = 0; $j < $numRows; $j++ ) { + print " "; + for ( my $i = 0; $i < $numCols; $i++ ) { + my $index = $j*$numCols + $i; + print sprintf("%3d",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + if ( $arrayLen > ($numRows*$numCols) ) { + print " "; + for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) { + my $index = $numCols*$numRows + $i; + print sprintf("%3d",$arrayRef->[$index]); + if ( $index != $arrayLen-1 ) { + print ", "; + } + } + print "\n"; + } + + } + + print "};\n\n"; +} + +#-------------------------------------------------------------------------- +# Main +#-------------------------------------------------------------------------- + +sub main() +{ + + processCommandLine(); + srand($opts{"seed"}); + + my @values1; + my @values2; + my @sum; + for ( my $i = 0; $i < $opts{"size"}; $i++ ) { + my $value1 = int(rand(999)); + my $value2 = int(rand(999)); + push( @values1, $value1 ); + push( @values2, $value2 ); + push( @sum, $value1 + $value2 ); + } + + + print "\n\#define DATA_SIZE ".$opts{"size"}." \n\n"; + printArray( "input1_data", \@values1 ); + printArray( "input2_data", \@values2 ); + printArray( "verify_data", \@sum ); + +} + +main(); + diff --git a/benchmarks/vvadd/vvadd_main.c b/benchmarks/vvadd/vvadd_main.c new file mode 100644 index 0000000..9738118 --- /dev/null +++ b/benchmarks/vvadd/vvadd_main.c @@ -0,0 +1,139 @@ +//************************************************************************** +// Vector-vector add benchmark +//-------------------------------------------------------------------------- +// +// This benchmark uses adds to vectors and writes the results to a +// third vector. The input data (and reference data) should be +// generated using the vvadd_gendata.pl perl script and dumped +// to a file named dataset1.h The smips-gcc toolchain does not +// support system calls so printf's can only be used on a host system, +// not on the smips processor simulator itself. You should not change +// anything except the HOST_DEBUG and PREALLOCATE macros for your timing +// runs. + +//-------------------------------------------------------------------------- +// Macros + +// Set HOST_DEBUG to 1 if you are going to compile this for a host +// machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG +// to 0 if you are compiling with the smips-gcc toolchain. + +#ifndef HOST_DEBUG +#define HOST_DEBUG 0 +#endif + +// Set PREALLOCATE to 1 if you want to preallocate the benchmark +// function before starting stats. If you have instruction/data +// caches and you don't want to count the overhead of misses, then +// you will need to use preallocation. + +#ifndef PREALLOCATE +#define PREALLOCATE 0 +#endif + +// Set SET_STATS to 1 if you want to carve out the piece that actually +// does the computation. + +#ifndef SET_STATS +#define SET_STATS 0 +#endif + +//-------------------------------------------------------------------------- +// Input/Reference Data + +#include "dataset1.h" + +//-------------------------------------------------------------------------- +// Helper functions + +int verify( int n, int test[], int correct[] ) +{ + int i; + for ( i = 0; i < n; i++ ) { + if ( test[i] != correct[i] ) { + return 2; + } + } + return 1; +} + +#if HOST_DEBUG +void printArray( char name[], int n, int arr[] ) +{ + int i; + printf( " %10s :", name ); + for ( i = 0; i < n; i++ ) + printf( " %3d ", arr[i] ); + printf( "\n" ); +} +#endif + +void finishTest( int toHostValue ) +{ +#if HOST_DEBUG + if ( toHostValue == 1 ) + printf( "*** PASSED ***\n" ); + else + printf( "*** FAILED *** (tohost = %d)\n", toHostValue ); + exit(0); +#else + asm( "mtpcr %0, cr30" : : "r" (toHostValue) ); + while ( 1 ) { } +#endif +} + +void setStats( int enable ) +{ +#if ( !HOST_DEBUG && SET_STATS ) + asm( "mtpcr %0, cr10" : : "r" (enable) ); +#endif +} + +//-------------------------------------------------------------------------- +// vvadd function + +void vvadd( int n, int a[], int b[], int c[] ) +{ + int i; + for ( i = 0; i < n; i++ ) + c[i] = a[i] + b[i]; +} + +//-------------------------------------------------------------------------- +// Main + +int main( int argc, char* argv[] ) +{ + int results_data[DATA_SIZE]; + + // Output the input array + +#if HOST_DEBUG + printArray( "input1", DATA_SIZE, input1_data ); + printArray( "input2", DATA_SIZE, input2_data ); + printArray( "verify", DATA_SIZE, verify_data ); +#endif + + // If needed we preallocate everything in the caches + +#if PREALLOCATE + vvadd( DATA_SIZE, input1_data, input2_data, results_data ); +#endif + + // Do the vvadd + + setStats(1); + vvadd( DATA_SIZE, input1_data, input2_data, results_data ); + setStats(0); + + // Print out the results + +#if HOST_DEBUG + printArray( "results", DATA_SIZE, results_data ); +#endif + + // Check the results + + finishTest(verify( DATA_SIZE, results_data, verify_data )); + +}