瀏覽代碼

* More scripts for part 3.

* Implemented main.c as a seccomp bytecode for CPUShare.


git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/research@2286 92316355-f0b4-4df1-b90c-862c8a59935f
master
sam 16 年之前
父節點
當前提交
c368ae0f32
共有 12 個檔案被更改,包括 827 行新增142 行删除
  1. +5
    -0
      2008-displacement/.gitignore
  2. +72
    -4
      2008-displacement/Makefile
  3. +55
    -8
      2008-displacement/README
  4. +62
    -0
      2008-displacement/bytecode.c
  5. +10
    -0
      2008-displacement/bytecode.lds.S
  6. +125
    -0
      2008-displacement/main-cpushare
  7. +425
    -128
      2008-displacement/main.c
  8. +1
    -1
      2008-displacement/study-4.sh
  9. +1
    -1
      2008-displacement/study-5.sh
  10. +34
    -0
      2008-displacement/study-6.sh
  11. +34
    -0
      2008-displacement/study-7.sh
  12. +3
    -0
      2008-displacement/vote.c

+ 5
- 0
2008-displacement/.gitignore 查看文件

@@ -3,5 +3,10 @@ main
*.dvi
*.log
*.pdf
*.o
xy2d
vote
bytecode
bytecode.*.bin
bytecode.lds
bytecode.lds.s

+ 72
- 4
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

+ 55
- 8
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/'

#

+ 62
- 0
2008-displacement/bytecode.c 查看文件

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2004-2007 Andrea Arcangeli <andrea@cpushare.com>
* 2008 Sam Hocevar <sam@zoy.org>
*
* 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 <signal.h>
#include <math.h>
#include <string.h>

#include <seccomp-loader.h>

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);
}


+ 10
- 0
2008-displacement/bytecode.lds.S 查看文件

@@ -0,0 +1,10 @@
#include <seccomp-loader.h>

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.*) }
}

+ 125
- 0
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 <buy_order.cpu> -<mode> [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()


+ 425
- 128
2008-displacement/main.c 查看文件

@@ -3,11 +3,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

#include <math.h>

#include <SDL_image.h>
#ifdef BYTECODE
# include <seccomp-loader.h>
#else
# include <SDL_image.h>
#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);


+ 1
- 1
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."


+ 1
- 1
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


+ 34
- 0
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 <directory>"
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


+ 34
- 0
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 <directory>"
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


+ 3
- 0
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;


Loading…
取消
儲存