diff --git a/2008-displacement/.gitignore b/2008-displacement/.gitignore index 45a28dc..72a792a 100644 --- a/2008-displacement/.gitignore +++ b/2008-displacement/.gitignore @@ -3,5 +3,10 @@ main *.dvi *.log *.pdf +*.o xy2d vote +bytecode +bytecode.*.bin +bytecode.lds +bytecode.lds.s diff --git a/2008-displacement/Makefile b/2008-displacement/Makefile index 0624388..33f6dfd 100644 --- a/2008-displacement/Makefile +++ b/2008-displacement/Makefile @@ -1,4 +1,74 @@ -all: main xy2d vote +ifeq ($(shell uname -m), x86_64) +ifeq ($(shell [ -d /lib64 ] && echo 64), 64) +CFLAGS = -m32 -march=i686 -mcpu=pentium4 -fomit-frame-pointer +CPPFLAGS = -m32 +LDFLAGS = -melf_i386 +endif +else # ! x86_64 + +ifeq ($(shell uname -m), i686) +CFLAGS = -march=i686 -mcpu=i686 -fomit-frame-pointer +CPPFLAGS = -m32 +LDFLAGS = -melf_i386 +else # ! i686 + +ifeq ($(shell uname -m), ppc64) +# mcpu means march and mtune means mcpu, oh well +CFLAGS = -m32 -mcpu=750 -mtune=970 +CPPFLAGS = -m32 +LDFLAGS = -melf32ppclinux +else # ! ppc64 + +ifeq ($(shell uname -m), ppc) +# mcpu means march and mtune means mcpu, oh well +CFLAGS = -mcpu=750 -mtune=970 +CPPFLAGS = -m32 +LDFLAGS = -melf32ppclinux +endif # ppc + +endif # ppc64 +endif # i686 +endif # x86_64 + +CFLAGS += -fno-common -O2 -Wall -Iglibc -I. +CPPFLAGS += -Iglibc -I. +LDFLAGS += -O2 + +CC = $(CROSS_COMPILE)gcc +CPP = $(CROSS_COMPILE)cpp +LD = $(CROSS_COMPILE)ld + +OBJCOPY = $(CROSS_COMPILE)objcopy + +LIBGCC = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) +LIBGCCEH = $(shell $(CC) $(CFLAGS) -print-file-name=libgcc_eh.a) +LIBM = $(shell $(CC) $(CFLAGS) -print-file-name=libm.a) +LIBC = $(shell $(CC) $(CFLAGS) -print-file-name=libc.a) + +all: bytecode.text.bin bytecode.data.bin main xy2d vote + +bytecode.o: main.c + $(CC) -DBYTECODE -c $(CFLAGS) $< -o $@ + +bytecode.lds.s: bytecode.lds.S + $(CPP) $(CPPFLAGS) $< -o $@ + +bytecode.lds: bytecode.lds.s + grep -A100000000 SECTION $< > $@ + +bytecode: bytecode.o bytecode.lds + $(LD) $(LDFLAGS) -static -T bytecode.lds $< --start-group $(LIBGCC) $(LIBC) $(LIBM) $(LIBGCCEH) --end-group -o $@ + +bytecode.text.bin: bytecode + $(OBJCOPY) -O binary $< -j .text $@ + +bytecode.data.bin: bytecode + $(OBJCOPY) -O binary $< -j .data $@ + +clean: + rm -f bytecode bytecode.lds bytecode.lds.s + rm -f xy2d vote main + rm -f *.pyc *.bin *.o xy2d: xy2d.c $(CC) -W -Wall $^ -o $@ @@ -9,6 +79,4 @@ vote: vote.c main: main.c $(CC) -Wall -O3 -funroll-loops -ffast-math -W -Wall $^ -o $@ $$(pkg-config --cflags --libs sdl) -lSDL_image -lm -clean: - rm -f xy2d vote main - +.PHONY: clean diff --git a/2008-displacement/README b/2008-displacement/README index 157c2a0..fe8f20f 100644 --- a/2008-displacement/README +++ b/2008-displacement/README @@ -1,7 +1,55 @@ -# Trouver des images au pif -% find ~/4chan/unsorted-4chan/http* -name '1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].???' | rev | sort -k2 -t. | rev | xargs -n 1 ./main | tee fs-4chan.txt -% find ~/4chan/unsorted-4chan/http* -name '1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].???' | rev | sort -k2 -t. | rev | xargs -n 1 ./main-jajuni | tee jajuni-4chan.txt -% cat /tmp/4chanlist.txt | xargs -n 1 ./main | tee -a fs-4chan.txt +# List all my 4chan images +find ~/4chan/unsorted-4chan/http* -name '1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].???' | rev | sort -k2 -t. | rev > 4chan-list.txt + +# Put all my 4chan images in 100 separate /tmp directories +for x in $(seq -w 00 09); do echo $x; mkdir -p /tmp/4chan/$x; cp $(find ~/4chan/unsorted-4chan/http* -name '1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'$x'.???') /tmp/4chan/$x; done + +# Condorcet voting for phase 2 results +# - raster + E +# - raster + E_min +# - serpentine + E +# - serpentine + E_min +for x in part2/*txt ; do grep '^.1' $x | awk '{ print $3,$5 }' >| $x.clean; done ; ./vote part2/*clean | sort -rnk3 | head -30 ; rm -f part2/*clean +for x in part2/*txt ; do grep '^.1' $x | awk '{ print $3,$9 }' >| $x.clean; done ; ./vote part2/*clean | sort -rnk3 | head -30 ; rm -f part2/*clean +for x in part2/*txt ; do grep '^.2' $x | awk '{ print $3,$5 }' >| $x.clean; done ; ./vote part2/*clean | sort -rnk3 | head -30 ; rm -f part2/*clean +for x in part2/*txt ; do grep '^.2' $x | awk '{ print $3,$9 }' >| $x.clean; done ; ./vote part2/*clean | sort -rnk3 | head -30 ; rm -f part2/*clean + +# Get phase 3 and phase 4 stuff +ssh canard.zoy.org "cd test-20080329; tar cz *raster.txt *serp.txt" | tar xz +for x in *-raster.txt; do y="$x"; y="${y%%-raster.txt}"; y="${y%%.tiff}"; y="${y##usc-sipi}"; \mv "$x" part3/"$y".txt; done +for x in *-serp.txt; do y="$x"; y="${y%%-serp.txt}"; y="${y%%.tiff}"; y="${y##usc-sipi}"; \mv "$x" part4/"$y".txt; done + +# Condorcet voting for part 3 and 4 +for x in part3/*txt ; do cat $x | awk '{ print $2,$4 }' >| $x.clean; done ; ./vote part3/*clean | sort -rnk3 | head -20 ; rm -f part3/*clean +for x in part3/*txt ; do cat $x | awk '{ print $2,$8 }' >| $x.clean; done ; ./vote part3/*clean | sort -rnk3 | head -20 ; rm -f part3/*clean +for x in part4/*txt ; do cat $x | awk '{ print $2,$4 }' >| $x.clean; done ; ./vote part4/*clean | sort -rnk3 | head -20 ; rm -f part4/*clean +for x in part4/*txt ; do cat $x | awk '{ print $2,$8 }' >| $x.clean; done ; ./vote part4/*clean | sort -rnk3 | head -20 ; rm -f part4/*clean + +# Mean voting for part 3 and 4 +cat part3/aerials2.1.01.txt | while read x k y ; do echo "$k $(grep $k part3/* | awk '{ a+=$4; dx+=$10; dy+=$12; n+=1 } END { print a/n, dx/n, dy/n }')"; done | sort -nk2 | head -20 +cat part3/aerials2.1.01.txt | while read x k y ; do echo "$k $(grep $k part3/* | awk '{ a+=$8; dx+=$10; dy+=$12; n+=1 } END { print a/n, dx/n, dy/n }')"; done | sort -nk2 | head -20 +cat part4/aerials2.1.01.txt | while read x k y ; do echo "$k $(grep $k part4/* | awk '{ a+=$4; dx+=$10; dy+=$12; n+=1 } END { print a/n, dx/n, dy/n }')"; done | sort -nk2 | head -20 +cat part4/aerials2.1.01.txt | while read x k y ; do echo "$k $(grep $k part4/* | awk '{ a+=$8; dx+=$10; dy+=$12; n+=1 } END { print a/n, dx/n, dy/n }')"; done | sort -nk2 | head -20 + +# Clever stuff (or not) +cat part3/aerials2.1.01.txt | grep K | while read x k y ; do grep $k part3/* | awk '{ dx+=$10; dy+=$12; n+=1 } END { print dx/n, dy/n }' | read dx dy; echo "$k $(grep $k part3/* | awk 'BEGIN { dx='$dx'; dy='$dy' } { x=dx-$10; y=dy-$12; t+=2.^-5*(x*x+y*y); a+=t*$4; n+=t } END { print a/n, n }')"; done | sort -nk2 | head -20 +cat part3/aerials2.1.01.txt | grep K | while read x k y ; do grep $k part3/* | awk '{ dx+=$10; dy+=$12; n+=1 } END { print dx/n, dy/n }' | read dx dy; echo "$k $(grep $k part3/* | awk 'BEGIN { dx='$dx'; dy='$dy' } { x=dx-$10; y=dy-$12; t+=2.^-5*(x*x+y*y); a+=t*$8; n+=t } END { print a/n, n }')"; done | sort -nk2 | head -20 +cat part4/aerials2.1.01.txt | grep K | while read x k y ; do grep $k part4/* | awk '{ dx+=$10; dy+=$12; n+=1 } END { print dx/n, dy/n }' | read dx dy; echo "$k $(grep $k part4/* | awk 'BEGIN { dx='$dx'; dy='$dy' } { x=dx-$10; y=dy-$12; t+=2.^-5*(x*x+y*y); a+=t*$4; n+=t } END { print a/n, n }')"; done | sort -nk2 | head -20 +cat part4/aerials2.1.01.txt | grep K | while read x k y ; do grep $k part4/* | awk '{ dx+=$10; dy+=$12; n+=1 } END { print dx/n, dy/n }' | read dx dy; echo "$k $(grep $k part4/* | awk 'BEGIN { dx='$dx'; dy='$dy' } { x=dx-$10; y=dy-$12; t+=2.^-5*(x*x+y*y); a+=t*$8; n+=t } END { print a/n, n }')"; done | sort -nk2 | head -20 + +### +### +### +### +### Stuff below here is deprecated or unsorted +### +### +### +### + +#% find ~/4chan/unsorted-4chan/http* -name '1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].???' | rev | sort -k2 -t. | rev | xargs -n 1 ./main | tee fs-4chan.txt +#% find ~/4chan/unsorted-4chan/http* -name '1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].???' | rev | sort -k2 -t. | rev | xargs -n 1 ./main-jajuni | tee jajuni-4chan.txt +#% cat /tmp/4chanlist.txt | xargs -n 1 ./main | tee -a fs-4chan.txt # Lena set hidden3d @@ -189,9 +237,8 @@ boat.png elaine.png texture[2345].png scp canard.zoy.org:out-'*'.txt . for x in out-*.txt; do sort -k7 $x | head -20 ; done | cut -f1 -d: | sort | uniq -c | sort -n -### Pour faire des répertoires -for x in $(seq -w 00 09); do echo $x; mkdir -p /tmp/4chan/$x; cp $(find ~/4chan/unsorted-4chan/http* -name '1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'$x'.???') /tmp/4chan/$x; done - -### Conversion du vieux format de résultats +### +### Conversion du vieux format de résultats (deprecated) cat -n $x | sed 's/^ *[0-9]*\([0-9]\)[[:space:]]*/[\1] /; s/....###/###/; s/\[[27]/[1/; s/\[[38]/[2/; s/\[[49]/[3/; s/\[[50]/[4/' +# diff --git a/2008-displacement/bytecode.c b/2008-displacement/bytecode.c new file mode 100644 index 0000000..a46a31f --- /dev/null +++ b/2008-displacement/bytecode.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2004-2007 Andrea Arcangeli + * 2008 Sam Hocevar + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * only version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include + +char x[1024] = "this is just here because the CPUShare server cannot " + "handle bytecode with no .data section"; + +volatile int stop; + +void sighandler(int signal) +{ + if(sys_write(1, "done", 4) != 4) + sys_exit(3); + stop = 1; +} + +void bytecode(unsigned char * mem, int heap_size, int stack_size) +{ + unsigned char n; + char c; + + if(sys_read(0, (char *)&n, 1) != 1) + sys_exit(-5); + + while(n-- && !stop) + { + if(sys_read(0, &c, 1) != 1) + sys_exit(-5); + + if(c >= 'a' && c <= 'z') + c = 'a' + ((c - 'a' + 13) % 26); + else if(c >= 'A' && c <= 'Z') + c = 'A' + ((c - 'A' + 13) % 26); + + if(sys_write(1, &c, 1) != 1) + sys_exit(-6); + } + + sys_exit(0); +} + diff --git a/2008-displacement/bytecode.lds.S b/2008-displacement/bytecode.lds.S new file mode 100644 index 0000000..1572453 --- /dev/null +++ b/2008-displacement/bytecode.lds.S @@ -0,0 +1,10 @@ +#include + +SECTIONS +{ + . = TEXT_ADDRESS; + .text : { *(.text .stub .text.* .gnu.linkonce.t.*) *(.rodata .rodata.*) } + . = DATA_BSS_ADDRESS; + .data : { *(.data* .sdata* .data.* .sdata.* .gnu.linkonce.d.*) } + .bss : { *(.dynbss) *(.bss* .bss.* .sbss .sbss.* .gnu.linkonce.b.*) } +} diff --git a/2008-displacement/main-cpushare b/2008-displacement/main-cpushare new file mode 100755 index 0000000..977a0bb --- /dev/null +++ b/2008-displacement/main-cpushare @@ -0,0 +1,125 @@ +#! /usr/bin/python + +import os, struct, sys, random + +import gd + +from cpushare.proto_const import * +from cpushare.exceptions import CompilationError + +# Our input data +source = False +result = False +todo = 0 + +# Parse command line +if len(sys.argv) < 4: + print 'Usage: %s - [image list]' % (sys.argv[0],) + sys.exit(-1) +mode = sys.argv[2][1] +source = sys.argv[3:] +result = [False] * len(source) + +class buy_state_machine_class(object): + buy_api = '0.0.0' + + w, h = 0, 0 + index = -1 + answer = '' + + def __init__(self, protocol): + self.protocol = protocol + self.handler = self.stringReceived + + def start(self): + global todo, source + if todo >= len(source): + return # We're finished... FIXME: a process is stuck + self.index = todo + todo += 1 + gd.gdMaxColors = 256 * 256 * 256 + im = gd.image(source[self.index]) + # Send mode + self.protocol.sendString(PROTO_SECCOMP_FORWARD + mode) + # Send image size + (self.w, self.h) = (w, h) = im.size() + print 'sending %s (%dx%d)' % (source[self.index], w, h) + msg = chr(w / 256) + chr(w % 256) + chr(h / 256) + chr(h % 256) + self.protocol.sendString(PROTO_SECCOMP_FORWARD + msg) + # Send image contents + msg = '' + for y in range(h): + for x in range(w): + p = im.getPixel((x, y)) + rgb = im.colorComponents(p) + msg += chr(rgb[1]) # use green coordinate + self.protocol.sendString(PROTO_SECCOMP_FORWARD + msg) + print '%s bytes sent' % len(msg) + + def stringReceived(self, string): + control = string[0] + data = string[1:] + + if control == PROTO_SECCOMP_FORWARD: + self.answer += data + if ord(self.answer[-1]) != 0: + return + global result + result[self.index] = self.answer[:-1] + print self.answer[:-1], + self.protocol.sendString(PROTO_SECCOMP_SUCCESS) + # the PROTO_SECCOMP_SUCCESS probably won't have a chance + # to go out but it doesn't matter because we'll disconnect + # not just this but all other seccomp state machines too + from twisted.internet import reactor + reactor.stop() + elif control == PROTO_SECCOMP_SIGNAL: + print 'Checkpoint starting' + elif control == PROTO_LOG: + print repr(data) + else: + if control == PROTO_SECCOMP_SUCCESS: + pass + elif control == PROTO_SECCOMP_FAILURE: + status = struct.unpack('!i', data)[0] + exit_code = status >> 8 + signal = status & 0xff + s = 'Seccomp failure: status %d, exit_code %d, signal %d.' % \ + (status, exit_code, signal) + print s + else: + s = 'Unknown failure %d - %s' % (ord(control), repr(string)) + self.protocol.sendString(PROTO_SECCOMP_FAILURE + s) + print s + self.protocol.sendString(PROTO_SECCOMP_FAILURE) + self.protocol.transport.loseConnection() + + def connectionLost(self): + pass + +# Build local module +from new import module +m = module('cpushare_buy') + +# Create bytecode -- i686 only +from cpushare.seccomp_gen import seccomp_gen_class +m.seccomp_gen_hash = {} +m.seccomp_gen_hash['i686'] = seccomp_gen_class('bytecode', 'i686') +m.seccomp_gen_hash['i686'].heap_kbytes = 1 +m.seccomp_gen_hash['i686'].stack_kbytes = 1 + +# Estimate of the max number of seconds that the sell client +# will take to checkpoint and send its state back to us +m.checkpoint_sec = 10 + +# Our buying state machine +m.buy_state_machine_class = buy_state_machine_class + +# Append our module to the global list of modules +sys.modules['cpushare_buy'] = m + +# Build a new command line and run twistd +sys.argv = [sys.argv[0], '-q', '-n', 'cpushare', '--order', sys.argv[1]] +from twisted.scripts.twistd import run +run() + diff --git a/2008-displacement/main.c b/2008-displacement/main.c index 21100f0..3693b45 100644 --- a/2008-displacement/main.c +++ b/2008-displacement/main.c @@ -3,11 +3,15 @@ #include #include #include -#include +#include #include -#include +#ifdef BYTECODE +# include +#else +# include +#endif #define MAXWIDTH 512 #define MAXHEIGHT 512 @@ -17,34 +21,241 @@ static int WIDTH, HEIGHT; -static inline float get(float const *src, int x, int y) +int main(int, char *[]); + +#ifdef BYTECODE +# define MAXIMAGES 128 +static int slots[MAXIMAGES]; +static double slotbuf[MAXIMAGES * MAXWIDTH * MAXHEIGHT]; + +volatile int stop; + +void sighandler(int signal) +{ + if(sys_write(1, "done", 4) != 4) + sys_exit(3); + stop = 1; +} + +void bytecode(unsigned char * mem, int heap_size, int stack_size) +{ + char mode[] = "-0"; + char *argv[] = { "program", mode, "arg" }; + char c; + + if(sys_read(0, mode + 1, 1) != 1) + sys_exit(-5); + + main(sizeof(argv)/sizeof(*argv), argv); + + c = 0; + if(sys_write(1, &c, 1) != 1) + sys_exit(-6); +} + +static int myatoi(const char *str) +{ + int i = 0; + while(*str) + { + i *= 10; + i += (unsigned char)*str++ - (unsigned char)'0'; + } + return i; +} +#define atoi myatoi +#endif + +#define WRITE_INT(i, base) \ + do \ + { \ + char buf[128], *b = buf + 127; \ + if(i <= 0) \ + sys_write(1, (i = -i) ? "-" : "0", 1); /* XXX: hack here */ \ + while(i) \ + { \ + *b-- = hex2char[i % base]; \ + i /= base; \ + } \ + sys_write(1, b + 1, (int)(buf + 127 - b)); \ + } while(0) + +static void msg(const char *f, ...) +{ + va_list args; + va_start(args, f); +#ifdef BYTECODE + static char const *hex2char = "0123456789abcdef"; + + for( ; *f; f++) + { + if(*f != '%') + { + sys_write(1, f, 1); + continue; + } + + f++; + if(!*f) + break; + + if(*f == 'c') + { + char i = (char)(unsigned char)va_arg(args, int); + if(i >= 0x20 && i < 0x7f) + sys_write(1, &i, 1); + else if(i == '\n') + sys_write(1, "\\n", 2); + else if(i == '\t') + sys_write(1, "\\t", 2); + else if(i == '\r') + sys_write(1, "\\r", 2); + else + { + sys_write(1, "\\x", 2); + sys_write(1, hex2char + ((i & 0xf0) >> 4), 1); + sys_write(1, hex2char + (i & 0x0f), 1); + } + } + else if(*f == 'i' || *f == 'd') + { + int i = va_arg(args, int); + WRITE_INT(i, 10); + } + else if(*f == 'x') + { + int i = va_arg(args, int); + WRITE_INT(i, 16); + } + else if(f[0] == 'l' && (f[1] == 'i' || f[1] == 'd')) + { + long int i = va_arg(args, long int); + WRITE_INT(i, 10); + f++; + } + else if(f[0] == 'l' && f[1] == 'l' && (f[2] == 'i' || f[1] == 'd')) + { + long long int i = va_arg(args, long long int); + WRITE_INT(i, 10); + f += 2; + } + else if(f[0] == 'g') + { + double g = va_arg(args, double), h = 9.9f; + int i; + if(g < 0.f) + { + sys_write(1, "-", 1); + g = -g; + } + for(i = 0; i < 7; i++) + { + sys_write(1, hex2char + (int)g, 1); + if(i == 0) + sys_write(1, ".", 1); + g = (g - (int)g) * 10; + h = h / 10.f; + if(g < h) + break; + } + } + else if(f[0] == 'p') + { + uintptr_t i = va_arg(args, uintptr_t); + if(!i) + sys_write(1, "NULL", 5); + else + { + sys_write(1, "0x", 2); + WRITE_INT(i, 16); + } + } + else if(f[0] == 's') + { + char *s = va_arg(args, char *); + if(!s) + sys_write(1, "(nil)", 5); + else + { + int l = 0; + while(s[l]) + l++; + sys_write(1, s, l); + } + } + else if(f[0] == '0' && f[1] == '2' && f[2] == 'x') + { + int i = va_arg(args, int); + sys_write(1, hex2char + ((i & 0xf0) >> 4), 1); + sys_write(1, hex2char + (i & 0x0f), 1); + f += 2; + } + else + { + sys_write(1, f - 1, 2); + } + } +#else + vprintf(f, args); + fflush(stdout); +#endif + va_end(args); +} + +static inline double get(double const *src, int x, int y) { return src[y * WIDTH + x]; } -static inline void put(float *src, int x, int y, float p) +static inline void put(double *src, int x, int y, double p) { src[y * WIDTH + x] = p; } -static float *new(void) +static double *new(void) { - return malloc(WIDTH * HEIGHT * sizeof(float)); +#ifdef BYTECODE + int i; + for(i = 0; i < MAXIMAGES; i++) + if(slots[i] == 0) + break; + if(i == MAXIMAGES) + return NULL; + slots[i] = 1; + return slotbuf + i * MAXWIDTH * MAXHEIGHT; +#else + return malloc(WIDTH * HEIGHT * sizeof(double)); +#endif +} + +static void del(double *img) +{ +#ifdef BYTECODE + int i; + for(i = 0; i < MAXIMAGES; i++) + if(slotbuf + i * MAXWIDTH * MAXHEIGHT == img) + break; + if(i == MAXIMAGES) + return; + slots[i] = 0; +#else + free(img); +#endif } -static float *copy(float const *src) +static double *copy(double const *src) { - float *dest = malloc(WIDTH * HEIGHT * sizeof(float)); - memcpy(dest, src, WIDTH * HEIGHT * sizeof(float)); + double *dest = new(); + memcpy(dest, src, WIDTH * HEIGHT * sizeof(double)); return dest; } #define N 5 #define NN ((N * 2 + 1)) -static void makegauss(float mat[NN][NN], float sigma, float dx, float dy) +static void makegauss(double mat[NN][NN], double sigma, double dx, double dy) { - float t = 0; + double t = 0; int i, j; sigma = 2. * sigma * sigma; @@ -52,8 +263,8 @@ static void makegauss(float mat[NN][NN], float sigma, float dx, float dy) for(j = 0; j < NN; j++) for(i = 0; i < NN; i++) { - float a = (float)(i - N) + dx; - float b = (float)(j - N) + dy; + double a = (double)(i - N) + dx; + double b = (double)(j - N) + dy; mat[i][j] = pow(M_E, - (a * a + b * b) / sigma); t += mat[i][j]; } @@ -63,15 +274,15 @@ static void makegauss(float mat[NN][NN], float sigma, float dx, float dy) mat[i][j] /= t; } -static float *gauss(float const *src, float mat[NN][NN]) +static double *gauss(double const *src, double mat[NN][NN]) { - float *dest = new(); + double *dest = new(); int x, y, i, j; for(y = N; y < HEIGHT - N; y++) for(x = N; x < WIDTH - N; x++) { - float p = 0; + double p = 0; for(j = 0; j < NN; j++) for(i = 0; i < NN; i++) @@ -83,15 +294,15 @@ static float *gauss(float const *src, float mat[NN][NN]) return dest; } -static float *fullgauss(float const *src, float mat[NN][NN]) +static double *fullgauss(double const *src, double mat[NN][NN]) { - float *dest = new(); + double *dest = new(); int x, y, i, j; for(y = 0; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) { - float p = 0; + double p = 0; for(j = 0; j < NN; j++) for(i = 0; i < NN; i++) @@ -106,15 +317,15 @@ static float *fullgauss(float const *src, float mat[NN][NN]) } #if 0 -static float fulldist(float const *p1, const float *p2) +static double fulldist(double const *p1, const double *p2) { - float error = 0.; + double error = 0.; int x, y; for(y = 0; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) { - float t = get(p1, x, y) - get(p2, x, y); + double t = get(p1, x, y) - get(p2, x, y); error += t * t; } @@ -122,9 +333,9 @@ static float fulldist(float const *p1, const float *p2) } #endif -static float dist(float const *p1, float const *p2, float max) +static double dist(double const *p1, double const *p2, double max) { - float error = 0.; + double error = 0.; int x, y; max *= (WIDTH - N) * (HEIGHT - N); @@ -133,7 +344,7 @@ static float dist(float const *p1, float const *p2, float max) { for(x = N; x < WIDTH - N; x++) { - float t = get(p1, x, y) - get(p2, x, y); + double t = get(p1, x, y) - get(p2, x, y); error += t * t; } @@ -147,12 +358,42 @@ static float dist(float const *p1, float const *p2, float max) return error / ((WIDTH - N) * (HEIGHT - N)); } -static float *load(char const *name) +static double *load(char const *name) { + double *floats; + int x, y; + +#ifdef BYTECODE + char c; + + if(sys_read(0, &c, 1) != 1) + sys_exit(-5); + WIDTH = ((int)(unsigned char)c) << 8; + if(sys_read(0, &c, 1) != 1) + sys_exit(-5); + WIDTH |= (int)(unsigned char)c; + + if(sys_read(0, &c, 1) != 1) + sys_exit(-5); + HEIGHT = ((int)(unsigned char)c) << 8; + if(sys_read(0, &c, 1) != 1) + sys_exit(-5); + HEIGHT |= (int)(unsigned char)c; + + floats = new(); + if(!floats) + return NULL; + + for(y = 0; y < HEIGHT; y++) + for(x = 0; x < WIDTH; x++) + { + if(sys_read(0, &c, 1) != 1) + sys_exit(-5); + put(floats, x, y, (double)(unsigned char)c / 0xff); + } +#else SDL_Surface *tmp, *surface; uint32_t *pixels; - float *floats; - int x, y; tmp = IMG_Load(name); if(!tmp) @@ -160,7 +401,7 @@ static float *load(char const *name) WIDTH = tmp->w > MAXWIDTH ? MAXWIDTH : tmp->w; HEIGHT = tmp->h > MAXHEIGHT ? MAXHEIGHT : tmp->h; - floats = malloc(WIDTH * HEIGHT * sizeof(float)); + floats = new(); if(!floats) return NULL; @@ -171,20 +412,32 @@ static float *load(char const *name) SDL_FreeSurface(tmp); for(y = 0; y < HEIGHT; y++) - for(x = 0; x < WIDTH; x++) - { - int green = (pixels[y * surface->pitch / 4 + x] >> 8) & 0xff; - put(floats, x, y, (float)green / 0xff); - } + for(x = 0; x < WIDTH; x++) + { + int green = (pixels[y * surface->pitch / 4 + x] >> 8) & 0xff; + put(floats, x, y, (double)green / 0xff); + } +#endif return floats; } -static void save(float const *src, char const *name) +static void save(double const *src, char const *name) { + int x, y; +#ifdef BYTECODE + for(y = 0; y < HEIGHT; y++) + for(x = 0; x < WIDTH; x++) + { + double p = 255 * get(src, x, y); + uint32_t i = p < 0 ? 0 : p > 255 ? 255 : p; + char c = (char)(unsigned char)i; + if(sys_write(1, &c, 1) != 1) + sys_exit(-6); + } +#else SDL_Surface *surface; uint32_t *pixels; - int x, y; surface = SDL_CreateRGBSurface(SDL_SWSURFACE, WIDTH, HEIGHT, 32, 0xff0000, 0xff00, 0xff, 0x0); @@ -193,15 +446,16 @@ static void save(float const *src, char const *name) for(y = 0; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) { - float p = 255 * get(src, x, y); + double p = 255 * get(src, x, y); uint32_t i = p < 0 ? 0 : p > 255 ? 255 : p; pixels[surface->pitch / 4 * y + x] = (i << 16) | (i << 8) | i; } SDL_SaveBMP(surface, name); +#endif } -static float *ostromoukhov(float const *src) +static double *ostromoukhov(double const *src) { static int const table[][3] = { @@ -239,8 +493,8 @@ static float *ostromoukhov(float const *src) {385, 112, 103}, {65, 18, 17}, {395, 104, 101}, {4, 1, 1} }; - float *dest = new(); - float *tmp = copy(src); + double *dest = new(); + double *tmp = copy(src); int x, y; for(y = 0; y < HEIGHT; y++) @@ -251,9 +505,9 @@ static float *ostromoukhov(float const *src) int x2 = (y & 1) ? WIDTH - 1 - x : x; int x3 = (y & 1) ? WIDTH - 1 - x - 1 : x + 1; - float p = get(tmp, x2, y); - float q = p > 0.5 ? 1. : 0.; - float error = (p - q); + double p = get(tmp, x2, y); + double q = p > 0.5 ? 1. : 0.; + double error = (p - q); int i = p * 255.9999; put(dest, x2, y, q); @@ -277,7 +531,7 @@ static float *ostromoukhov(float const *src) } } - free(tmp); + del(tmp); return dest; } @@ -287,12 +541,12 @@ static float *ostromoukhov(float const *src) c d e f g h i j k l */ -static float *ed(float const *src, int serpentine, +static double *ed(double const *src, int serpentine, int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) { - float *dest = new(); - float *tmp = copy(src); + double *dest = new(); + double *tmp = copy(src); int x, y, n; n = a + b + c + d + e + f + g + h + i + j + k + l; @@ -309,9 +563,9 @@ static float *ed(float const *src, int serpentine, int x3 = swap ? WIDTH - 1 - x - 1 : x + 1; int x4 = swap ? WIDTH - 1 - x - 2 : x + 2; - float p = get(tmp, x2, y); - float q = p > 0.5 ? 1. : 0.; - float error = (p - q) / n; + double p = get(tmp, x2, y); + double q = p > 0.5 ? 1. : 0.; + double error = (p - q) / n; put(dest, x2, y, q); @@ -362,18 +616,18 @@ static float *ed(float const *src, int serpentine, } } - free(tmp); + del(tmp); return dest; } /* XXX */ -static float *dbs(float const *src, float const *orig, - float sigma, float dx, float dy) +static double *dbs(double const *src, double const *orig, + double sigma, double dx, double dy) { - float mat[NN][NN]; - float *dest, *tmp, *tmp2; - float error; + double mat[NN][NN]; + double *dest, *tmp, *tmp2; + double error; makegauss(mat, sigma, 0., 0.); tmp = fullgauss(src, mat); @@ -392,7 +646,7 @@ static float *dbs(float const *src, float const *orig, for(y = 0; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) { - float d, d2, e, best = 0.; + double d, d2, e, best = 0.; int opx = -1, opy = -1; d = get(dest, x, y); @@ -406,7 +660,7 @@ static float *dbs(float const *src, float const *orig, for(i = -N; i < N + 1; i++) { - float m, p, q1, q2; + double m, p, q1, q2; if(x + i < 0 || x + i >= WIDTH) continue; @@ -445,7 +699,7 @@ static float *dbs(float const *src, float const *orig, continue; for(i = -N; i < N + 1; i++) { - float ma, mb, p, q1, q2; + double ma, mb, p, q1, q2; if(x + i < 0 || x + i >= WIDTH) continue; if(i - idx + N < 0 || i - idx + N >= NN) @@ -480,17 +734,17 @@ static float *dbs(float const *src, float const *orig, for(j = -N; j < N + 1; j++) for(i = -N; i < N + 1; i++) { - float m = mat[i + N][j + N]; + double m = mat[i + N][j + N]; if(y + j >= 0 && y + j < HEIGHT && x + i >= 0 && x + i < WIDTH) { - float t = get(tmp2, x + i, y + j); + double t = get(tmp2, x + i, y + j); put(tmp2, x + i, y + j, t + m * (d2 - d)); } if((opx || opy) && y + opy + j >= 0 && y + opy + j < HEIGHT && x + opx + i >= 0 && x + opx + i < WIDTH) { - float t = get(tmp2, x + opx + i, y + opy + j); + double t = get(tmp2, x + opx + i, y + opy + j); put(tmp2, x + opx + i, y + opy + j, t + m * (d - d2)); } } @@ -504,20 +758,20 @@ static float *dbs(float const *src, float const *orig, break; } - free(tmp); - free(tmp2); + del(tmp); + del(tmp2); return dest; } -static void study(float const *src, float const *dest, - float sigma, float precision, float fdx, float fdy) +static void study(double const *src, double const *dest, + double sigma, double precision, double fdx, double fdy) { # define Z 3 - float mat[NN][NN], mat2[NN][NN]; - float *tmp, *tmp2; - float e, e0, e1; - float best = 1., fx = -1., fy = -1., step = 2., bfx = 0., bfy = 0.; + double mat[NN][NN], mat2[NN][NN]; + double *tmp, *tmp2; + double e, e0, e1; + double best = 1., fx = -1., fy = -1., step = 2., bfx = 0., bfy = 0.; int dx, dy; makegauss(mat, sigma, 0., 0.); @@ -525,12 +779,12 @@ static void study(float const *src, float const *dest, tmp2 = gauss(dest, mat); e0 = dist(tmp, tmp2, 1.); - free(tmp2); + del(tmp2); makegauss(mat2, sigma, fdx, fdy); tmp2 = gauss(dest, mat2); e1 = dist(tmp, tmp2, 1.); - free(tmp2); + del(tmp2); while(step > precision) { @@ -540,7 +794,7 @@ static void study(float const *src, float const *dest, makegauss(mat, sigma, fx + step * dx / Z, fy + step * dy / Z); tmp2 = gauss(dest, mat); e = dist(tmp, tmp2, best); - free(tmp2); + del(tmp2); if(e < best) { best = e; @@ -554,16 +808,15 @@ static void study(float const *src, float const *dest, step = step * 2 / Z; } - free(tmp); + del(tmp); - printf("E: %g E_fast: %g E_min: %g dx: %g dy: %g\n", - 1000. * e0, 1000. * e1, 1000. * best, fx, fy); - fflush(stdout); + msg("E: %g E_fast: %g E_min: %g dx: %g dy: %g\n", + 1000. * e0, 1000. * e1, 1000. * best, fx, fy); } -static float *merge(float const *im1, float const *im2, float t) +static double *merge(double const *im1, double const *im2, double t) { - float *dest = new(); + double *dest = new(); int x, y; for(y = 0; y < HEIGHT; y++) @@ -586,7 +839,7 @@ static void usage(char *argv[]) int main(int argc, char *argv[]) { - float *src; + double *src; int mode, i; if(argc < 2) @@ -607,24 +860,24 @@ int main(int argc, char *argv[]) if(!src) return 2; - printf("### mode %i on `%s' ###\n", mode, argv[2]); + msg("### mode %i on `%s' ###\n", mode, argv[2]); switch(mode) { case 1: { - float *dest = ed(src, false, 7, 0, + double *dest = ed(src, false, 7, 0, 0, 3, 5, 1, 0, 0, 0, 0, 0, 0); study(src, dest, 1.2, 0.001, .16, .28); - free(dest); - free(src); + del(dest); + del(src); } break; case 2: { - float *src2, *dest, *tmp; + double *src2, *dest, *tmp; if(argc < 3) return 3; @@ -634,24 +887,24 @@ int main(int argc, char *argv[]) for(i = 0; i <= 100; i++) { - tmp = merge(src, src2, (float)i / 100.); + tmp = merge(src, src2, (double)i / 100.); dest = ed(tmp, false, 7, 0, 0, 3, 5, 1, 0, 0, 0, 0, 0, 0); study(tmp, dest, 1.2, 0.001, .16, .28); - free(dest); - free(tmp); + del(dest); + del(tmp); } - free(src2); - free(src); + del(src2); + del(src); } break; case 3: case 4: { - float mat[NN][NN]; - float *dest, *tmp, *tmp2; + double mat[NN][NN]; + double *dest, *tmp, *tmp2; int a, b, c, d, e; #define TOTAL 16 @@ -688,8 +941,8 @@ int main(int argc, char *argv[]) for(i = 1; i <= 2; i++) { - //printf("[%i] K: %d,%d,%d,%d,%d ", i, a2, b2, c2, d2, e2); - printf("[%i] K: %d,%d,%d,%d ", i, a2, c2, d2, e2); + //msg("[%i] K: %d,%d,%d,%d,%d ", i, a2, b2, c2, d2, e2); + msg("[%i] K: %d,%d,%d,%d ", i, a2, c2, d2, e2); dest = ed(src, i == 2, a2, 0, b2, c2, d2, e2, 0, @@ -703,60 +956,104 @@ int main(int argc, char *argv[]) { tmp = gauss(src, mat); tmp2 = gauss(dest, mat); - printf("E: %.5g\n", 1000. * dist(tmp, tmp2, 1.)); - free(tmp); - free(tmp2); + msg("E: %.5g\n", 1000. * dist(tmp, tmp2, 1.)); + del(tmp); + del(tmp2); } fflush(stdout); - free(dest); + del(dest); } } - free(src); + del(src); } break; case 5: { - float *dest; + double *dest; dest = ed(src, false, 7, 0, 0, 3, 5, 1, 0, 0, 0, 0, 0, 0); - printf("[1] "); + msg("[1] "); study(src, dest, 1.2, 0.001, .16, .28); - free(dest); + del(dest); dest = ed(src, false, 7, 5, 3, 5, 7, 5, 3, 1, 3, 5, 3, 1); - printf("[2] "); + msg("[2] "); study(src, dest, 1.2, 0.001, .26, .76); - free(dest); + del(dest); dest = ostromoukhov(src); - printf("[3] "); + msg("[3] "); study(src, dest, 1.2, 0.001, .0, .19); - free(dest); + del(dest); dest = ed(src, true, 2911, 0, 0, 1373, 3457, 2258, 0, 0, 0, 0, 0, 0); - printf("[4] "); + msg("[4] "); study(src, dest, 1.2, 0.001, .0, .34); } break; + case 6: + case 7: + { + double mat[NN][NN]; + double *dest; + int a, ax, b, bx, c, cx, d, dx; + + if(mode == 6) + a = 7, b = 3, c = 5, d = 1; + else + a = 7, b = 5, c = 4, d = 0; + +#undef TOTAL +#define TOTAL (a+b+c+d) + makegauss(mat, 1.2, 0, 0); + for(ax = -2; ax <= 2; ax++) + for(bx = -2; bx <= 2; bx++) + for(cx = -2; cx <= 2; cx++) + for(dx = -2; dx <= 3; dx++) + { + int a2 = a + ax, b2 = b + bx, c2 = c + cx, d2 = d + dx; + + if(a2 < 0 || a2 > TOTAL || b2 < 0 || b2 > TOTAL || + c2 < 0 || c2 > TOTAL || d2 < 0 || d2 > TOTAL) + continue; + + if(a2 + b2 + c2 + d2 != TOTAL) + continue; + + msg("K: %d,%d,%d,%d ", a2, b2, c2, d2); + + dest = ed(src, mode == 7, a2, 0, + 0, b2, c2, d2, 0, + 0, 0, 0, 0, 0); + /* XXX: E_fast is meaningless, ignore it */ + study(src, dest, 1.2, 0.001, 0., 0.); + fflush(stdout); + del(dest); + } + + del(src); + } + break; + #if 0 tmp = ed(src, 7, 0, 0, 3, 5, 1, 0, 0, 0, 0, 0, 0); //dest = dbs(src, tmp, 0., 0.); dest = dbs(src, tmp, 0.20, 0.30); //dest = dbs(src, tmp, 0.158718, 0.283089); //dest = copy(tmp); - free(tmp); + del(tmp); study(src, dest, 1.2, 0.00001); save(dest, "output.bmp"); - free(dest); + del(dest); #endif #if 0 @@ -771,10 +1068,10 @@ int main(int argc, char *argv[]) //dest = ed(src, 2911, 0, 1373, 3457, 2258, 0, 0, 0, 0, 0, 0, 0); dest = ostromoukhov(src); //dest = ed(src, 7, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0); - //printf("%s: ", argv[1]); + //msg("%s: ", argv[1]); //study(src, dest, 1.2, 0.001); save(dest, "output.bmp"); - free(dest); + del(dest); #endif #if 0 @@ -786,16 +1083,16 @@ int main(int argc, char *argv[]) { for(dx = 0; dx < STEP; dx++) { - float fy = 2. / STEP * (dy - STEP / 2.); - float fx = 2. / STEP * (dx - STEP / 2.); + double fy = 2. / STEP * (dy - STEP / 2.); + double fx = 2. / STEP * (dx - STEP / 2.); makegauss(mat, 1.2, fx, fy); tmp2 = gauss(dest, mat); - printf("%g %g %g\n", fy, fx, 1000. * dist(tmp, tmp2, 1.)); + msg("%g %g %g\n", fy, fx, 1000. * dist(tmp, tmp2, 1.)); fflush(stdout); - free(tmp2); + del(tmp2); } - printf("\n"); + msg("\n"); } save(dest, "output.bmp"); @@ -812,35 +1109,35 @@ int main(int argc, char *argv[]) continue; dest = ed(src, a, 0, 0, b, c, d, 0, 0, 0, 0, 0, 0); tmp2 = gauss(dest, 0., 0.); - printf("%.5g: (%02d %02d %02d %02d)\n", - 1000. * dist(tmp, tmp2, 1.), a, b, c, d); - free(dest); - free(tmp2); + msg("%.5g: (%02d %02d %02d %02d)\n", + 1000. * dist(tmp, tmp2, 1.), a, b, c, d); + del(dest); + del(tmp2); } save(dest, "output.bmp"); #endif #if 0 - printf("%s\n", argv[1]); + msg("%s\n", argv[1]); dest = ed(src, false, 7, 0, 0, 3, 5, 1, 0, 0, 0, 0, 0, 0); study(src, dest, 1.2, 0.01); - free(dest); + del(dest); dest = ed(src, false, 7, 5, 3, 5, 7, 5, 3, 1, 3, 5, 3, 1); study(src, dest, 1.2, 0.01); - free(dest); + del(dest); dest = ostromoukhov(src); study(src, dest, 1.2, 0.01); - free(dest); + del(dest); dest = ed(src, true, 2911, 0, 0, 1373, 3457, 2258, 0, 0, 0, 0, 0, 0); study(src, dest, 1.2, 0.01); - free(dest); + del(dest); - printf("\n"); + msg("\n"); #endif #if 0 @@ -851,7 +1148,7 @@ int main(int argc, char *argv[]) for(sigma = 0.8; sigma < 2; sigma *= 1.03) //for(sigma = 0.8; sigma < 2.; sigma *= 1.01) { - printf("%g ", sigma); + msg("%g ", sigma); study(src, dest, sigma, 0.01); } #endif @@ -864,7 +1161,7 @@ int main(int argc, char *argv[]) for(sigma = 0.8; sigma < 2; sigma *= 1.03) { char buf[1024]; - printf("%i: %g\n", a, sigma); + msg("%i: %g\n", a, sigma); dest = dbs(src, tmp, sigma, 0., 0.); sprintf(buf, "output-dbs-%i.bmp", a++); save(dest, buf); diff --git a/2008-displacement/study-4.sh b/2008-displacement/study-4.sh index 72f3bb3..f96408a 100755 --- a/2008-displacement/study-4.sh +++ b/2008-displacement/study-4.sh @@ -26,7 +26,7 @@ find $1 -type f | while read i; do fi touch "$OUTPUT" - ./main -4 $i | tee -a "$OUTPUT" | while read line; do + ./main -4 "$i" | tee -a "$OUTPUT" | while read line; do echo -n . done echo "done." diff --git a/2008-displacement/study-5.sh b/2008-displacement/study-5.sh index 74ec1d3..1642582 100755 --- a/2008-displacement/study-5.sh +++ b/2008-displacement/study-5.sh @@ -25,7 +25,7 @@ find $1 -type f | while read i; do if grep -q "$J" "$OUTPUT"; then continue fi - if TMP="$(./main -5 $i)"; then + if TMP="$(./main -5 "$i")"; then echo "$TMP" >> "$OUTPUT" echo "$TMP" else diff --git a/2008-displacement/study-6.sh b/2008-displacement/study-6.sh new file mode 100755 index 0000000..d8848f1 --- /dev/null +++ b/2008-displacement/study-6.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +set -e + +if [ ! -x ./main ]; then + make main +fi + +if [ "$1" = "" ]; then + echo "Usage: $0 " + exit 1 +fi + +if [ ! -d "$1" ]; then + echo "$0: $1 is not a directory" + exit 1 +fi + +find $1 -type f | while read i; do + OUTPUT="$(echo "$i" | tr -d / | sed 's/^[.]*//')-raster.txt" + echo "$0: outputting to $OUTPUT" + + if [ -f "$OUTPUT" ]; then + echo "$0: file already exists, skipping" + continue + fi + + touch "$OUTPUT" + ./main -6 "$i" | tee -a "$OUTPUT" | while read line; do + echo -n . + done + echo "done." +done + diff --git a/2008-displacement/study-7.sh b/2008-displacement/study-7.sh new file mode 100755 index 0000000..46d06f6 --- /dev/null +++ b/2008-displacement/study-7.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +set -e + +if [ ! -x ./main ]; then + make main +fi + +if [ "$1" = "" ]; then + echo "Usage: $0 " + exit 1 +fi + +if [ ! -d "$1" ]; then + echo "$0: $1 is not a directory" + exit 1 +fi + +find $1 -type f | while read i; do + OUTPUT="$(echo "$i" | tr -d / | sed 's/^[.]*//')-serp.txt" + echo "$0: outputting to $OUTPUT" + + if [ -f "$OUTPUT" ]; then + echo "$0: file already exists, skipping" + continue + fi + + touch "$OUTPUT" + ./main -7 "$i" | tee -a "$OUTPUT" | while read line; do + echo -n . + done + echo "done." +done + diff --git a/2008-displacement/vote.c b/2008-displacement/vote.c index 2871275..7b2c6fd 100644 --- a/2008-displacement/vote.c +++ b/2008-displacement/vote.c @@ -65,6 +65,9 @@ static void readfile(char const *file) float val; int n, i, j; + for(i = 0; i < nitems; i++) + values[i] = 9999.; + f = fopen(file, "r"); if(!f) return;