diff --git a/.github/workflows/hw-build.yml b/.github/workflows/hw-build.yml new file mode 100644 index 00000000..8e818a39 --- /dev/null +++ b/.github/workflows/hw-build.yml @@ -0,0 +1,103 @@ +name: HW Build + +on: + push: + branches: + - main + release: + types: [published] + pull_request: + branches: + - '**' + workflow_dispatch: + +concurrency: + # SHA is added to the end if on `main` to let all main workflows run + group: ${{ github.ref }}-${{ github.workflow }}-${{ github.event_name }}-${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.ref, 'refs/heads/long_lived/')) && github.sha || '' }} + cancel-in-progress: true + +permissions: + contents: write + +jobs: + build-hw: + name: Build HW VDF Client + runs-on: [ubuntu-latest] + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set Env + uses: Chia-Network/actions/setjobenv@main + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install deps + run: | + sudo apt-get update + sudo apt-get install -y build-essential cmake libgmp-dev libboost-system-dev + + - name: Download USB drivers + run: | + mkdir libft4222 + cd libft4222 + wget https://download.chia.net/vdf/libft4222-linux-1.4.4.170.tgz + tar -xvzf libft4222-linux-1.4.4.170.tgz + ln -s ${{ github.workspace }}/libft4222 ${{ github.workspace }}/src/hw/libft4222 + ln -s ${{ github.workspace }}/libft4222/build-x86_64/libft4222.so.1.4.4.170 ${{ github.workspace }}/libft4222/build-x86_64/libft4222.so + + - name: Compile + working-directory: "${{ github.workspace }}/src" + run: make -f Makefile.vdf-client emu_hw_test hw_test emu_hw_vdf_client hw_vdf_client + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: hw-vdf + path: | + ${{ github.workspace }}/src/emu_hw_test + ${{ github.workspace }}/src/hw_test + ${{ github.workspace }}/src/hw_vdf_client + ${{ github.workspace }}/src/emu_hw_vdf_client + ${{ github.workspace }}/src/hw/libft4222/build-x86_64/libft4222.so + + - name: Assemble .deb + env: + INSTALLER_VERSION: "${{ env.RELEASE_TAG || format('0.0.1-{0}', github.run_id) }}" + PLATFORM: "amd64" + run: | + pip install j2cli + CLI_DEB_BASE="chiavdf-hw_$INSTALLER_VERSION-1_$PLATFORM" + mkdir -p "dist/$CLI_DEB_BASE/usr/bin" + mkdir -p "dist/$CLI_DEB_BASE/usr/lib" + mkdir -p "dist/$CLI_DEB_BASE/DEBIAN" + mkdir -p "dist/$CLI_DEB_BASE/etc/udev/rules.d" + j2 -o "dist/$CLI_DEB_BASE/DEBIAN/control" assets/deb/control.j2 + + cp ${{ github.workspace }}/src/emu_hw_test dist/$CLI_DEB_BASE/usr/bin/ + cp ${{ github.workspace }}/src/hw_test dist/$CLI_DEB_BASE/usr/bin/ + cp ${{ github.workspace }}/src/hw_vdf_client dist/$CLI_DEB_BASE/usr/bin/ + cp ${{ github.workspace }}/src/emu_hw_vdf_client dist/$CLI_DEB_BASE/usr/bin/ + cp ${{ github.workspace }}/src/hw/libft4222/build-x86_64/libft4222.so dist/$CLI_DEB_BASE/usr/lib/ + echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="601c", MODE="0666"' > dist/$CLI_DEB_BASE/etc/udev/rules.d/99-chiavdf.rules + dpkg-deb --build --root-owner-group "dist/$CLI_DEB_BASE" + + echo "DEB_NAME=$CLI_DEB_BASE.deb" >> $GITHUB_ENV + + - name: Upload Installer + uses: actions/upload-artifact@v3 + with: + name: installer + path: | + ${{ github.workspace }}/dist/${{ env.DEB_NAME }} + + - name: Upload release artifacts + if: env.RELEASE == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release upload \ + $RELEASE_TAG \ + dist/${{ env.DEB_NAME }} diff --git a/.gitignore b/.gitignore index 30933fef..77796548 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,10 @@ src/vdf_client src/1weso_test src/2weso_test src/prover_test +src/emu_hw_test +src/hw_test +src/emu_hw_vdf_client +src/hw_vdf_client /verifier /verifier_test /build/* @@ -33,6 +37,9 @@ src/prover_test *.o *.s +# external library +/src/hw/libft4222 + # pyenv .python-version .eggs diff --git a/README_ASIC.md b/README_ASIC.md new file mode 100644 index 00000000..7a925f06 --- /dev/null +++ b/README_ASIC.md @@ -0,0 +1,76 @@ +# ASIC timelord user guide + +## Initial setup + +Download and unpack LibFT4222 library: +```bash +# in chiavdf directory +wget https://ftdichip.com/wp-content/uploads/2022/06/libft4222-linux-1.4.4.170.tgz +mkdir src/hw/libft4222 +tar -C src/hw/libft4222 -xf libft4222-linux-1.4.4.170.tgz +ln -s libft4222.so.1.4.4.170 src/hw/libft4222/build-x86_64/libft4222.so +``` + +Build binaries: +```bash +cd src +make -f Makefile.vdf-client emu_hw_test hw_test emu_hw_vdf_client hw_vdf_client +``` + +Connect the Chia VDF ASIC device and verify that it is detected: +```bash +# in chiavdf/src/ directory +LD_LIBRARY_PATH=hw/libft4222/build-x86_64 ./hw_vdf_client --list +``` + +If the device is shown in the list, check if it's working: +```bash +LD_LIBRARY_PATH=hw/libft4222/build-x86_64 ./hw_test +``` + +Output should contain lines similar to the following: +``` +VDF 0: 1000000 HW iters done in 2s, HW speed: 714720 ips +``` + +## Running + +You should have a Chia full node running and synced. + +Start timelord (but not timelord-launcher) in chia-blockchain: +```bash +chia start timelord-only +``` + +Start hardware VDF client (`8000` specifies timelord's port number): +```bash +# in chiavdf/src/ directory +LD_LIBRARY_PATH=hw/libft4222/build-x86_64 ./hw_vdf_client 8000 +``` + +The VDF client accepts a number of options: +``` +Usage: ./hw_vdf_client [OPTIONS] PORT [N_VDFS] +List of options [default, min - max]: + --freq N - set ASIC frequency [1100, 200 - 2200] + --voltage N - set board voltage [0.88, 0.7 - 1.0] + --ip A.B.C.D - timelord IP address [localhost] + Allows connecting to a timelord running on a remote host. Useful when running multiple machines with VDF hardware connecting to a single timelord. + --vdfs-mask N - mask for enabling VDF engines [7, 1 - 7] + The ASIC has 3 VDF engines numbered 0, 1, 2. If not running all 3 engines, the mask can be specified to enable specific engines. It must be the result of bitwise OR of the engine bits (1, 2, 4 for engines 0, 1, 2). + --vdf-threads N - number of software threads per VDF engine [4, 2 - 64] + Number of software threads computing intermediate values and proofs per VDF engine. + --proof-threads N - number of proof threads per VDF engine + Number of software threads only computing proofs per VDF engine. Must be less than --vdf-threads. + --auto-freq-period N - auto-adjust frequency every N seconds [0, 10 - inf] + --list - list available devices and exit +``` + +## Shutting down + +Stop timelord: +```bash +chia stop timelord-only +``` + +Stop the VDF client by pressing Control-C or killing the process with `SIGTERM`. diff --git a/assets/deb/control.j2 b/assets/deb/control.j2 new file mode 100644 index 00000000..078312db --- /dev/null +++ b/assets/deb/control.j2 @@ -0,0 +1,6 @@ +Package: chiavdf-hw +Version: {{ INSTALLER_VERSION }} +Architecture: {{ PLATFORM }} +Maintainer: Chia Network Inc +Description: Hardware VDF Client +Depends: libgmp-dev, libboost-system-dev diff --git a/src/Makefile.vdf-client b/src/Makefile.vdf-client index 236a214d..4376142f 100644 --- a/src/Makefile.vdf-client +++ b/src/Makefile.vdf-client @@ -6,14 +6,14 @@ else NOPIE = -no-pie endif -LDFLAGS += -flto $(NOPIE) +LDFLAGS += -flto $(NOPIE) -g LDLIBS += -lgmpxx -lgmp -lboost_system -pthread CXXFLAGS += -flto -std=c++1z -D VDF_MODE=0 -D FAST_MACHINE=1 -pthread $(NOPIE) -fvisibility=hidden ifeq ($(UNAME),Darwin) CXXFLAGS += -D CHIAOSX=1 endif -OPT_CFLAGS = -O3 +OPT_CFLAGS = -O3 -g ifneq ($(ASAN),) LDFLAGS += -fsanitize=address -fsanitize=undefined @@ -27,15 +27,16 @@ endif .PHONY: all clean -all: vdf_client prover_test 1weso_test 2weso_test vdf_bench +BINS = vdf_client prover_test 1weso_test 2weso_test vdf_bench +all: $(BINS) clean: - rm -f *.o vdf_client prover_test 1weso_test 2weso_test compile_asm vdf_bench + rm -f *.o hw/*.o $(BINS) compile_asm emu_hw_test hw_test hw_vdf_client emu_hw_vdf_client -vdf_client vdf_bench prover_test 1weso_test 2weso_test avx512_test: %: %.o lzcnt.o asm_compiled.o avx2_asm_compiled.o avx512_asm_compiled.o +$(BINS) avx512_test: %: %.o lzcnt.o asm_compiled.o avx2_asm_compiled.o avx512_asm_compiled.o $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) -vdf_client.o vdf_bench.o prover_test.o 1weso_test.o 2weso_test.o avx512_test.o: CXXFLAGS += $(OPT_CFLAGS) +$(addsuffix .o,$(BINS)) avx512_test.o: CXXFLAGS += $(OPT_CFLAGS) lzcnt.o: refcode/lzcnt.c $(CC) -c refcode/lzcnt.c @@ -51,3 +52,21 @@ avx512_asm_compiled.s: compile_asm compile_asm: compile_asm.o $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +HW_OBJS = $(addprefix hw/,hw_util.o hw_proof.o hw_interface.o chia_driver.o ftdi_driver.o vdf_driver.o pll_freqs.o) vdf_base.o lzcnt.o +EMU_OBJS = hw/emu_funcs.o hw/emu_runner.o +HW_LIB = hw/libft4222/build-x86_64/libft4222.so + +hw_test: hw/hw_test.o $(HW_OBJS) $(HW_LIB) hw/real_hw.o + $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +emu_hw_test: hw/hw_test.o $(HW_OBJS) $(EMU_OBJS) + $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +hw_vdf_client: hw/hw_vdf_client.o $(HW_OBJS) $(HW_LIB) hw/real_hw.o + $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +emu_hw_vdf_client: hw/hw_vdf_client.o $(HW_OBJS) $(EMU_OBJS) + $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +hw/hw_test.o hw/hw_vdf_client.o $(HW_OBJS) $(EMU_OBJS): CXXFLAGS += -I. -Ihw -Ihw/libft4222 $(OPT_CFLAGS) -Wall diff --git a/src/Reducer.h b/src/Reducer.h index dc8d7dfa..fd040f50 100644 --- a/src/Reducer.h +++ b/src/Reducer.h @@ -64,7 +64,7 @@ class alignas(64) Reducer { /** * @brief run - runs reduction algorithm for cg context params */ - inline void run() { + void run() { while (!isReduced()) { int_fast64_t a, b, c; { @@ -229,7 +229,7 @@ bool bLZCHasHW=false; // The condition (abs(v_) | abs(x_)) <= THRESH protects against // overflow - below_threshold = (abs(v_) | abs(x_)) <= THRESH ? 1 : 0; + below_threshold = (labs(v_) | labs(x_)) <= THRESH ? 1 : 0; } while (below_threshold && a > c && c > 0); if (below_threshold) { diff --git a/src/bqfc.c b/src/bqfc.c index 54fa8d75..c277b48e 100644 --- a/src/bqfc.c +++ b/src/bqfc.c @@ -161,7 +161,7 @@ enum BQFC_FLAGS { */ int bqfc_serialize_only(uint8_t *out_str, const struct qfb_c *c, size_t d_bits) { - size_t offset, bytes, size, g_size; + size_t offset, g_size; d_bits = (d_bits + 31) & ~(size_t)31; diff --git a/src/bqfc.h b/src/bqfc.h index 44217c6b..bccdaa98 100644 --- a/src/bqfc.h +++ b/src/bqfc.h @@ -27,6 +27,6 @@ int bqfc_serialize_only(uint8_t *out_str, const struct qfb_c *c, size_t d_bits); int bqfc_deserialize_only(struct qfb_c *out_c, const uint8_t *str, size_t d_bits); int bqfc_serialize(uint8_t *out_str, mpz_t a, mpz_t b, size_t d_bits); -int bqfc_deserialize(mpz_t out_a, mpz_t out_b, const mpz_t D, const uint8_t *str, size_t d_bits); +int bqfc_deserialize(mpz_t out_a, mpz_t out_b, const mpz_t D, const uint8_t *str, size_t size, size_t d_bits); #endif // BQFC_H diff --git a/src/hw/chia_driver.cpp b/src/hw/chia_driver.cpp new file mode 100644 index 00000000..6752980c --- /dev/null +++ b/src/hw/chia_driver.cpp @@ -0,0 +1,39 @@ +#include "chia_driver.hpp" + +void ChiaDriver::SerializeJob(uint8_t *buf, + uint32_t job_id, + uint64_t iteration_count, + mpz_t a, + mpz_t f, + mpz_t d, + mpz_t l) { + size_t offset = 0; + const size_t reg_size = REG_BYTES; + offset += write_bytes(reg_size, offset, buf, job_id); + offset += write_bytes(2 * reg_size, offset, buf, iteration_count); + offset += write_bytes(reg_size * CHIA_VDF_CMD_A_MULTIREG_COUNT, + offset, buf, a, NUM_2X_COEFFS); + offset += write_bytes(reg_size * CHIA_VDF_CMD_F_MULTIREG_COUNT, + offset, buf, f, NUM_2X_COEFFS); + offset += write_bytes(reg_size * CHIA_VDF_CMD_D_MULTIREG_COUNT, + offset, buf, d, NUM_4X_COEFFS); + offset += write_bytes(reg_size * CHIA_VDF_CMD_L_MULTIREG_COUNT, + offset, buf, l, NUM_1X_COEFFS); + // The last word is 0x1 to start the job + offset += write_bytes(reg_size, offset, buf, (uint32_t)0x1); +} + +void ChiaDriver::DeserializeJob(uint8_t *buf, + uint32_t &job_id, + uint64_t &iteration_count, + mpz_t a, + mpz_t f) { + size_t offset = 0; + const size_t reg_size = REG_BYTES; + offset += read_bytes(reg_size, offset, buf, job_id); + offset += read_bytes(2 * reg_size, offset, buf, iteration_count); + offset += read_bytes(reg_size * CHIA_VDF_STATUS_A_MULTIREG_COUNT, + offset, buf, a, NUM_2X_COEFFS); + offset += read_bytes(reg_size * CHIA_VDF_STATUS_F_MULTIREG_COUNT, + offset, buf, f, NUM_2X_COEFFS); +} diff --git a/src/hw/chia_driver.hpp b/src/hw/chia_driver.hpp new file mode 100644 index 00000000..2e24452a --- /dev/null +++ b/src/hw/chia_driver.hpp @@ -0,0 +1,44 @@ +#ifndef CHIA_DRIVER_HPP +#define CHIA_DRIVER_HPP + +#include + +#include "vdf_driver.hpp" +#include "chia_registers.hpp" + +class ChiaDriver : public VdfDriver { +public: + const static unsigned NUM_1X_COEFFS = 18; + const static unsigned NUM_2X_COEFFS = 34; + const static unsigned NUM_3X_COEFFS = 52; + const static unsigned NUM_4X_COEFFS = 68; + + ChiaDriver() : + VdfDriver(16 /*WORD_BITS*/, 19 /*REDUNDANT_BITS*/, true) { + } + + virtual size_t CmdSize() { + return (CHIA_VDF_CMD_START_REG_OFFSET - + CHIA_VDF_CMD_JOB_ID_REG_OFFSET + REG_BYTES); + } + + virtual size_t StatusSize() { + return (CHIA_VDF_STATUS_END_REG_OFFSET - + CHIA_VDF_STATUS_ITER_0_REG_OFFSET); + } + + void SerializeJob(uint8_t *buf, + uint32_t job_id, + uint64_t iteration_count, + mpz_t a, + mpz_t f, + mpz_t d, + mpz_t l); + + void DeserializeJob(uint8_t *buf, + uint32_t &job_id, + uint64_t &iteration_count, + mpz_t a, + mpz_t f); +}; +#endif diff --git a/src/hw/chia_registers.hpp b/src/hw/chia_registers.hpp new file mode 100644 index 00000000..fce7c59f --- /dev/null +++ b/src/hw/chia_registers.hpp @@ -0,0 +1,656 @@ +// Generated register defines for chia_vdf +#ifndef _CHIA_VDF_REG_DEFS_ +#define _CHIA_VDF_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif +// Register width +#define CHIA_VDF_PARAM_REG_WIDTH 32 + +// Control clocking and reset of the squaring engine +#define CHIA_VDF_CONTROL_REG_OFFSET 0x100000 +#define CHIA_VDF_CONTROL_REG_RESVAL 0x10 +#define CHIA_VDF_CONTROL_CLK_ENABLE_BIT 0 +#define CHIA_VDF_CONTROL_RESET_BIT 4 +#define CHIA_VDF_CONTROL_DIS_CG_GCD_BIT 8 +#define CHIA_VDF_CONTROL_DIS_CG_GCDP_BIT 9 +#define CHIA_VDF_CONTROL_DIS_CG_RECIP_BIT 10 +#define CHIA_VDF_CONTROL_DIS_CG_DIV_BIT 11 +#define CHIA_VDF_CONTROL_DIS_CG_MUL_BIT 12 +#define CHIA_VDF_CONTROL_DIS_CG_RECIP_MUL_BIT 13 +#define CHIA_VDF_CONTROL_DIS_CG_DIV_MUL_BIT 14 + +// Identifier for job being loaded into engine +#define CHIA_VDF_CMD_JOB_ID_REG_OFFSET 0x101000 +#define CHIA_VDF_CMD_JOB_ID_REG_RESVAL 0x0 + +// Number of squaring operations in job (common parameters) +#define CHIA_VDF_CMD_ITER_COUNT_CMD_ITER_COUNT_FIELD_WIDTH 32 +#define CHIA_VDF_CMD_ITER_COUNT_CMD_ITER_COUNT_FIELDS_PER_REG 1 +#define CHIA_VDF_CMD_ITER_COUNT_MULTIREG_COUNT 2 + +// Number of squaring operations in job +#define CHIA_VDF_CMD_ITER_COUNT_0_REG_OFFSET 0x101004 +#define CHIA_VDF_CMD_ITER_COUNT_0_REG_RESVAL 0x0 + +// Number of squaring operations in job +#define CHIA_VDF_CMD_ITER_COUNT_1_REG_OFFSET 0x101008 +#define CHIA_VDF_CMD_ITER_COUNT_1_REG_RESVAL 0x0 + +// A input (common parameters) +#define CHIA_VDF_CMD_A_CMD_A_FIELD_WIDTH 32 +#define CHIA_VDF_CMD_A_CMD_A_FIELDS_PER_REG 1 +#define CHIA_VDF_CMD_A_MULTIREG_COUNT 21 + +// A input +#define CHIA_VDF_CMD_A_0_REG_OFFSET 0x10100c +#define CHIA_VDF_CMD_A_0_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_1_REG_OFFSET 0x101010 +#define CHIA_VDF_CMD_A_1_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_2_REG_OFFSET 0x101014 +#define CHIA_VDF_CMD_A_2_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_3_REG_OFFSET 0x101018 +#define CHIA_VDF_CMD_A_3_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_4_REG_OFFSET 0x10101c +#define CHIA_VDF_CMD_A_4_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_5_REG_OFFSET 0x101020 +#define CHIA_VDF_CMD_A_5_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_6_REG_OFFSET 0x101024 +#define CHIA_VDF_CMD_A_6_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_7_REG_OFFSET 0x101028 +#define CHIA_VDF_CMD_A_7_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_8_REG_OFFSET 0x10102c +#define CHIA_VDF_CMD_A_8_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_9_REG_OFFSET 0x101030 +#define CHIA_VDF_CMD_A_9_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_10_REG_OFFSET 0x101034 +#define CHIA_VDF_CMD_A_10_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_11_REG_OFFSET 0x101038 +#define CHIA_VDF_CMD_A_11_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_12_REG_OFFSET 0x10103c +#define CHIA_VDF_CMD_A_12_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_13_REG_OFFSET 0x101040 +#define CHIA_VDF_CMD_A_13_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_14_REG_OFFSET 0x101044 +#define CHIA_VDF_CMD_A_14_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_15_REG_OFFSET 0x101048 +#define CHIA_VDF_CMD_A_15_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_16_REG_OFFSET 0x10104c +#define CHIA_VDF_CMD_A_16_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_17_REG_OFFSET 0x101050 +#define CHIA_VDF_CMD_A_17_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_18_REG_OFFSET 0x101054 +#define CHIA_VDF_CMD_A_18_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_19_REG_OFFSET 0x101058 +#define CHIA_VDF_CMD_A_19_REG_RESVAL 0x0 + +// A input +#define CHIA_VDF_CMD_A_20_REG_OFFSET 0x10105c +#define CHIA_VDF_CMD_A_20_REG_RESVAL 0x0 + +// F input (common parameters) +#define CHIA_VDF_CMD_F_CMD_F_FIELD_WIDTH 32 +#define CHIA_VDF_CMD_F_CMD_F_FIELDS_PER_REG 1 +#define CHIA_VDF_CMD_F_MULTIREG_COUNT 21 + +// F input +#define CHIA_VDF_CMD_F_0_REG_OFFSET 0x101060 +#define CHIA_VDF_CMD_F_0_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_1_REG_OFFSET 0x101064 +#define CHIA_VDF_CMD_F_1_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_2_REG_OFFSET 0x101068 +#define CHIA_VDF_CMD_F_2_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_3_REG_OFFSET 0x10106c +#define CHIA_VDF_CMD_F_3_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_4_REG_OFFSET 0x101070 +#define CHIA_VDF_CMD_F_4_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_5_REG_OFFSET 0x101074 +#define CHIA_VDF_CMD_F_5_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_6_REG_OFFSET 0x101078 +#define CHIA_VDF_CMD_F_6_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_7_REG_OFFSET 0x10107c +#define CHIA_VDF_CMD_F_7_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_8_REG_OFFSET 0x101080 +#define CHIA_VDF_CMD_F_8_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_9_REG_OFFSET 0x101084 +#define CHIA_VDF_CMD_F_9_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_10_REG_OFFSET 0x101088 +#define CHIA_VDF_CMD_F_10_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_11_REG_OFFSET 0x10108c +#define CHIA_VDF_CMD_F_11_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_12_REG_OFFSET 0x101090 +#define CHIA_VDF_CMD_F_12_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_13_REG_OFFSET 0x101094 +#define CHIA_VDF_CMD_F_13_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_14_REG_OFFSET 0x101098 +#define CHIA_VDF_CMD_F_14_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_15_REG_OFFSET 0x10109c +#define CHIA_VDF_CMD_F_15_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_16_REG_OFFSET 0x1010a0 +#define CHIA_VDF_CMD_F_16_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_17_REG_OFFSET 0x1010a4 +#define CHIA_VDF_CMD_F_17_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_18_REG_OFFSET 0x1010a8 +#define CHIA_VDF_CMD_F_18_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_19_REG_OFFSET 0x1010ac +#define CHIA_VDF_CMD_F_19_REG_RESVAL 0x0 + +// F input +#define CHIA_VDF_CMD_F_20_REG_OFFSET 0x1010b0 +#define CHIA_VDF_CMD_F_20_REG_RESVAL 0x0 + +// D input (common parameters) +#define CHIA_VDF_CMD_D_CMD_D_FIELD_WIDTH 32 +#define CHIA_VDF_CMD_D_CMD_D_FIELDS_PER_REG 1 +#define CHIA_VDF_CMD_D_MULTIREG_COUNT 41 + +// D input +#define CHIA_VDF_CMD_D_0_REG_OFFSET 0x1010b4 +#define CHIA_VDF_CMD_D_0_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_1_REG_OFFSET 0x1010b8 +#define CHIA_VDF_CMD_D_1_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_2_REG_OFFSET 0x1010bc +#define CHIA_VDF_CMD_D_2_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_3_REG_OFFSET 0x1010c0 +#define CHIA_VDF_CMD_D_3_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_4_REG_OFFSET 0x1010c4 +#define CHIA_VDF_CMD_D_4_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_5_REG_OFFSET 0x1010c8 +#define CHIA_VDF_CMD_D_5_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_6_REG_OFFSET 0x1010cc +#define CHIA_VDF_CMD_D_6_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_7_REG_OFFSET 0x1010d0 +#define CHIA_VDF_CMD_D_7_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_8_REG_OFFSET 0x1010d4 +#define CHIA_VDF_CMD_D_8_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_9_REG_OFFSET 0x1010d8 +#define CHIA_VDF_CMD_D_9_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_10_REG_OFFSET 0x1010dc +#define CHIA_VDF_CMD_D_10_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_11_REG_OFFSET 0x1010e0 +#define CHIA_VDF_CMD_D_11_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_12_REG_OFFSET 0x1010e4 +#define CHIA_VDF_CMD_D_12_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_13_REG_OFFSET 0x1010e8 +#define CHIA_VDF_CMD_D_13_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_14_REG_OFFSET 0x1010ec +#define CHIA_VDF_CMD_D_14_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_15_REG_OFFSET 0x1010f0 +#define CHIA_VDF_CMD_D_15_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_16_REG_OFFSET 0x1010f4 +#define CHIA_VDF_CMD_D_16_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_17_REG_OFFSET 0x1010f8 +#define CHIA_VDF_CMD_D_17_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_18_REG_OFFSET 0x1010fc +#define CHIA_VDF_CMD_D_18_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_19_REG_OFFSET 0x101100 +#define CHIA_VDF_CMD_D_19_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_20_REG_OFFSET 0x101104 +#define CHIA_VDF_CMD_D_20_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_21_REG_OFFSET 0x101108 +#define CHIA_VDF_CMD_D_21_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_22_REG_OFFSET 0x10110c +#define CHIA_VDF_CMD_D_22_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_23_REG_OFFSET 0x101110 +#define CHIA_VDF_CMD_D_23_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_24_REG_OFFSET 0x101114 +#define CHIA_VDF_CMD_D_24_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_25_REG_OFFSET 0x101118 +#define CHIA_VDF_CMD_D_25_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_26_REG_OFFSET 0x10111c +#define CHIA_VDF_CMD_D_26_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_27_REG_OFFSET 0x101120 +#define CHIA_VDF_CMD_D_27_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_28_REG_OFFSET 0x101124 +#define CHIA_VDF_CMD_D_28_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_29_REG_OFFSET 0x101128 +#define CHIA_VDF_CMD_D_29_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_30_REG_OFFSET 0x10112c +#define CHIA_VDF_CMD_D_30_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_31_REG_OFFSET 0x101130 +#define CHIA_VDF_CMD_D_31_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_32_REG_OFFSET 0x101134 +#define CHIA_VDF_CMD_D_32_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_33_REG_OFFSET 0x101138 +#define CHIA_VDF_CMD_D_33_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_34_REG_OFFSET 0x10113c +#define CHIA_VDF_CMD_D_34_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_35_REG_OFFSET 0x101140 +#define CHIA_VDF_CMD_D_35_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_36_REG_OFFSET 0x101144 +#define CHIA_VDF_CMD_D_36_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_37_REG_OFFSET 0x101148 +#define CHIA_VDF_CMD_D_37_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_38_REG_OFFSET 0x10114c +#define CHIA_VDF_CMD_D_38_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_39_REG_OFFSET 0x101150 +#define CHIA_VDF_CMD_D_39_REG_RESVAL 0x0 + +// D input +#define CHIA_VDF_CMD_D_40_REG_OFFSET 0x101154 +#define CHIA_VDF_CMD_D_40_REG_RESVAL 0x0 + +// L input (common parameters) +#define CHIA_VDF_CMD_L_CMD_L_FIELD_WIDTH 32 +#define CHIA_VDF_CMD_L_CMD_L_FIELDS_PER_REG 1 +#define CHIA_VDF_CMD_L_MULTIREG_COUNT 11 + +// L input +#define CHIA_VDF_CMD_L_0_REG_OFFSET 0x101158 +#define CHIA_VDF_CMD_L_0_REG_RESVAL 0x0 + +// L input +#define CHIA_VDF_CMD_L_1_REG_OFFSET 0x10115c +#define CHIA_VDF_CMD_L_1_REG_RESVAL 0x0 + +// L input +#define CHIA_VDF_CMD_L_2_REG_OFFSET 0x101160 +#define CHIA_VDF_CMD_L_2_REG_RESVAL 0x0 + +// L input +#define CHIA_VDF_CMD_L_3_REG_OFFSET 0x101164 +#define CHIA_VDF_CMD_L_3_REG_RESVAL 0x0 + +// L input +#define CHIA_VDF_CMD_L_4_REG_OFFSET 0x101168 +#define CHIA_VDF_CMD_L_4_REG_RESVAL 0x0 + +// L input +#define CHIA_VDF_CMD_L_5_REG_OFFSET 0x10116c +#define CHIA_VDF_CMD_L_5_REG_RESVAL 0x0 + +// L input +#define CHIA_VDF_CMD_L_6_REG_OFFSET 0x101170 +#define CHIA_VDF_CMD_L_6_REG_RESVAL 0x0 + +// L input +#define CHIA_VDF_CMD_L_7_REG_OFFSET 0x101174 +#define CHIA_VDF_CMD_L_7_REG_RESVAL 0x0 + +// L input +#define CHIA_VDF_CMD_L_8_REG_OFFSET 0x101178 +#define CHIA_VDF_CMD_L_8_REG_RESVAL 0x0 + +// L input +#define CHIA_VDF_CMD_L_9_REG_OFFSET 0x10117c +#define CHIA_VDF_CMD_L_9_REG_RESVAL 0x0 + +// L input +#define CHIA_VDF_CMD_L_10_REG_OFFSET 0x101180 +#define CHIA_VDF_CMD_L_10_REG_RESVAL 0x0 + +// Write to start engine +#define CHIA_VDF_CMD_START_REG_OFFSET 0x101184 +#define CHIA_VDF_CMD_START_REG_RESVAL 0x0 +#define CHIA_VDF_CMD_START_START_BIT 0 + +// Identifier of job for which status is being reported +#define CHIA_VDF_STATUS_JOB_ID_REG_OFFSET 0x102000 +#define CHIA_VDF_STATUS_JOB_ID_REG_RESVAL 0x0 + +// Iteration within job for which status is being reported (common +// parameters) +#define CHIA_VDF_STATUS_ITER_STATUS_ITER_FIELD_WIDTH 32 +#define CHIA_VDF_STATUS_ITER_STATUS_ITER_FIELDS_PER_REG 1 +#define CHIA_VDF_STATUS_ITER_MULTIREG_COUNT 2 + +// Iteration within job for which status is being reported +#define CHIA_VDF_STATUS_ITER_0_REG_OFFSET 0x102004 +#define CHIA_VDF_STATUS_ITER_0_REG_RESVAL 0x0 + +// Iteration within job for which status is being reported +#define CHIA_VDF_STATUS_ITER_1_REG_OFFSET 0x102008 +#define CHIA_VDF_STATUS_ITER_1_REG_RESVAL 0x0 + +// A result. (common parameters) +#define CHIA_VDF_STATUS_A_STATUS_A_FIELD_WIDTH 32 +#define CHIA_VDF_STATUS_A_STATUS_A_FIELDS_PER_REG 1 +#define CHIA_VDF_STATUS_A_MULTIREG_COUNT 21 + +// A result. +#define CHIA_VDF_STATUS_A_0_REG_OFFSET 0x10200c +#define CHIA_VDF_STATUS_A_0_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_1_REG_OFFSET 0x102010 +#define CHIA_VDF_STATUS_A_1_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_2_REG_OFFSET 0x102014 +#define CHIA_VDF_STATUS_A_2_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_3_REG_OFFSET 0x102018 +#define CHIA_VDF_STATUS_A_3_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_4_REG_OFFSET 0x10201c +#define CHIA_VDF_STATUS_A_4_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_5_REG_OFFSET 0x102020 +#define CHIA_VDF_STATUS_A_5_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_6_REG_OFFSET 0x102024 +#define CHIA_VDF_STATUS_A_6_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_7_REG_OFFSET 0x102028 +#define CHIA_VDF_STATUS_A_7_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_8_REG_OFFSET 0x10202c +#define CHIA_VDF_STATUS_A_8_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_9_REG_OFFSET 0x102030 +#define CHIA_VDF_STATUS_A_9_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_10_REG_OFFSET 0x102034 +#define CHIA_VDF_STATUS_A_10_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_11_REG_OFFSET 0x102038 +#define CHIA_VDF_STATUS_A_11_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_12_REG_OFFSET 0x10203c +#define CHIA_VDF_STATUS_A_12_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_13_REG_OFFSET 0x102040 +#define CHIA_VDF_STATUS_A_13_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_14_REG_OFFSET 0x102044 +#define CHIA_VDF_STATUS_A_14_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_15_REG_OFFSET 0x102048 +#define CHIA_VDF_STATUS_A_15_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_16_REG_OFFSET 0x10204c +#define CHIA_VDF_STATUS_A_16_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_17_REG_OFFSET 0x102050 +#define CHIA_VDF_STATUS_A_17_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_18_REG_OFFSET 0x102054 +#define CHIA_VDF_STATUS_A_18_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_19_REG_OFFSET 0x102058 +#define CHIA_VDF_STATUS_A_19_REG_RESVAL 0x0 + +// A result. +#define CHIA_VDF_STATUS_A_20_REG_OFFSET 0x10205c +#define CHIA_VDF_STATUS_A_20_REG_RESVAL 0x0 + +// F result. (common parameters) +#define CHIA_VDF_STATUS_F_STATUS_F_FIELD_WIDTH 32 +#define CHIA_VDF_STATUS_F_STATUS_F_FIELDS_PER_REG 1 +#define CHIA_VDF_STATUS_F_MULTIREG_COUNT 21 + +// F result. +#define CHIA_VDF_STATUS_F_0_REG_OFFSET 0x102060 +#define CHIA_VDF_STATUS_F_0_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_1_REG_OFFSET 0x102064 +#define CHIA_VDF_STATUS_F_1_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_2_REG_OFFSET 0x102068 +#define CHIA_VDF_STATUS_F_2_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_3_REG_OFFSET 0x10206c +#define CHIA_VDF_STATUS_F_3_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_4_REG_OFFSET 0x102070 +#define CHIA_VDF_STATUS_F_4_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_5_REG_OFFSET 0x102074 +#define CHIA_VDF_STATUS_F_5_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_6_REG_OFFSET 0x102078 +#define CHIA_VDF_STATUS_F_6_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_7_REG_OFFSET 0x10207c +#define CHIA_VDF_STATUS_F_7_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_8_REG_OFFSET 0x102080 +#define CHIA_VDF_STATUS_F_8_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_9_REG_OFFSET 0x102084 +#define CHIA_VDF_STATUS_F_9_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_10_REG_OFFSET 0x102088 +#define CHIA_VDF_STATUS_F_10_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_11_REG_OFFSET 0x10208c +#define CHIA_VDF_STATUS_F_11_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_12_REG_OFFSET 0x102090 +#define CHIA_VDF_STATUS_F_12_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_13_REG_OFFSET 0x102094 +#define CHIA_VDF_STATUS_F_13_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_14_REG_OFFSET 0x102098 +#define CHIA_VDF_STATUS_F_14_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_15_REG_OFFSET 0x10209c +#define CHIA_VDF_STATUS_F_15_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_16_REG_OFFSET 0x1020a0 +#define CHIA_VDF_STATUS_F_16_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_17_REG_OFFSET 0x1020a4 +#define CHIA_VDF_STATUS_F_17_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_18_REG_OFFSET 0x1020a8 +#define CHIA_VDF_STATUS_F_18_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_19_REG_OFFSET 0x1020ac +#define CHIA_VDF_STATUS_F_19_REG_RESVAL 0x0 + +// F result. +#define CHIA_VDF_STATUS_F_20_REG_OFFSET 0x1020b0 +#define CHIA_VDF_STATUS_F_20_REG_RESVAL 0x0 + +// Dummy register locating the end of the status registers +#define CHIA_VDF_STATUS_END_REG_OFFSET 0x1020b4 +#define CHIA_VDF_STATUS_END_REG_RESVAL 0x0 +#define CHIA_VDF_STATUS_END_STATUS_END_BIT 0 + +// Temporary read/write space for verification +#define CHIA_VDF_RW_REG_OFFSET 0x10fff8 +#define CHIA_VDF_RW_REG_RESVAL 0x0 + +// Mark the end of the address space +#define CHIA_VDF_END_OF_RANGE_REG_OFFSET 0x10fffc +#define CHIA_VDF_END_OF_RANGE_REG_RESVAL 0x0 +#define CHIA_VDF_END_OF_RANGE_MARKER_BIT 0 + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _CHIA_VDF_REG_DEFS_ +// End generated register defines for chia_vdf diff --git a/src/hw/clock.hpp b/src/hw/clock.hpp new file mode 100644 index 00000000..34b12944 --- /dev/null +++ b/src/hw/clock.hpp @@ -0,0 +1,88 @@ +// Generated register defines for clock +#ifndef _CLOCK_REG_DEFS_ +#define _CLOCK_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif +// Register width +#define CLOCK_PARAM_REG_WIDTH 32 + +// PLL control register +#define CLOCK_CONTROL_REG_OFFSET 0x0 +#define CLOCK_CONTROL_REG_RESVAL 0x3 +#define CLOCK_CONTROL_RESET_BIT 0 +#define CLOCK_CONTROL_BYPASS_BIT 1 +#define CLOCK_CONTROL_NEWDIV_BIT 2 +#define CLOCK_CONTROL_USEREF_BIT 3 + +// PLL pre-divider register +#define CLOCK_PRE_DIVIDE_REG_OFFSET 0x4 +#define CLOCK_PRE_DIVIDE_REG_RESVAL 0x0 +#define CLOCK_PRE_DIVIDE_DIVR_MASK 0x3f +#define CLOCK_PRE_DIVIDE_DIVR_OFFSET 0 +#define CLOCK_PRE_DIVIDE_DIVR_FIELD \ + ((bitfield_field32_t) { .mask = CLOCK_PRE_DIVIDE_DIVR_MASK, .index = CLOCK_PRE_DIVIDE_DIVR_OFFSET }) + +// PLL feedback integer divider register +#define CLOCK_FB_DIVIDE_INTEGER_REG_OFFSET 0x8 +#define CLOCK_FB_DIVIDE_INTEGER_REG_RESVAL 0x0 +#define CLOCK_FB_DIVIDE_INTEGER_DIVFI_MASK 0x1ff +#define CLOCK_FB_DIVIDE_INTEGER_DIVFI_OFFSET 0 +#define CLOCK_FB_DIVIDE_INTEGER_DIVFI_FIELD \ + ((bitfield_field32_t) { .mask = CLOCK_FB_DIVIDE_INTEGER_DIVFI_MASK, .index = CLOCK_FB_DIVIDE_INTEGER_DIVFI_OFFSET }) + +// PLL feedback factional divider register +#define CLOCK_FB_DIVIDE_FRACTION_REG_OFFSET 0xc +#define CLOCK_FB_DIVIDE_FRACTION_REG_RESVAL 0x0 +#define CLOCK_FB_DIVIDE_FRACTION_DIVFF_MASK 0xffffff +#define CLOCK_FB_DIVIDE_FRACTION_DIVFF_OFFSET 0 +#define CLOCK_FB_DIVIDE_FRACTION_DIVFF_FIELD \ + ((bitfield_field32_t) { .mask = CLOCK_FB_DIVIDE_FRACTION_DIVFF_MASK, .index = CLOCK_FB_DIVIDE_FRACTION_DIVFF_OFFSET }) + +// PLL post-divider register +#define CLOCK_POST_DIVIDE_REG_OFFSET 0x10 +#define CLOCK_POST_DIVIDE_REG_RESVAL 0x0 +#define CLOCK_POST_DIVIDE_DIVQ_MASK 0x1f +#define CLOCK_POST_DIVIDE_DIVQ_OFFSET 0 +#define CLOCK_POST_DIVIDE_DIVQ_FIELD \ + ((bitfield_field32_t) { .mask = CLOCK_POST_DIVIDE_DIVQ_MASK, .index = CLOCK_POST_DIVIDE_DIVQ_OFFSET }) + +// PLL filter range selection +#define CLOCK_FILTER_RANGE_REG_OFFSET 0x14 +#define CLOCK_FILTER_RANGE_REG_RESVAL 0x0 +#define CLOCK_FILTER_RANGE_RANGE_MASK 0x7 +#define CLOCK_FILTER_RANGE_RANGE_OFFSET 0 +#define CLOCK_FILTER_RANGE_RANGE_FIELD \ + ((bitfield_field32_t) { .mask = CLOCK_FILTER_RANGE_RANGE_MASK, .index = CLOCK_FILTER_RANGE_RANGE_OFFSET }) + +// PLL spread spectrum controls +#define CLOCK_SPREAD_SPECTRUM_REG_OFFSET 0x18 +#define CLOCK_SPREAD_SPECTRUM_REG_RESVAL 0x0 +#define CLOCK_SPREAD_SPECTRUM_ENABLE_BIT 0 +#define CLOCK_SPREAD_SPECTRUM_DOWN_SPREAD_BIT 1 +#define CLOCK_SPREAD_SPECTRUM_MODULATION_DEPTH_MASK 0x7 +#define CLOCK_SPREAD_SPECTRUM_MODULATION_DEPTH_OFFSET 4 +#define CLOCK_SPREAD_SPECTRUM_MODULATION_DEPTH_FIELD \ + ((bitfield_field32_t) { .mask = CLOCK_SPREAD_SPECTRUM_MODULATION_DEPTH_MASK, .index = CLOCK_SPREAD_SPECTRUM_MODULATION_DEPTH_OFFSET }) +#define CLOCK_SPREAD_SPECTRUM_MODULATION_FREQUENCY_MASK 0xf +#define CLOCK_SPREAD_SPECTRUM_MODULATION_FREQUENCY_OFFSET 8 +#define CLOCK_SPREAD_SPECTRUM_MODULATION_FREQUENCY_FIELD \ + ((bitfield_field32_t) { .mask = CLOCK_SPREAD_SPECTRUM_MODULATION_FREQUENCY_MASK, .index = CLOCK_SPREAD_SPECTRUM_MODULATION_FREQUENCY_OFFSET }) + +// PLL status register +#define CLOCK_STATUS_REG_OFFSET 0x1c +#define CLOCK_STATUS_REG_RESVAL 0x0 +#define CLOCK_STATUS_LOCK_BIT 0 +#define CLOCK_STATUS_DIVACK_BIT 1 + +// Mark the end of the address space +#define CLOCK_END_OF_RANGE_REG_OFFSET 0xfffc +#define CLOCK_END_OF_RANGE_REG_RESVAL 0x0 +#define CLOCK_END_OF_RANGE_MARKER_BIT 0 + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _CLOCK_REG_DEFS_ +// End generated register defines for clock diff --git a/src/hw/emu_funcs.cpp b/src/hw/emu_funcs.cpp new file mode 100644 index 00000000..8f6cb0ca --- /dev/null +++ b/src/hw/emu_funcs.cpp @@ -0,0 +1,146 @@ +#include "emu_runner.hpp" +#include "libft4222.h" + +//#include "verifier.h" +//#include "bit_manipulation.h" +//#include "alloc.hpp" +//#include "double_utility.h" + +#include +#include +#include + +int chia_vdf_is_emu = 1; + +#define EMU_LOC_ID 0x88888 +#define SPI_FT_BASE 0x100 +#define GPIO_FT_BASE 0x200 + +FTD2XX_API FT_STATUS WINAPI FT_CreateDeviceInfoList(LPDWORD lpdwNumDevs) +{ + *lpdwNumDevs = 1; + return 0; +} + +FTD2XX_API FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, LPDWORD lpdwNumDevs) +{ + *lpdwNumDevs = 1; + + pDest->Type = FT_DEVICE_4222H_0; + strcpy(pDest->Description, "A"); + pDest->LocId = EMU_LOC_ID; + + return 0; +} + +FTD2XX_API FT_STATUS WINAPI FT_OpenEx(PVOID pArg1, DWORD Flags, FT_HANDLE *pHandle) +{ + if ((uintptr_t)pArg1 == EMU_LOC_ID) { + *pHandle = (void *)SPI_FT_BASE; + } else if ((uintptr_t)pArg1 == EMU_LOC_ID + 3) { + *pHandle = (void *)GPIO_FT_BASE; + } else { + return FT4222_DEVICE_NOT_FOUND; + } + + return 0; +} + +LIBFT4222_API FT4222_STATUS FT4222_SPIMaster_Init(FT_HANDLE ftHandle, FT4222_SPIMode ioLine, FT4222_SPIClock clock, FT4222_SPICPOL cpol, FT4222_SPICPHA cpha, uint8 ssoMap) +{ + return FT4222_OK; +} + +LIBFT4222_API FT4222_STATUS FT4222_SPIMaster_SetCS(FT_HANDLE ftHandle, SPI_ChipSelect cs) +{ + return FT4222_OK; +} + +LIBFT4222_API FT4222_STATUS FT4222_SetClock(FT_HANDLE ftHandle, FT4222_ClockRate clk) +{ + return FT4222_OK; +} + +FTD2XX_API FT_STATUS WINAPI FT_SetUSBParameters(FT_HANDLE ftHandle, ULONG ulInTransferSize, ULONG ulOutTransferSize) +{ + return 0; +} + +LIBFT4222_API FT4222_STATUS FT4222_SPI_SetDrivingStrength(FT_HANDLE ftHandle, SPI_DrivingStrength clkStrength, SPI_DrivingStrength ioStrength, SPI_DrivingStrength ssoStrength) +{ + return FT4222_OK; +} + +LIBFT4222_API FT4222_STATUS FT4222_GPIO_Init(FT_HANDLE ftHandle, GPIO_Dir gpioDir[4]) +{ + return FT4222_OK; +} + +LIBFT4222_API FT4222_STATUS FT4222_SetSuspendOut(FT_HANDLE ftHandle, BOOL enable) +{ + return FT4222_OK; +} + +LIBFT4222_API FT4222_STATUS FT4222_SetWakeUpInterrupt(FT_HANDLE ftHandle, BOOL enable) +{ + return FT4222_OK; +} + +LIBFT4222_API FT4222_STATUS FT4222_UnInitialize(FT_HANDLE ftHandle) +{ + return FT4222_OK; +} + +FTD2XX_API FT_STATUS WINAPI FT_Close(FT_HANDLE ftHandle) +{ + return 0; +} + +LIBFT4222_API FT4222_STATUS FT4222_SPIMaster_MultiReadWrite(FT_HANDLE ftHandle, uint8* readBuffer, uint8* writeBuffer, uint8 singleWriteBytes, uint16 multiWriteBytes, uint16 multiReadBytes, uint32* sizeOfRead) +{ + int ret = emu_do_io(writeBuffer, multiWriteBytes, readBuffer, multiReadBytes); + if (!ret) { + *sizeOfRead = multiReadBytes; + return FT4222_OK; + } else { + return FT4222_IO_ERROR; + } +} + +LIBFT4222_API FT4222_STATUS FT4222_GPIO_Write(FT_HANDLE ftHandle, GPIO_Port portNum, BOOL bValue) +{ + return FT4222_OK; +} + +LIBFT4222_API FT4222_STATUS FT4222_GPIO_Read(FT_HANDLE ftHandle, GPIO_Port portNum, BOOL* value) +{ + return FT4222_OK; +} + +LIBFT4222_API FT4222_STATUS FT4222_I2CMaster_Init(FT_HANDLE ftHandle, uint32 kbps) +{ + return FT4222_OK; +} + +LIBFT4222_API FT4222_STATUS FT4222_I2CMaster_ReadEx(FT_HANDLE ftHandle, uint16 deviceAddress, uint8 flag, uint8* buffer, uint16 bufferSize, uint16* sizeTransferred) +{ + int ret = emu_do_io_i2c(buffer, bufferSize, deviceAddress, 1); + if (!ret) { + *sizeTransferred = bufferSize; + return FT4222_OK; + } else { + return FT4222_IO_ERROR; + } +} + +LIBFT4222_API FT4222_STATUS FT4222_I2CMaster_WriteEx(FT_HANDLE ftHandle, uint16 deviceAddress, uint8 flag, uint8* buffer, uint16 bufferSize, uint16* sizeTransferred) +{ + int ret = emu_do_io_i2c(buffer, bufferSize, deviceAddress, 0); + if (!ret) { + *sizeTransferred = bufferSize; + return FT4222_OK; + } else { + return FT4222_IO_ERROR; + } +} diff --git a/src/hw/emu_runner.cpp b/src/hw/emu_runner.cpp new file mode 100644 index 00000000..356365ac --- /dev/null +++ b/src/hw/emu_runner.cpp @@ -0,0 +1,317 @@ +#include "chia_driver.hpp" +#include "vdf_base.hpp" +#include "clock.hpp" +#include "hw_util.hpp" + +#include +#include +#include +#include +#include + +#include +#include + +#define N_VDFS 3 + +struct job_reg_set { + uint32_t id; + uint32_t iters[2]; + uint32_t a[21], f[21], d[41], l[11]; + uint32_t start_flag; + uint32_t padding[30]; +}; + +static struct job_reg_set g_job_regs[N_VDFS]; + +struct job_status { + uint32_t id; + uint32_t iters[2]; + uint32_t a[21], f[21]; + //uint32_t padding[19]; +}; + +static struct job_status g_status_regs[N_VDFS]; +static uint32_t g_pll_regs[8]; + +static int g_error_prob = -1; + +struct job_state { + uint64_t cur_iter; + uint64_t target_iter; + integer d, l; + form qf; + bool init_done; + bool stopping; + bool running; + bool error; + ChiaDriver *drv; + std::mutex mtx; +}; + +static struct job_state *states[N_VDFS]; + +void init_state(struct job_state *st, struct job_reg_set *r) +{ + integer a, f; + st->drv = new ChiaDriver(); + + st->cur_iter = 0; + st->drv->read_bytes(sizeof(r->iters), 0, (uint8_t *)r->iters, st->target_iter); + + st->drv->read_bytes(sizeof(r->a), 0, (uint8_t *)r->a, a.impl, st->drv->NUM_2X_COEFFS); + st->drv->read_bytes(sizeof(r->f), 0, (uint8_t *)r->f, f.impl, st->drv->NUM_2X_COEFFS); + st->drv->read_bytes(sizeof(r->d), 0, (uint8_t *)r->d, st->d.impl, st->drv->NUM_4X_COEFFS); + st->drv->read_bytes(sizeof(r->l), 0, (uint8_t *)r->l, st->l.impl, st->drv->NUM_1X_COEFFS); + + st->qf = form::from_abd(a, f, st->d); + st->init_done = true; + st->stopping = false; +} + +void clear_state(struct job_state *st) +{ + if (st->init_done) { + delete st->drv; + st->init_done = false; + } +} + +void run_job(int i) +{ + struct job_state *st = states[i]; + PulmarkReducer reducer; + form qf2; + + LOG_INFO("Emu %d: Starting run for %lu iters", i, st->target_iter); + + st->error = false; + st->running = true; + while (!st->stopping && st->cur_iter < st->target_iter) { + nudupl_form(qf2, st->qf, st->d, st->l); + reducer.reduce(qf2); + + if (!(st->cur_iter % 4096)) { + usleep(10); + } + + st->mtx.lock(); + st->cur_iter++; + st->qf = qf2; + st->mtx.unlock(); + } + st->running = false; + LOG_INFO("Emu %d: job ended", i); +} + +void job_thread(int i) +{ + run_job(i); +} + +static void start_job(int i) +{ + while (states[i]->running) { + states[i]->stopping = true; + LOG_INFO("Emu %d: Waiting for the old thread to finish", i); + usleep(1000); + } + clear_state(states[i]); + + LOG_INFO("Emu %d: Starting job", i); + init_state(states[i], &g_job_regs[i]); + std::thread(job_thread, i).detach(); + //usleep(100000); +} + +static void disable_engine(int i) +{ + if (states[i] && states[i]->init_done && !states[i]->stopping) { + LOG_INFO("Emu %d: Disabling engine", i); + states[i]->stopping = true; + } +} + +static void enable_engine(int i) +{ + if (!states[i]) { + states[i] = new job_state; + states[i]->init_done = false; + states[i]->stopping = true; + states[i]->running = false; + srand48(1); + } + if (states[i]->stopping) { + states[i]->stopping = false; + LOG_INFO("Emu %d: Enabling engine", i); + } +} + +void inject_error(struct job_status *stat, struct job_state *st) +{ + int p = g_error_prob; + if (p == -1) { + char *prob = getenv("EMU_ERROR_PROB"); + p = prob ? atoi(prob) : 0; + g_error_prob = p; + } + if (p != 0 && (st->error || (uint32_t)mrand48() % p == 0)) { + // Inject error by messing up 'a' register + stat->a[10] = ~stat->a[10]; + st->error = true; + } +} + +void update_status(struct job_status *stat, struct job_state *st) +{ + if (!st->stopping) { + st->mtx.lock(); + st->drv->write_bytes(sizeof(stat->iters), 0, (uint8_t *)stat->iters, st->cur_iter); + st->drv->write_bytes(sizeof(stat->a), 0, (uint8_t *)stat->a, st->qf.a.impl, st->drv->NUM_2X_COEFFS); + st->drv->write_bytes(sizeof(stat->f), 0, (uint8_t *)stat->f, st->qf.b.impl, st->drv->NUM_2X_COEFFS); + st->mtx.unlock(); + } else { + memset(stat, 0, sizeof(*stat)); + } + + inject_error(stat, st); +} + +void copy_regs(void *dst, void *src, uint32_t size, uint32_t max_size, int32_t offset) +{ + if (offset < 0) { + memset(dst, 0, -offset); + size += offset; + dst = (uint8_t *)dst - offset; + offset = 0; + } + if (size + offset <= max_size) { + memcpy(dst, (uint8_t *)src + offset, size); + } else { + memcpy(dst, (uint8_t *)src + offset, max_size - offset); + memset((uint8_t *)dst + max_size - offset, 0, offset); + } +} + +#define CHIA_VDF_STATUS_SIZE 0xb4 +#define CHIA_VDF_BURST_START 0x300014 +//#define CHIA_VDF_BURST_END 0x300244 +#define CHIA_VDF_JOB_CSR_MULT 0x10000 + +void read_regs(uint32_t addr, uint8_t *buf, uint32_t size) +{ + uint32_t job_status_base = CHIA_VDF_STATUS_JOB_ID_REG_OFFSET; + uint32_t job_status_end = job_status_base + CHIA_VDF_JOB_CSR_MULT * N_VDFS; + + uint32_t burst_start = CHIA_VDF_BURST_START; + uint32_t burst_end = CHIA_VDF_BURST_START + sizeof(g_status_regs); + + for (int i = 0; i < N_VDFS; i++) { + uint32_t job_id_addr = CHIA_VDF_BURST_START + + sizeof(g_status_regs[0]) * i; + uint32_t job_id_addr2 = job_status_base + + CHIA_VDF_JOB_CSR_MULT * i; + + if (!states[i] || !states[i]->init_done) { + continue; + } + + // Reading the job ID register triggers job status update + if ((job_id_addr >= addr && job_id_addr < addr + size) || + (job_id_addr2 >= addr && job_id_addr2 < addr + size)) + { + LOG_DEBUG("Emu: Updating vdf %d", i); + update_status(&g_status_regs[i], states[i]); + } + } + + if (addr + size > job_status_base && addr < job_status_end) { + uint32_t i = (addr - job_status_base) / CHIA_VDF_JOB_CSR_MULT; + int32_t offset = addr - job_status_base - CHIA_VDF_JOB_CSR_MULT * i; + copy_regs(buf, &g_status_regs[i], size, sizeof(g_status_regs[0]), offset); + } else if (addr + size > burst_start && addr < burst_end) { + int32_t offset = addr - burst_start; + copy_regs(buf, g_status_regs, size, sizeof(g_status_regs), offset); + } else if (addr < sizeof(g_pll_regs)) { + copy_regs(buf, g_pll_regs, size, sizeof(g_pll_regs), addr); + } else { + memset(buf, 0, size); + LOG_INFO("Emu: No data at addr=0x%x size=%u", addr, size); + } +} + +#define CMD_SIZE 4 +#define WAIT_CYCLES 4 + +int emu_do_io(uint8_t *buf_in, uint16_t size_in, uint8_t *buf_out, uint16_t size_out) +{ + uint32_t job_control = CHIA_VDF_CONTROL_REG_OFFSET; + uint32_t job_csr = CHIA_VDF_CMD_JOB_ID_REG_OFFSET; + uint32_t addr = (buf_in[1] << 16) | (buf_in[2] << 8) | buf_in[3]; + int i; + + addr <<= 2; + // skip address bytes + buf_in += CMD_SIZE; + size_in -= CMD_SIZE; + LOG_DEBUG("Emu: addr=0x%x in=%hu bytes out=%hu bytes", addr, size_in, size_out); + for (i = 0; i < N_VDFS; i++) { + if (addr >= job_csr && addr < job_csr + sizeof(g_job_regs[0])) { + uint32_t offset = addr - job_csr; + memcpy((uint8_t *)&g_job_regs[i] + offset, buf_in, size_in); + LOG_DEBUG("Emu: offset=0x%x start_flag=0x%x", offset, g_job_regs[i].start_flag); + + if (g_job_regs[i].start_flag & (1 << 24)) { + start_job(i); + g_job_regs[i].start_flag = 0; + } + } + if (addr == job_control) { + uint32_t data; + memcpy(&data, buf_in, 4); + data = ntohl(data); + if (data & (1U << CHIA_VDF_CONTROL_CLK_ENABLE_BIT)) { + enable_engine(i); + } else { + disable_engine(i); + } + } + job_csr += CHIA_VDF_JOB_CSR_MULT; + job_control += CHIA_VDF_JOB_CSR_MULT; + } + + if (!size_in && size_out) { + size_out -= WAIT_CYCLES; + buf_out += WAIT_CYCLES; + + read_regs(addr, buf_out, size_out); + } else if (!size_out && addr < sizeof(g_pll_regs)) { + uint8_t *regs_addr = &((uint8_t *)g_pll_regs)[addr]; + uint32_t status_val = htonl((1U << CLOCK_STATUS_DIVACK_BIT) | + (1U << CLOCK_STATUS_LOCK_BIT)); + + copy_regs(regs_addr, buf_in, size_in, sizeof(g_pll_regs) - addr, 0); + g_pll_regs[CLOCK_STATUS_REG_OFFSET / 4] = status_val; + } + + return 0; +} + +int emu_do_io_i2c(uint8_t *buf, uint16_t size, uint32_t addr, int is_out) +{ + if (is_out) { + memset(buf, 0, size); + } + return 0; +} + +__attribute__((destructor)) void emu_shutdown(void) +{ + for (int i = 0; i < N_VDFS; i++) { + if (states[i]) { + clear_state(states[i]); + delete states[i]; + states[i] = NULL; + } + } +} diff --git a/src/hw/emu_runner.hpp b/src/hw/emu_runner.hpp new file mode 100644 index 00000000..7287f2a7 --- /dev/null +++ b/src/hw/emu_runner.hpp @@ -0,0 +1,4 @@ +#include + +int emu_do_io(uint8_t *buf_in, uint16_t size_in, uint8_t *buf_out, uint16_t size_out); +int emu_do_io_i2c(uint8_t *buf, uint16_t size, uint32_t addr, int is_out); diff --git a/src/hw/ftdi_driver.cpp b/src/hw/ftdi_driver.cpp new file mode 100644 index 00000000..9678e6cb --- /dev/null +++ b/src/hw/ftdi_driver.cpp @@ -0,0 +1,1026 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +typedef std::chrono::high_resolution_clock Clock; + +#include "ftdi_driver.hpp" + +void print_buf(size_t offset, uint8_t *buf, size_t size) { + uint32_t *buf32 = (uint32_t *)buf; + for (unsigned i = 0; i < size / (32/8); i++) { + fprintf(stderr, "%08lx: %08x\n", offset + i * (32/8), buf32[i]); + } +} + +#define SPI_TRANSFER_RW_DATA 0 +#define SPI_TRANSFER_READ_REQUEST 1 +#define SPI_TRANSFER_STATUS 2 +#define SPI_TRANSFER_READ_WITH_DUMMY 3 + +#define SPI_WAIT_8 0 +#define SPI_WAIT_16 1 +#define SPI_WAIT_24 2 +#define SPI_WAIT_32 3 + +#define SPI_ADDR_WIDTH 3 // Bytes + +struct spi_cmd { + union { + struct { + unsigned data_length : 3; + unsigned wait_cycles : 2; + unsigned transfer_type : 2; + unsigned write : 1; + }; + uint8_t u; + }; +}; + +#define CYCLES_PER_BYTE 2 +#define WAIT_CYCLES ((SPI_WAIT_8 + 1) * (8 / CYCLES_PER_BYTE)) // For READ8 +#define CMD_BYTES 4 +#define MAX_WRITE_BUF 2048 + CMD_BYTES +#define MAX_READ_BUF 2048 + WAIT_CYCLES + +#define CHECK(x) { \ + FT4222_STATUS stat = (FT4222_STATUS)x; \ + if (FT4222_OK != stat) { \ + eprintf("%s failed (error %d)", #x, (int)stat); \ + return stat; \ + } \ +} + +FtdiDriver::FtdiDriver() { + spi_ft_handle = NULL; + gpio_ft_handle = NULL; + int_write_buf = new uint8_t[MAX_WRITE_BUF]; + int_read_buf = new uint8_t[MAX_READ_BUF]; +} + +FtdiDriver::~FtdiDriver() { + // TODO: Handle deletion from multiple references + Close(); + delete [] int_write_buf; + delete [] int_read_buf; + int_write_buf = NULL; + int_read_buf = NULL; +} + +void FtdiDriver::eprintf(const char * format, ...) { + va_list argptr; + va_start(argptr, format); + +#ifdef USE_THROW + char buffer[1024]; + vsnprintf(buffer, sizeof(buffer), format, argptr); + va_end(argptr); + throw(buffer); +#else + vfprintf(stderr, format, argptr); + fprintf(stderr, "\n"); + va_end(argptr); +#endif +} + +bool FtdiDriver::IsOpen() { + //printf("spi_ft_handle %x\n", spi_ft_handle); + //printf("gpio_ft_handle %x\n", gpio_ft_handle); + return spi_ft_handle != NULL && gpio_ft_handle != NULL; +} + +inline std::string DeviceFlagToString(DWORD flags) { + std::string msg; + msg += (flags & 0x1)? "DEVICE_OPEN" : "DEVICE_CLOSED"; + msg += ", "; + msg += (flags & 0x2)? "High-speed USB" : "Full-speed USB"; + return msg; +} + +int FtdiDriver::List() { + DWORD num_devs = 0; + + CHECK(FT_CreateDeviceInfoList(&num_devs)); + + if (num_devs == 0) { + eprintf("No FTDI devices connected."); + return -1; + } + + // Allocate storage + FT_DEVICE_LIST_INFO_NODE *dev_info = + (FT_DEVICE_LIST_INFO_NODE *)malloc((size_t)num_devs * + sizeof(FT_DEVICE_LIST_INFO_NODE)); + + // Populate the list of info nodes + if (FT_GetDeviceInfoList(dev_info, &num_devs) != FT4222_OK) { + free(dev_info); + eprintf("FT_GetDeviceInfoList failed"); + return -1; + } + + for (unsigned i = 0; i < num_devs; i++) { + if (dev_info[i].Type == FT_DEVICE_4222H_0 || + dev_info[i].Type == FT_DEVICE_4222H_1_2) { + // In mode 0, the FT4222H presents two interfaces: A and B. + // In modes 1 and 2, it presents four interfaces: A, B, C and D. + size_t descLen = strlen(dev_info[i].Description); + // fprintf(stderr, "Device %d: '%s', loc %d\n", i, + // dev_info[i].Description, dev_info[i].LocId); + if ('A' == dev_info[i].Description[descLen - 1]) { + fprintf(stderr, "Device %d: '%s', loc %d\n", i, + dev_info[i].Description, dev_info[i].LocId); + } + } + } + + free(dev_info); + return 0; +} + +int FtdiDriver::Open() { + return OpenClk((int)SYS_CLK_80, (int)CLK_DIV_8); +} + +int FtdiDriver::OpenClk(unsigned sys_clk, unsigned clk_div, DWORD target_id) { + DWORD num_devs = 0; + + CHECK(FT_CreateDeviceInfoList(&num_devs)); + + if (num_devs == 0) { + eprintf("No FTDI devices connected."); + return -1; + } + + // Allocate storage + FT_DEVICE_LIST_INFO_NODE *dev_info = + (FT_DEVICE_LIST_INFO_NODE *)malloc((size_t)num_devs * + sizeof(FT_DEVICE_LIST_INFO_NODE)); + + // Populate the list of info nodes + if (FT_GetDeviceInfoList(dev_info, &num_devs) != FT4222_OK) { + free(dev_info); + eprintf("FT_GetDeviceInfoList failed"); + return -1; + } + + bool found = false; + unsigned device_id = 0; + for (unsigned i = 0; i < num_devs; i++) { + if (dev_info[i].Type == FT_DEVICE_4222H_0 || + dev_info[i].Type == FT_DEVICE_4222H_1_2) { + // In mode 0, the FT4222H presents two interfaces: A and B. + // In modes 1 and 2, it presents four interfaces: A, B, C and D. + size_t descLen = strlen(dev_info[i].Description); + if ('A' == dev_info[i].Description[descLen - 1]) { + if ((target_id != 0 && dev_info[i].LocId == target_id) || + target_id == 0) { + device_id = dev_info[i].LocId; + found = true; + //print_buf(0x0, (uint8_t *)dev_info[i].SerialNumber, 16); + break; + } + } + //printf("Dev %d:\n",i); + //printf(" Flags=0x%x\n",dev_info[i].Flags); + //printf(" Type=0x%x\n",dev_info[i].Type); + //printf(" ID=0x%x\n",dev_info[i].ID); + //printf(" LocId=0x%x\n",dev_info[i].LocId); + //printf(" SerialNumber=%s\n",dev_info[i].SerialNumber); + //printf(" Description=%s\n",dev_info[i].Description); + } + } + + free(dev_info); + + if (!found) { + eprintf("No FT4222H detected."); + return -1; + } + + return Open(device_id, sys_clk, clk_div); +} + +int FtdiDriver::SetMode(FtdiDriver::MODE_t mode) +{ + //printf("SetMode mode %d\n", mode); + if (mode == active_mode) { + return 0; + } + + if (active_mode != MODE_none) { + CHECK(FT4222_UnInitialize(spi_ft_handle)); + //printf("SetMode FT4222_UnInitialize\n"); + active_mode = MODE_none; + } + + switch(mode) { + + case MODE_spi: + //printf("SetMode(MODE_spi);\n"); + CHECK(FT4222_SPIMaster_Init(spi_ft_handle, SPI_IO_QUAD, spi_clk_div, + CLK_IDLE_LOW, CLK_LEADING, 0x01)); + // The SPI_ChipSelect value is named either CS_ACTIVE_NEGTIVE or + // CS_ACTIVE_LOW depending on libftd2xx version, but it's 0 in any case + CHECK(FT4222_SPIMaster_SetCS(spi_ft_handle, (SPI_ChipSelect)0)); + CHECK(FT4222_SPI_SetDrivingStrength(spi_ft_handle, + // clk, io, sso + //DS_8MA, DS_8MA, DS_8MA)); + //DS_4MA, DS_4MA, DS_8MA)); + DS_4MA, DS_4MA, DS_4MA)); + active_mode = mode; + break; + + case MODE_i2c: + //printf("SetMode(MODE_i2c);\n"); + CHECK(FT4222_I2CMaster_Init(spi_ft_handle, 100 /*kHz*/)); + active_mode = mode; + break; + + default: + active_mode = MODE_none; + } + + return 0; +} + + +int FtdiDriver::Open(DWORD loc_id, unsigned sys_clk, unsigned clk_div) { + Close(); + + // fprintf(stderr, "Opening device %d\n", loc_id); + spi_loc_id = loc_id; + + CHECK(FT_OpenEx((PVOID)(uintptr_t)spi_loc_id, FT_OPEN_BY_LOCATION, + &spi_ft_handle)); + + // originally we set jumpers for CNFMODE1, which uses 4 USB interfaces with + // SPIM on "A,B,C" and GPIO on "D" (ie +3). But it may be convenient to get + // more GPs by using CNFMODE0 which uses 2 USB interfaces with SPIM on "A" + // and GPIO on "B" (ie +1). Try to open GP on both. + gpio_loc_id = loc_id + 3; + cnfmode = 1; + if (FT_OpenEx((PVOID)(uintptr_t)gpio_loc_id, FT_OPEN_BY_LOCATION, + &gpio_ft_handle)) { + gpio_loc_id = loc_id + 1; + cnfmode = 0; + CHECK(FT_OpenEx((PVOID)(uintptr_t)gpio_loc_id, FT_OPEN_BY_LOCATION, + &gpio_ft_handle)); + } + + CHECK(FT4222_SetClock(spi_ft_handle, (FT4222_ClockRate)sys_clk)); + CHECK(FT_SetUSBParameters(spi_ft_handle, 2048+16, 2048+16)); + + // save clock divide SPI + spi_clk_div = (FT4222_SPIClock)clk_div; + + // start with SPI mode + CHECK(SetMode(MODE_spi)); + + // Init GPIO + gpio_dir[0] = GPIO_INPUT; + gpio_dir[1] = GPIO_INPUT; + gpio_dir[2] = GPIO_INPUT; + gpio_dir[3] = GPIO_INPUT; + CHECK(FT4222_GPIO_Init(gpio_ft_handle, gpio_dir)); + + // Set up GPIOs + // Disable suspend out, enable gpio 2 + CHECK(FT4222_SetSuspendOut(gpio_ft_handle, 0)); + // Disable interrupt, enable gpio 3 + CHECK(FT4222_SetWakeUpInterrupt(gpio_ft_handle, 0)); + + return 0; +} + +int FtdiDriver::Close() { + if (spi_ft_handle != NULL) { + //printf("FtdiDriver::Close\n"); + CHECK(FT4222_UnInitialize(spi_ft_handle)); + CHECK(FT_Close(spi_ft_handle)); + spi_ft_handle = NULL; + } + if (gpio_ft_handle != NULL) { + //printf("FtdiDriver::Close\n"); + CHECK(FT4222_UnInitialize(gpio_ft_handle)); + CHECK(FT_Close(gpio_ft_handle)); + gpio_ft_handle = NULL; + } + return 0; +} + +void FtdiDriver::ParseParams(unsigned &sys_clk, unsigned &clk_div, + int argc, char *argv[]) { + for (int i = 0; i < argc; i++) { + if (strcmp(argv[i], "-clk") == 0) { + i++; + if (strcmp(argv[i], "60") == 0) { + sys_clk = SYS_CLK_60; + } else if (strcmp(argv[i], "24") == 0) { + sys_clk = SYS_CLK_24; + } else if (strcmp(argv[i], "48") == 0) { + sys_clk = SYS_CLK_48; + } else if (strcmp(argv[i], "80") == 0) { + sys_clk = SYS_CLK_80; + } else { + fprintf(stderr, "Invalid clk %s\n", argv[i]); + exit(1); + } + } else if (strcmp(argv[i], "-div") == 0) { + i++; + if (strcmp(argv[i], "2") == 0) { + clk_div = CLK_DIV_2; + } else if (strcmp(argv[i], "4") == 0) { + clk_div = CLK_DIV_4; + } else if (strcmp(argv[i], "8") == 0) { + clk_div = CLK_DIV_8; + } else if (strcmp(argv[i], "16") == 0) { + clk_div = CLK_DIV_16; + } else if (strcmp(argv[i], "32") == 0) { + clk_div = CLK_DIV_32; + } else if (strcmp(argv[i], "64") == 0) { + clk_div = CLK_DIV_64; + } else if (strcmp(argv[i], "128") == 0) { + clk_div = CLK_DIV_128; + } else if (strcmp(argv[i], "256") == 0) { + clk_div = CLK_DIV_256; + } else if (strcmp(argv[i], "512") == 0) { + clk_div = CLK_DIV_512; + } else { + fprintf(stderr, "Invalid clk div %s\n", argv[i]); + exit(1); + } + } + } +} + +// static bool is_size_valid(size_t size) { +// return (size == 4 || +// size == 16 || +// size == 32 || +// size == 64 || +// size == 128 || +// size == 256); +// } + +static bool round_size_up(size_t &size) { + if (size <= 4) { + size = 4; + } else if (size <= 16) { + size = 16; + } else if (size <= 32) { + size = 32; + } else if (size <= 64) { + size = 64; + } else if (size <= 128) { + size = 128; + } else if (size <= 256) { + size = 256; + } else if (size > 256) { + return false; + } + return true; +} + +static int encode_size(size_t size) { + switch(size) { + case 4: + return 0; + case 16: + return 1; + case 32: + return 2; + case 64: + return 3; + case 128: + return 4; + case 256: + return 5; + default: + fprintf(stderr, "Unexpected size %zu\n", size); + exit(1); + } +} + +int FtdiDriver::WriteRaw(uint8_t *write_buf, size_t size) { + assert(IsOpen()); + // fprintf(stderr, "WriteRaw\n"); + // print_buf(0x0, write_buf, size); + + uint32_t size_of_read; + CHECK(SetMode(MODE_spi)); + CHECK(FT4222_SPIMaster_MultiReadWrite(spi_ft_handle, NULL, write_buf, + 0, // singleWriteBytes + size, // multiWriteBytes + 0, // multiReadBytes + &size_of_read)); + return 0; +} + +int FtdiDriver::ReadRaw(uint8_t *write_buf, size_t wsize, + uint8_t *read_buf, size_t rsize) { + assert(IsOpen()); + + uint32_t size_of_read; + CHECK(SetMode(MODE_spi)); + CHECK(FT4222_SPIMaster_MultiReadWrite(spi_ft_handle, read_buf, write_buf, + 0, // singleWriteBytes + wsize, // multiWriteBytes + rsize, // multiReadBytes + &size_of_read)); + if (size_of_read != rsize) { + eprintf("Size of read (%d) does not match expected (%zu)", + size_of_read, rsize); + return -1; + } + + return 0; +} + +int FtdiDriver::Write(uint32_t addr, uint8_t *write_buf, size_t wsize) { + const size_t TARGET_WRITE_SIZE = 256; + while (wsize > 0) { + if (wsize >= TARGET_WRITE_SIZE) { + int ret; + if ((ret = WriteCmd(addr, write_buf, TARGET_WRITE_SIZE)) != 0) { + return ret; + } + addr += TARGET_WRITE_SIZE; + wsize -= TARGET_WRITE_SIZE; + write_buf += TARGET_WRITE_SIZE; + } else { + // Write remaining data + return WriteCmd(addr, write_buf, wsize); + } + } + return 0; +} + +int FtdiDriver::Read(uint32_t addr, uint8_t *read_buf, size_t rsize) { + const size_t TARGET_READ_SIZE = 256; + while (rsize > 0) { + if (rsize >= TARGET_READ_SIZE) { + int ret; + if ((ret = ReadCmd(addr, read_buf, TARGET_READ_SIZE)) != 0) { + return ret; + } + addr += TARGET_READ_SIZE; + rsize -= TARGET_READ_SIZE; + read_buf += TARGET_READ_SIZE; + } else { + // Read remaining data + return ReadCmd(addr, read_buf, rsize); + } + } + return 0; +} + +int FtdiDriver::WriteCmd(uint32_t addr, uint8_t *write_buf, size_t wsize) { + //printf("WriteCmd(%x, %p, %zu)\n", addr, write_buf, wsize); + assert(IsOpen()); + size_t padded_size = wsize; + if (!round_size_up(padded_size)) { + eprintf("Unexpected wsize %zu, padded_size %zu", wsize, padded_size); + return -1; + } + + spi_cmd cmd; + cmd.write = 1; + cmd.transfer_type = SPI_TRANSFER_RW_DATA; + cmd.wait_cycles = 0; + cmd.data_length = encode_size(padded_size); + int_write_buf[0] = (uint8_t)cmd.u; + + // 4 byte addressing + addr >>= 2; + int_write_buf[1] = (addr >> (8 * 2)) & 0xff; + int_write_buf[2] = (addr >> (8 * 1)) & 0xff; + int_write_buf[3] = (addr >> (8 * 0)) & 0xff; + + // Fill in wsize bytes - padding we can ignore + for (unsigned i = 0; i < wsize; i++) { + int_write_buf[i + 4] = write_buf[i]; + } + + return WriteRaw(int_write_buf, padded_size + CMD_BYTES); +} + +int FtdiDriver::ReadCmd(uint32_t addr, uint8_t *read_buf, size_t rsize) { + //printf("ReadCmd(%x, %p, %zu)\n", addr, read_buf, rsize); + assert(IsOpen()); + size_t padded_size = rsize; + if (!round_size_up(padded_size)) { + eprintf("Unexpected read rsize %zu", rsize); + return -1; + } + //printf("ReadCmd: addr %x, size %ld, padded size %ld)\n", addr, rsize, padded_size); + + spi_cmd cmd; + cmd.write = 0; + cmd.transfer_type = SPI_TRANSFER_READ_WITH_DUMMY; + cmd.wait_cycles = 0; + cmd.data_length = encode_size(padded_size); + int_write_buf[0] = (uint8_t)cmd.u; + + // 4 byte addressing + addr >>= 2; + int_write_buf[1] = (addr >> (8 * 2)) & 0xff; + int_write_buf[2] = (addr >> (8 * 1)) & 0xff; + int_write_buf[3] = (addr >> (8 * 0)) & 0xff; + + // Clear the read buffer to ensure we don't look at stale data + memset(int_read_buf, 0, MAX_READ_BUF); + CHECK(ReadRaw(int_write_buf, CMD_BYTES, + int_read_buf, padded_size + WAIT_CYCLES)); + + // Fill in rsize bytes - padding we can ignore + for (unsigned i = 0; i < rsize; i++) { + read_buf[i] = int_read_buf[i + WAIT_CYCLES]; + } + return 0; +} + +int FtdiDriver::SetGPIO(GPIO_Port port, bool value) { + assert(IsOpen()); + assert((cnfmode==0 && + (port == GPIO_PORT0 || port == GPIO_PORT1 || + port == GPIO_PORT2 || port == GPIO_PORT3)) + || + (cnfmode==1 && + (port == GPIO_PORT2 || port == GPIO_PORT3))); + //FIXME: might this cause a glitch when going from tri to out? + if (gpio_dir[port] != GPIO_OUTPUT) { + gpio_dir[port] = GPIO_OUTPUT; + CHECK(FT4222_GPIO_Init(gpio_ft_handle, gpio_dir)); + } + CHECK(FT4222_GPIO_Write(gpio_ft_handle, port, value)); + return 0; +} + +int FtdiDriver::GetGPIO(GPIO_Port port, bool &value) { + assert(IsOpen()); + assert((cnfmode==0 && + (port == GPIO_PORT0 || port == GPIO_PORT1 || + port == GPIO_PORT2 || port == GPIO_PORT3)) + || + (cnfmode==1 && + (port == GPIO_PORT2 || port == GPIO_PORT3))); + BOOL int_val; + CHECK(FT4222_GPIO_Read(gpio_ft_handle, port, &int_val)); + value = int_val > 0; + return 0; +} + +int FtdiDriver::TriGPIO(GPIO_Port port) +{ + assert(IsOpen()); + assert((cnfmode==0 && + (port == GPIO_PORT0 || port == GPIO_PORT1 || + port == GPIO_PORT2 || port == GPIO_PORT3)) + || + (cnfmode==1 && + (port == GPIO_PORT2 || port == GPIO_PORT3))); + if (gpio_dir[port] != GPIO_INPUT) { + gpio_dir[port] = GPIO_INPUT; + CHECK(FT4222_GPIO_Init(gpio_ft_handle, gpio_dir)); + } + return 0; +} + +void FtdiDriver::ToggleGPIO(GPIO_Port port) { + bool val; + GetGPIO(port, val); + SetGPIO(port, !val); +} + +#if USE_I2C_BITBANG + +// ----------------------------------------------------------------------------- +// Bitbang I2C + +void FtdiDriver::Delay() +{ + if (!delayDisable) { + uint64_t diff; + auto t0 = Clock::now(); + do { + auto t1 = Clock::now(); + diff = std::chrono::duration_cast(t1-t0).count(); + } while (diff < 4); + } +} + +void FtdiDriver::ClearSCL() +{ + if (gpio_dir[port_SCL] != GPIO_OUTPUT) { + gpio_dir[port_SCL] = GPIO_OUTPUT; + FT4222_GPIO_Init(gpio_ft_handle, gpio_dir); + } +} + +void FtdiDriver::ClearSDA() +{ + if (gpio_dir[port_SDA] != GPIO_OUTPUT) { + gpio_dir[port_SDA] = GPIO_OUTPUT; + FT4222_GPIO_Init(gpio_ft_handle, gpio_dir); + } +} + +int FtdiDriver::ReadSCL() +{ + if (gpio_dir[port_SCL] != GPIO_INPUT) { + gpio_dir[port_SCL] = GPIO_INPUT; + FT4222_GPIO_Init(gpio_ft_handle, gpio_dir); + } + bool val; + GetGPIO(port_SCL, val); + return val ? 1 : 0; +} + +int FtdiDriver::ReadSDA() +{ + if (gpio_dir[port_SDA] != GPIO_INPUT) { + gpio_dir[port_SDA] = GPIO_INPUT; + FT4222_GPIO_Init(gpio_ft_handle, gpio_dir); + } + bool val; + GetGPIO(port_SDA, val); + return val ? 1 : 0; +} + +int FtdiDriver::ReadBit(int *bit) +{ + // "ReadSDA" makes SDA an input - processor lets go of pin and internal + // pull-up resistor makes it high. Now slave can drive the pin. + ReadSDA(); + + Delay(); + + // Clock stretching - Makes SCL an input and pull-up resistor makes + // the pin high. Slave device can pull SCL low to extend clock cycle. + if (!clockStretchDisable) { + auto t0 = Clock::now(); + while (!ReadSCL()) + { + // Check for timeout + if (timeoutEnable) { + auto t1 = Clock::now(); + uint64_t diff = std::chrono::duration_cast(t1-t0).count(); + if (diff > 2000) + return I2C_RETURN_CODE_timeout; + } + } + } else { + ReadSCL(); + } + + // At this point, SCL is high and SDA is valid - so read the bit. + *bit = ReadSDA(); + + Delay(); + + ClearSCL(); // Pull the serial clock line low ... + + return I2C_RETURN_CODE_success; // and return. +} + +int FtdiDriver::WriteBit(int bit) +{ + if (bit) + { + ReadSDA(); // Make SDA an input ... so pin is pulled up. + } + else + { + ClearSDA(); // Make SDA an output ... so pin is pulled low. + } + + Delay(); + + // Clock stretching - Makes SCL an input and pull-up resistor makes + // the pin high. Slave device can pull SCL low to extend clock cycle. + if (!clockStretchDisable) { + auto t0 = Clock::now(); + while (!ReadSCL()) + { + // Check for timeout + if (timeoutEnable) { + auto t1 = Clock::now(); + uint64_t diff = std::chrono::duration_cast(t1-t0).count(); + if (diff > 2000) + return I2C_RETURN_CODE_timeout; + } + } + } else { + ReadSCL(); + } + + // SCL is high and SDA is valid ... + // Check that nobody else is driving SDA + if (bit && !ReadSDA()) + { + return I2C_RETURN_CODE_lostArbitration; // Lost arbitration + } + + Delay(); + ClearSCL(); + + return I2C_RETURN_CODE_success; // Success! +} + +int FtdiDriver::SendStartCondition() +{ + if (start) + { + // set SDA to 1 + ReadSDA(); + Delay(); + + // Clock stretching - Makes SCL an input and pull-up resistor makes + // the pin high. Slave device can pull SCL low to extend clock cycle. + if (!clockStretchDisable) { + auto t0 = Clock::now(); + while (!ReadSCL()) + { + // Check for timeout + if (timeoutEnable) { + auto t1 = Clock::now(); + uint64_t diff = std::chrono::duration_cast(t1-t0).count(); + if (diff > 2000) + return I2C_RETURN_CODE_timeout; + } + } + } else { + ReadSCL(); + } + } + + if (!ReadSDA()) + { + return I2C_RETURN_CODE_sdaBadState; + } + + // SCL is high, set SDA from 1 to 0 + ClearSDA(); + Delay(); + ClearSCL(); + + start = 1; + + return I2C_RETURN_CODE_success; +} + +int FtdiDriver::SendStopCondition() +{ + // set SDA to 0 + ClearSDA(); + Delay(); + + // Clock stretching - Makes SCL an input and pull-up resistor makes + // the pin high. Slave device can pull SCL low to extend clock cycle. + if (!clockStretchDisable) { + auto t0 = Clock::now(); + while (!ReadSCL()) + { + // Check for timeout + if (timeoutEnable) { + auto t1 = Clock::now(); + uint64_t diff = std::chrono::duration_cast(t1-t0).count(); + if (diff > 2000) + return I2C_RETURN_CODE_timeout; + } + } + } else { + ReadSCL(); + } + + // SCL is high, set SDA from 0 to 1 + ReadSDA(); + Delay(); + + start = 0; + + return I2C_RETURN_CODE_success; +} + +#endif + +int FtdiDriver::i2c_Init() +{ +#if USE_I2C_BITBANG + port_SCL = GPIO_PORT0; + port_SDA = GPIO_PORT1; + + timeoutEnable = 1; + clockStretchDisable = 1; + delayDisable = 1; + start = 0; + + if (!ReadSCL()) return I2C_RETURN_CODE_timeout; + if (!ReadSDA()) return I2C_RETURN_CODE_timeout; +#endif + + return I2C_RETURN_CODE_success; +} + +int FtdiDriver::i2c_TransmitX +( int sendStartCondition, + int sendStopCondition, + int slaveAddress, + uint8_t *buf, + uint16_t bytesToXfer, + uint16_t &bytesXfered ) +{ +#if !USE_I2C_BITBANG + + FT_STATUS s; + + s = SetMode(MODE_i2c); + if (s!=FT_OK) + return I2C_RETURN_CODE_fail; + + s = FT4222_I2CMaster_WriteEx + (spi_ft_handle, + slaveAddress, + (sendStartCondition ? START : 0) | (sendStopCondition ? STOP : 0), + buf, + bytesToXfer, + &bytesXfered); + + if (s!=FT_OK) + return I2C_RETURN_CODE_fail; + + return I2C_RETURN_CODE_success; + +#else + + int ret; + int bit, nack; + + if (sendStartCondition) { + ret = SendStartCondition(); + if (ret != I2C_RETURN_CODE_success) + goto transmitx_error; + } + + // send slave address and write flag + { + uint8_t byteToSend = (slaveAddress<<1) | 0; + for (bit = 0; bit < 8; bit++) { + ret = WriteBit((byteToSend & 0x80) != 0); + if (ret != I2C_RETURN_CODE_success) + goto transmitx_error; + byteToSend <<= 1; + } + + ret = ReadBit(&nack); + if (ret != I2C_RETURN_CODE_success) + goto transmitx_error; + } + + // send packet + if (!nack) { + for(bytesXfered = 0; bytesXfered < bytesToXfer; bytesXfered++) { + + uint8_t byteToSend = buf[bytesXfered]; + for (bit = 0; bit < 8; bit++) { + ret = WriteBit((byteToSend & 0x80) != 0); + if (ret != I2C_RETURN_CODE_success) + goto transmitx_error; + byteToSend <<= 1; + } + + ret = ReadBit(&nack); + if (ret != I2C_RETURN_CODE_success) + goto transmitx_error; + + if (nack) + break; + } + } + + if (sendStopCondition) { + ret = SendStopCondition(); + if (ret != I2C_RETURN_CODE_success) + goto transmitx_error; + } + + return I2C_RETURN_CODE_success; + + transmitx_error: + SendStopCondition(); + ReadSDA(); + Delay(); + start = 0; + return ret; + +#endif +} + +int FtdiDriver::i2c_ReceiveX +( int sendStartCondition, + int sendStopCondition, + int slaveAddress, + uint8_t *buf, + uint16_t bytesToXfer, + uint16_t &bytesXfered ) +{ +#if !USE_I2C_BITBANG + + FT_STATUS s; + + s = SetMode(MODE_i2c); + if (s!=FT_OK) + return I2C_RETURN_CODE_fail; + + s = FT4222_I2CMaster_ReadEx + (spi_ft_handle, + slaveAddress, + (sendStartCondition ? Repeated_START : 0) | (sendStopCondition ? STOP : 0), + buf, + bytesToXfer, + &bytesXfered); + if (s!=FT_OK) + return I2C_RETURN_CODE_fail; + + return I2C_RETURN_CODE_success; + +#else + + int ret; + int b, bit, nack, sendAcknowledgeBit; + + if (sendStartCondition) { + ret = SendStartCondition(); + if (ret != I2C_RETURN_CODE_success) + goto receivex_error; + } + + // send slave address and read flag + { + uint8_t byteToSend = (slaveAddress<<1) | 1; + for (bit = 0; bit < 8; bit++) { + ret = WriteBit((byteToSend & 0x80) != 0); + if (ret != I2C_RETURN_CODE_success) + goto receivex_error; + byteToSend <<= 1; + } + + ret = ReadBit(&nack); + if (ret != I2C_RETURN_CODE_success) + goto receivex_error; + } + + // receive packet + if (!nack) { + for(bytesXfered = 0; bytesXfered < bytesToXfer; ) { + + uint8_t byte = 0; + for (bit = 0; bit < 8; bit++) { + byte <<= 1; + ret = ReadBit(&b); + if (ret != I2C_RETURN_CODE_success) + goto receivex_error; + if (b) + byte |= 1; + } + + buf[bytesXfered++] = byte; + sendAcknowledgeBit = bytesXfered < bytesToXfer; + + ret = WriteBit(!sendAcknowledgeBit); + if (ret != I2C_RETURN_CODE_success) + goto receivex_error; + } + } + + if (sendStopCondition) { + ret = SendStopCondition(); + if (ret != I2C_RETURN_CODE_success) + goto receivex_error; + } + + return I2C_RETURN_CODE_success; + + receivex_error: + SendStopCondition(); + ReadSDA(); + Delay(); + start = 0; + return ret; + +#endif +} + +const char *FtdiDriver::i2c_error(int code) +{ + if ((int)code >= (int)I2C_RETURN_CODE__last) { + code = I2C_RETURN_CODE__last; + } + return i2c_error_string[(int)code]; +} diff --git a/src/hw/ftdi_driver.hpp b/src/hw/ftdi_driver.hpp new file mode 100644 index 00000000..e740c9fd --- /dev/null +++ b/src/hw/ftdi_driver.hpp @@ -0,0 +1,174 @@ +#ifndef __FTDI_DRIVER_HPP__ +#define __FTDI_DRIVER_HPP__ + +#include +#include + +extern "C" { +#include "ftd2xx.h" +#include "libft4222.h" +} + +void print_buf(size_t offset, uint8_t *buf, size_t size); + +class FtdiDriver { +public: + typedef unsigned int DWORD; + static const unsigned GPIO2 = 2; + static const unsigned GPIO3 = 3; + + FtdiDriver(); + ~FtdiDriver(); + + void eprintf(const char * format, ...); + + int List(); + + bool IsOpen(); + + // Open a connection to an automatically located FTDI device + // Returns status, 0 for success + int Open(); + + // Open with given SPI clock parameters + int OpenClk(unsigned sys_clk, unsigned clk_div, DWORD target_id = 0); + + // Open a connection to a specific FTDI device + // Returns status, 0 for success + int Open(DWORD spi_loc_id, unsigned sys_clk, unsigned clk_div); + + // Enumeration of FTDI statemachine operation modes + typedef enum { + MODE_none, + MODE_spi, + MODE_i2c + } MODE_t; + + // Select mode for FTDI state machine transfers + int SetMode(FtdiDriver::MODE_t mode); + + // Close the connection to the FTDI device + int Close(); + + // Note: caller should set sys_clk and clk_div to a default value + // prior to calling. + static void ParseParams(unsigned &sys_clk, unsigned &clk_div, + int argc, char *argv[]); + + // Write arbitrary size message + // Returns status, 0 for success + int Write(uint32_t addr, uint8_t *write_data, size_t size); + + // Read arbitrary size message + // Returns status, 0 for success + int Read(uint32_t addr, uint8_t *read_data, size_t size); + + // Write size bytes, starting at the specified register. + // Size must be 4, 16, 32, 64, 128, or 256 + // Returns status, 0 for success + int WriteCmd(uint32_t addr, uint8_t *write_data, size_t size); + + // Read size bytes, starting at the specified register. + // Size must be 4, 16, 32, 64, 128, or 256 + // Returns status, 0 for success + int ReadCmd(uint32_t addr, uint8_t *read_data, size_t size); + + // Write size bytes, starting at the specified register. + // Returns status, 0 for success + int WriteRaw(uint8_t *write_buf, size_t size); + + // Read size bytes, starting at the specified register. + // Returns status, 0 for success + int ReadRaw(uint8_t *write_buf, size_t wsize, + uint8_t *read_buf, size_t rsize); + + // TODO - Read/write abritrary sizes + + // Set GPIO output value + // Port must be GPIO_PORT2 or GPIO_PORT3. + int SetGPIO(GPIO_Port port, bool value); + + // Get GPIO output value + // Port must be GPIO_PORT2 or GPIO_PORT3. + int GetGPIO(GPIO_Port port, bool &value); + + // Tristate GPIO output + // Port must be GPIO_PORT2 or GPIO_PORT3. + int TriGPIO(GPIO_Port port); + + // Toggle GPIO + void ToggleGPIO(GPIO_Port port); + + typedef enum { + I2C_RETURN_CODE_success = 0, + I2C_RETURN_CODE_fail, + I2C_RETURN_CODE_timeout, + I2C_RETURN_CODE_sdaBadState, + I2C_RETURN_CODE_lostArbitration, + I2C_RETURN_CODE_nack, + I2C_RETURN_CODE_checkSumFail, + I2C_RETURN_CODE__last + } I2C_RETURN_CODE_t; + + const char *i2c_error_string[32] = + { + "success", + "fail", + "timeout", + "sdaBadState", + "lostArbitration", + "nack", + "checkSumFail", + "(badErrorCode)" + }; + + int i2c_Init(); + + int SendStopCondition(); + + int i2c_TransmitX + ( int sendStartCondition, + int sendStopCondition, + int slaveAddress, + uint8_t *buf, + uint16_t bytesToXfer, + uint16_t &bytesXfered ); + + int i2c_ReceiveX + ( int sendStartCondition, + int sendStopCondition, + int slaveAddress, + uint8_t *buf, + uint16_t bytesToXfer, + uint16_t &bytesXfered ); + + const char *i2c_error + (int code); + +private: + // Opaque pointer for the FTDI driver + void *spi_ft_handle; + void *gpio_ft_handle; + + // Location ID for the FTDI SPI device + DWORD spi_loc_id; + + // Location ID for the FTDI GPIO device + DWORD gpio_loc_id; + + // Internal transaction buffer + uint8_t *int_write_buf; + uint8_t *int_read_buf; + + // detected FTDI4222 CNF MODE + int cnfmode; + + GPIO_Dir gpio_dir[4]; + + // selected SPI clock divider + FT4222_SPIClock spi_clk_div; + + // current state machine transfer mode + MODE_t active_mode = MODE_none; +}; +#endif diff --git a/src/hw/hw_interface.cpp b/src/hw/hw_interface.cpp new file mode 100644 index 00000000..d3cbf66f --- /dev/null +++ b/src/hw/hw_interface.cpp @@ -0,0 +1,213 @@ +#include "hw_interface.hpp" +#include "chia_driver.hpp" +#include "hw_util.hpp" +#include "pll_freqs.hpp" + +#include "vdf_base.hpp" + +#include "libft4222.h" + +#include +#include +#include + +#define REG_BYTES 4 +#define CHIA_VDF_JOB_SIZE (CHIA_VDF_CMD_START_REG_OFFSET - \ + CHIA_VDF_CMD_JOB_ID_REG_OFFSET + REG_BYTES) +#define CHIA_VDF_JOB_CSR_MULT 0x10000 +#define CHIA_VDF_JOB_ID_OFFSET 0x1000 +#define CHIA_VDF_JOB_STATUS_OFFSET 0x2000 + +void init_vdf_value(struct vdf_value *val) +{ + val->iters = 0; + mpz_inits(val->a, val->b, NULL); +} + +void clear_vdf_value(struct vdf_value *val) +{ + mpz_clears(val->a, val->b, NULL); +} + +void copy_vdf_value(struct vdf_value *dst, struct vdf_value *src) +{ + dst->iters = src->iters; + mpz_init_set(dst->a, src->a); + mpz_init_set(dst->b, src->b); +} + +int list_hw(void) +{ + FtdiDriver ftdi; + return ftdi.List(); +} + +void prepare_job(ChiaDriver *drv, uint64_t n_iters, uint8_t *buf, mpz_t d, mpz_t a, mpz_t b) +{ + uint32_t job_id = 0xab; + mpz_t L; + mpz_init_set(L, d); + mpz_neg(L, L); + mpz_root(L, L, 4); + + drv->SerializeJob(buf, job_id, n_iters, a, b, d, L); + mpz_clear(L); +} + +ChiaDriver *init_hw(double freq, double set_brd_voltage) +{ + bool set_status; + double freq_read, brd_voltage, brd_current, brd_power; + double external_alarm_temp = 100.0, engine_alarm_temp = 100.0; + + ChiaDriver* drv = new ChiaDriver(); + if (drv->ftdi.Open()) { + LOG_ERROR("Failed to open device"); + goto fail; + } + + LOG_INFO("Setting frequency to %f MHz", freq); + set_status = drv->SetPLLFrequency(freq, 0); + if (set_status == false) { + LOG_ERROR("Aborting since freq not set"); + goto fail; + } + + // Check frequency + freq_read = drv->GetPLLFrequency(); + LOG_INFO("Frequency is %f MHz", freq_read); + + brd_voltage = drv->GetBoardVoltage(); + LOG_INFO("Board voltage is %1.3f V", brd_voltage); + + LOG_INFO("Setting voltage to %1.3f V", set_brd_voltage); + if (drv->SetBoardVoltage(set_brd_voltage) != 0) { + LOG_ERROR("Aborting since set voltage failed"); + goto fail; + } + + brd_voltage = drv->GetBoardVoltage(); + LOG_INFO("Board voltage is now %1.3f V", brd_voltage); + + brd_current = drv->GetBoardCurrent(); + LOG_INFO("Board current is %2.3f A", brd_current); + + brd_power = drv->GetPower(); + LOG_INFO("Board power is %2.3f W", brd_power); + + // Enable PVT sensor + drv->EnablePvt(); + + // Set external temperature alarm in PVT sensor + set_status = drv->SetTempAlarmExternal(external_alarm_temp); + if (set_status == false) { + LOG_ERROR("Aborting since temp alarm not set"); + goto fail; + } + + // Set engine temperature alarm in PVT sensor + set_status = drv->SetTempAlarmEngine(engine_alarm_temp); + if (set_status == false) { + LOG_ERROR("Aborting since temp alarm not set"); + goto fail; + } + + return drv; + +fail: + if (drv->ftdi.IsOpen()) { + drv->ftdi.Close(); + } + delete drv; + return NULL; +} + +void stop_hw(ChiaDriver *drv) +{ + delete drv; +} + +void hw_vdf_control(ChiaDriver *drv, uint8_t idx_mask, uint32_t value) +{ + for (uint8_t i = 0; i < N_HW_VDFS; i++) { + uint32_t addr = CHIA_VDF_CONTROL_REG_OFFSET + CHIA_VDF_JOB_CSR_MULT * i; + if (idx_mask & (1 << i)) { + drv->RegWrite(addr, value); + } + } +} + +void adjust_hw_freq(ChiaDriver *drv, uint8_t idx_mask, int direction) +{ + double freq; + + hw_vdf_control(drv, idx_mask, 0); + + drv->SetPLLFrequency(0.0, drv->freq_idx + direction); + freq = drv->GetPLLFrequency(); + LOG_INFO("Frequency is %s to %.1f MHz; freq_idx = %u", + direction > 0 ? "increased" : "decreased", freq, drv->freq_idx); + + hw_vdf_control(drv, idx_mask, 1); +} + +int start_hw_vdf(ChiaDriver *drv, mpz_t d, mpz_t a, mpz_t b, uint64_t n_iters, int idx) +{ + uint8_t job[CHIA_VDF_JOB_SIZE]; + uint32_t base_addr = CHIA_VDF_CONTROL_REG_OFFSET + CHIA_VDF_JOB_CSR_MULT * idx; + + prepare_job(drv, n_iters, job, d, a, b); + + // Enable the engine and write in the job + drv->EnableEngine(base_addr); + drv->ftdi.Write(base_addr + CHIA_VDF_JOB_ID_OFFSET, job, sizeof(job)); + + // Provide time to clear any stale data in status registers + //usleep(150000); + return 0; +} + +void stop_hw_vdf(ChiaDriver *drv, int idx) +{ + uint32_t base_addr = CHIA_VDF_CONTROL_REG_OFFSET + CHIA_VDF_JOB_CSR_MULT * idx; + + drv->DisableEngine(base_addr); +} + +int read_hw_status(ChiaDriver *drv, uint8_t idx_mask, struct vdf_value *values) +{ + uint8_t read_status[HW_VDF_STATUS_SIZE + 20]; + uint32_t job_id; + + for (int i = 0; i < N_HW_VDFS; i++) { + uint8_t *job; + struct vdf_value *val = &values[i]; + + if (i == 0 && idx_mask & (HW_VDF_TEMP_FLAG | (1 << i))) { + drv->ftdi.Read(0x300000, read_status, HW_VDF_STATUS_SIZE + 20); + job = read_status + 20; + + if (idx_mask & HW_VDF_TEMP_FLAG) { + uint32_t temp_code; + drv->read_bytes(4, 0, read_status, temp_code); + double temp = drv->ValueToTemp(temp_code); + LOG_INFO("ASIC Temp = %3.2f C; Frequency = %.1f MHz; freq_idx = %u", + temp, pll_entries[drv->freq_idx].freq, drv->freq_idx); + } + } else if (idx_mask & (1 << i)) { + drv->ftdi.Read(CHIA_VDF_STATUS_JOB_ID_REG_OFFSET + (0x10000 * i), + read_status, HW_VDF_STATUS_SIZE); + job = read_status; + } else { + continue; + } + + if (idx_mask & (1 << i)) { + drv->DeserializeJob(job, job_id, val->iters, val->a, val->b); + LOG_DEBUG("VDF %d: Got iters=%lu", i, val->iters); + } + } + + //usleep(100000); + return 0; +} diff --git a/src/hw/hw_interface.hpp b/src/hw/hw_interface.hpp new file mode 100644 index 00000000..f6e7fe51 --- /dev/null +++ b/src/hw/hw_interface.hpp @@ -0,0 +1,37 @@ +#ifndef HW_INTERFACE_H +#define HW_INTERFACE_H + +#include +#include + +#define N_HW_VDFS 3 +#define HW_VDF_STATUS_SIZE 0xb4 +#define HW_VDF_BURST_START 0x300014 +#define HW_VDF_TEMP_FLAG (1 << 3) + +#define HW_VDF_DEF_FREQ 1100.0 +#define HW_VDF_DEF_VOLTAGE 0.88 + +struct vdf_value { + uint64_t iters; + mpz_t a, b; +}; + +extern int chia_vdf_is_emu; + +class ChiaDriver; +ChiaDriver *init_hw(double freq, double brd_voltage); +void stop_hw(ChiaDriver *drv); + +struct vdf_state; +void init_vdf_value(struct vdf_value *val); +void clear_vdf_value(struct vdf_value *val); +void copy_vdf_value(struct vdf_value *dst, struct vdf_value *src); + +int list_hw(void); +void adjust_hw_freq(ChiaDriver *drv, uint8_t idx_mask, int direction); +int start_hw_vdf(ChiaDriver *drv, mpz_t d, mpz_t a, mpz_t b, uint64_t n_iters, int idx); +void stop_hw_vdf(ChiaDriver *drv, int idx); +int read_hw_status(ChiaDriver *drv, uint8_t idx_mask, struct vdf_value *values); + +#endif // HW_INTERFACE_H diff --git a/src/hw/hw_proof.cpp b/src/hw/hw_proof.cpp new file mode 100644 index 00000000..3ea63ee6 --- /dev/null +++ b/src/hw/hw_proof.cpp @@ -0,0 +1,846 @@ +#include "hw_proof.hpp" +#include "bqfc.h" +//#include "vdf.h" + +#include +#include +#include + +static const uint32_t g_chkp_thres = 1000000; +static const uint32_t g_skip_thres = 10; + +void report_bad_vdf_value(struct vdf_state *vdf, struct vdf_value *val) +{ + vdf->n_bad++; + LOG_INFO("VDF %d: Warning: Bad VDF value at iters=%lu n_bad=%u", + vdf->idx, val->iters, vdf->n_bad); +} + +int verify_vdf_value(struct vdf_state *vdf, struct vdf_value *val) +{ + mpz_mul(vdf->a2.impl, val->b, val->b); + mpz_sub(vdf->a2.impl, vdf->a2.impl, vdf->D.impl); + /* Verify that c could be computed as c = (b^2 - d) / (4 * a) */ + if (!mpz_divisible_p(vdf->a2.impl, val->a) || mpz_scan1(vdf->a2.impl, 0) < mpz_scan1(val->a, 0) + 2) { + report_bad_vdf_value(vdf, val); + return -1; + } + return 0; +} + +int hw_proof_add_value(struct vdf_state *vdf, struct vdf_value *val) +{ + val->iters += vdf->iters_offset; + if (val->iters == vdf->iters_offset || val->iters == vdf->last_val.iters) { + vdf->n_skipped++; + LOG_INFO("VDF %d: Skipping iters=%lu n_skipped=%u", + vdf->idx, val->iters, vdf->n_skipped); + if (vdf->n_skipped > g_skip_thres) { + vdf->n_skipped = 0; + return -1; + } + return 1; + } + vdf->n_skipped = 0; + + if (mpz_sgn(val->a) == 0) { + report_bad_vdf_value(vdf, val); + return -1; + } + // b = b (mod 2*a) + mpz_mul_2exp(vdf->a2.impl, val->a, 1); + mpz_mod(val->b, val->b, vdf->a2.impl); + + if (verify_vdf_value(vdf, val)) { + return -1; + } + hw_proof_handle_value(vdf, val); + return 0; +} + +void hw_proof_get_form(form *f, struct vdf_state *vdf, struct vdf_value *val) +{ + integer a, b; + + mpz_swap(a.impl, val->a); + mpz_swap(b.impl, val->b); + + *f = form::from_abd(a, b, vdf->D); + + mpz_swap(a.impl, val->a); + mpz_swap(b.impl, val->b); +} + +void hw_proof_print_stats(struct vdf_state *vdf, uint64_t elapsed_us, bool detail) +{ + uint64_t sw_elapsed_us = vdf->elapsed_us; + uint64_t sw_iters = vdf->done_iters; + uint64_t ips, sw_ips; + + elapsed_us = elapsed_us ? elapsed_us : 1; + sw_elapsed_us = sw_elapsed_us ? sw_elapsed_us : 1; + ips = vdf->cur_iters * 1000000 / elapsed_us; + sw_ips = sw_iters * 1000000 / sw_elapsed_us; + + LOG_INFO(""); + LOG_INFO("VDF %d: %lu HW iters done in %lus, HW speed: %lu ips", + vdf->idx, vdf->cur_iters, elapsed_us / 1000000, ips); + LOG_INFO("VDF %d: %lu SW iters done in %lus, SW speed: %lu ips", + vdf->idx, sw_iters, sw_elapsed_us / 1000000, sw_ips); + if (detail) { + uint64_t done_values = vdf->done_values; + LOG_INFO("VDF %d: Avg iters per intermediate: %lu", + vdf->idx, sw_iters / done_values); + if (vdf->n_bad > 0) { + LOG_INFO("VDF %d: Bad VDF values observed: %u", vdf->idx, vdf->n_bad); + } + } + LOG_INFO(""); +} + +static const size_t g_values_mult = 1UL << 12; + +form *hw_proof_value_at(struct vdf_state *vdf, size_t pos) +{ + size_t idx = pos / g_values_mult; + size_t old_size = vdf->values.size(); + + if (idx + 1 >= old_size) { + size_t new_size = idx + 2; + vdf->values.resize(new_size); + for (size_t i = old_size; i < new_size; i++) { + vdf->values[i] = new form[g_values_mult]; + } + LOG_INFO("VDF %d: Allocating intermediate values, total %zu * %zu", + vdf->idx, new_size, g_values_mult); + } + return &vdf->values[idx][pos % g_values_mult]; +} + +form *hw_proof_last_good_form(struct vdf_state *vdf, size_t *out_pos) +{ + size_t pos = vdf->cur_iters / vdf->interval; + + while (!(vdf->valid_values[pos / 8] & (1 << (pos % 8)))) { + pos--; + } + *out_pos = pos; + return hw_proof_value_at(vdf, pos); +} + +void hw_proof_add_intermediate(struct vdf_state *vdf, struct vdf_value *val, size_t pos) +{ + if (val) { + hw_proof_get_form(hw_proof_value_at(vdf, pos), vdf, val); + } + vdf->valid_values_mtx.lock(); + vdf->valid_values[pos / 8] |= 1 << (pos % 8); + vdf->valid_values_mtx.unlock(); + vdf->done_values++; +} + +void hw_proof_calc_values(struct vdf_state *vdf, struct vdf_work *work, int thr_idx) +{ + struct vdf_value *val = &work->start_val; + uint64_t next_iters = work->start_iters; + uint32_t n_steps = work->n_steps; + + integer a(val->a), b(val->b); + //const integer a = {val->a}, b = {val->b}, d = {vdf->d}, l = {vdf->l}; + form f = form::from_abd(a, b, vdf->D); + uint64_t end_iters = next_iters + vdf->interval * n_steps; + uint64_t iters = val->iters; + PulmarkReducer reducer; + timepoint_t t1; + uint64_t init_iters = iters; + + LOG_DEBUG(" VDF %d: computing %lu iters (%lu -> %lu, %u steps) in aux thread %d", + vdf->idx, end_iters - iters, iters, end_iters, n_steps, thr_idx); + + clear_vdf_value(val); + delete work; + t1 = vdf_get_cur_time(); + do { + if (vdf->stopping) { + break; + } + nudupl_form(f, f, vdf->D, vdf->L); + reducer.reduce(f); + iters++; + + if (iters == next_iters) { + size_t pos = iters / vdf->interval; + + if (!f.check_valid(vdf->D)) { + LOG_ERROR(" VDF %d: bad form at iters=%lu", vdf->idx, iters); + abort(); + } + + *hw_proof_value_at(vdf, pos) = f; + hw_proof_add_intermediate(vdf, NULL, pos); + + next_iters += vdf->interval; + } + + } while (iters < end_iters); + + vdf->done_iters += iters - init_iters; + vdf->elapsed_us += vdf_get_elapsed_us(t1); + LOG_DEBUG(" VDF %d: aux thread %d done", vdf->idx, thr_idx); + vdf->aux_threads_busy &= ~(1UL << thr_idx); +} + +class ProofCmp { +public: + ProofCmp(std::vector &p) + { + proofs = p.data(); + } + + bool operator() (uint16_t a, uint16_t b) + { + return proofs[a].iters < proofs[b].iters; + } + +private: + struct vdf_proof *proofs; +}; + +uint16_t hw_queue_proof(struct vdf_state *vdf, uint64_t seg_iters, uint16_t prev, uint8_t flags) +{ + uint16_t pos; + struct vdf_proof proof; + + proof.iters = seg_iters; + if (prev != HW_VDF_PROOF_NONE) { + proof.iters += vdf->proofs[prev].iters; + } + proof.seg_iters = seg_iters; + proof.flags = flags; + proof.prev = prev; + proof.ref_cnt = 1; + pos = vdf->proofs.size(); + + vdf->proofs_resize_mtx.lock(); + vdf->proofs.push_back(proof); + vdf->proofs_resize_mtx.unlock(); + + vdf->queued_proofs.push_back(pos); + + return pos; +} + +uint8_t hw_proof_cnt_segments(struct vdf_state *vdf, uint16_t idx) +{ + uint8_t cnt = 0; + do { + cnt++; + idx = vdf->proofs[idx].prev; + } while (idx != HW_VDF_PROOF_NONE); + return cnt; +} + +void hw_proof_inc_ref(struct vdf_state *vdf, uint16_t idx) +{ + do { + vdf->proofs[idx].ref_cnt++; + idx = vdf->proofs[idx].prev; + } while (idx != HW_VDF_PROOF_NONE); +} + +void hw_proof_dec_ref(struct vdf_state *vdf, std::vector &idxs) +{ + std::vector proofs_to_del; + int len = idxs.size(); + int last_proof_idx = vdf->proofs.size() - 1; + + for (int i = 0; i < len; i++) { + uint16_t idx = idxs[i]; + struct vdf_proof *proof; + do { + proof = &vdf->proofs[idx]; + if (proof->flags & HW_VDF_PROOF_FLAG_STARTED) { + break; + } + proof->ref_cnt--; + if (!proof->ref_cnt) { + proofs_to_del.push_back(idx); + } + idx = proof->prev; + } while (idx != HW_VDF_PROOF_NONE); + } + + std::sort(proofs_to_del.begin(), proofs_to_del.end()); + + for (int i = proofs_to_del.size() - 1; i >= 0; i--) { + uint16_t idx = proofs_to_del[i]; + if (idx == last_proof_idx) { + last_proof_idx--; + } + memset(&vdf->proofs[idx], 0xff, sizeof(vdf->proofs[idx])); + + for (int j = 0; j < (int)vdf->queued_proofs.size(); j++) { + if (vdf->queued_proofs[j] == idx) { + vdf->queued_proofs.erase(vdf->queued_proofs.begin() + j); + } + } + } + LOG_INFO("VDF %d: Removed %d queued proofs; total proofs reduced by %zu", + vdf->idx, proofs_to_del.size(), vdf->proofs.size() - last_proof_idx - 1); + vdf->proofs.resize(last_proof_idx + 1); + LOG_DEBUG("VDF %d: Proofs %zu, queued %zu", vdf->idx, vdf->proofs.size(), vdf->queued_proofs.size()); +} + +bool hw_proof_should_queue(struct vdf_state *vdf, uint64_t iters) +{ + uint16_t last_queued_idx = vdf->queued_proofs.back(); + return iters < vdf->proofs[last_queued_idx].iters; +} + +void hw_proof_process_req(struct vdf_state *vdf) +{ + uint64_t iters; + uint64_t req_iters; + uint64_t base_iters = 0; + uint64_t chkp_iters; + uint32_t chkp_div = 4, chkp_mul = 3; + uint8_t max_chkp_segments = 64 - 3; + int i; + uint16_t prev = HW_VDF_PROOF_NONE; + + if (vdf->req_proofs.empty()) { + return; + } + + req_iters = vdf->req_proofs[0].iters; + vdf->req_proofs.erase(vdf->req_proofs.begin()); + if (!vdf->queued_proofs.empty() && hw_proof_should_queue(vdf, req_iters)) { + std::vector proofs_to_del; + for (i = 0; i < (int)vdf->queued_proofs.size(); i++) { + uint16_t idx = vdf->queued_proofs[i]; + bool is_chkp = !(vdf->proofs[idx].flags & HW_VDF_PROOF_FLAG_IS_REQ); + if (is_chkp || req_iters > vdf->proofs[idx].iters) { + continue; + } + proofs_to_del.push_back(idx); + hw_request_proof(vdf, vdf->proofs[idx].iters, false); + } + hw_proof_dec_ref(vdf, proofs_to_del); + } + + for (i = vdf->queued_proofs.size() - 1; i >= 0; i--) { + uint16_t idx = vdf->queued_proofs[i]; + uint8_t n_segments; + if (vdf->proofs[idx].flags & HW_VDF_PROOF_FLAG_IS_REQ) { + continue; + } + iters = vdf->proofs[idx].iters; + n_segments = hw_proof_cnt_segments(vdf, idx); + if (iters <= req_iters && n_segments <= max_chkp_segments) { + base_iters = iters; + prev = idx; + hw_proof_inc_ref(vdf, prev); + break; + } else if (iters <= req_iters) { + LOG_INFO("VDF %d: Max seg triggered at req_iters=%lu", vdf->idx, req_iters); + } + } + + iters = req_iters - base_iters; + + if (iters > g_chkp_thres) { + // Split iters as [75%, 25%] + chkp_iters = iters * chkp_mul / chkp_div; + if (iters - chkp_iters > g_chkp_thres) { + // Split iters as [69%, 23%, 8%] + uint32_t chkp2_mul[] = { 69, 69 + 23 }; + uint64_t chkp2_iters; + + chkp_iters = iters * chkp2_mul[0] / 100; + chkp_iters = chkp_iters / vdf->interval * vdf->interval; + prev = hw_queue_proof(vdf, chkp_iters, prev, 0); + + chkp2_iters = iters * chkp2_mul[1] / 100 - chkp_iters; + iters -= chkp_iters; + chkp_iters = chkp2_iters; + } + chkp_iters = chkp_iters / vdf->interval * vdf->interval; + prev = hw_queue_proof(vdf, chkp_iters, prev, 0); + iters -= chkp_iters; + } + hw_queue_proof(vdf, iters, prev, HW_VDF_PROOF_FLAG_IS_REQ); + + { + ProofCmp cmp(vdf->proofs); + std::sort(vdf->queued_proofs.begin(), vdf->queued_proofs.end(), cmp); + } +} + +bool hw_proof_req_cmp(struct vdf_proof_req &a, struct vdf_proof_req &b) +{ + return a.iters < b.iters; +} + +void hw_request_proof(struct vdf_state *vdf, uint64_t iters, bool is_chkp) +{ + vdf->req_proofs.push_back({iters, is_chkp}); + std::sort(vdf->req_proofs.begin(), vdf->req_proofs.end(), hw_proof_req_cmp); +} + +void hw_proof_add_work(struct vdf_state *vdf, uint64_t next_iters, uint32_t n_steps) +{ + auto *work = new struct vdf_work; + + copy_vdf_value(&work->start_val, &vdf->last_val); + work->start_iters = next_iters; + work->n_steps = n_steps; + + vdf->wq.push_back(work); +} + +void hw_proof_process_work(struct vdf_state *vdf) +{ + uint64_t busy = vdf->aux_threads_busy; + uint32_t qlen; + + while (!vdf->req_proofs.empty() && (vdf->queued_proofs.size() < 3 || + hw_proof_should_queue(vdf, vdf->req_proofs[0].iters))) { + hw_proof_process_req(vdf); + } + + for (int i = 0; i < vdf->max_aux_threads; i++) { + uint64_t iters; + struct vdf_proof *proof; + size_t idx; + + if (vdf->queued_proofs.empty()) { + break; + } + idx = vdf->queued_proofs[0]; + proof = &vdf->proofs[idx]; + iters = proof->iters; + if (vdf->last_val.iters < iters || + vdf->n_proof_threads >= vdf->max_proof_threads) { + break; + } + + if (!(busy & (1UL << i))) { + bool is_chkp = !(proof->flags & HW_VDF_PROOF_FLAG_IS_REQ); + + LOG_INFO("VDF %d: Starting proof thread %d for iters=%lu, length=%lu%s", + vdf->idx, i, iters, proof->seg_iters, is_chkp ? " [checkpoint]" : ""); + vdf->queued_proofs.erase(vdf->queued_proofs.begin()); + vdf->aux_threads_busy |= 1UL << i; + vdf->n_proof_threads += PARALLEL_PROVER_N_THREADS; + proof->flags |= HW_VDF_PROOF_FLAG_STARTED; + std::thread(hw_compute_proof, vdf, idx, proof, i).detach(); + } + } + + busy = vdf->aux_threads_busy; + + for (int i = 0; i < vdf->max_aux_threads; i++) { + if (!(busy & (1UL << i))) { + struct vdf_work *work; + + if (vdf->wq.empty()) { + break; + } + + work = vdf->wq.front(); + vdf->wq.pop_front(); + //struct vdf_value *val = &vdf->raw_values[work.raw_idx]; + + vdf->aux_threads_busy |= 1UL << i; + std::thread(hw_proof_calc_values, vdf, work, i).detach(); + } + } + + qlen = vdf->wq.size(); + if (qlen >= vdf->wq_warn_thres[1]) { + vdf->wq_warn_thres[0] *= HW_VDF_WQ_WARN_MULT; + vdf->wq_warn_thres[1] *= HW_VDF_WQ_WARN_MULT; + LOG_INFO("VDF %d: Warning: too much work for VDF aux threads; qlen=%u", + vdf->idx, qlen); + } else if (vdf->wq_warn_thres[0] != 1 && qlen < vdf->wq_warn_thres[0]) { + vdf->wq_warn_thres[0] /= HW_VDF_WQ_WARN_MULT; + vdf->wq_warn_thres[1] /= HW_VDF_WQ_WARN_MULT; + LOG_INFO("VDF %d: Work queue for VDF aux threads reduced; qlen=%u", + vdf->idx, qlen); + } +} + +void hw_proof_wait_values(struct vdf_state *vdf, bool finish_work) +{ + if (finish_work) { + while (!vdf->wq.empty()) { + usleep(100000); + hw_proof_process_work(vdf); + } + } + + while (vdf->aux_threads_busy) { + usleep(10000); + } + + if (!finish_work) { + for (size_t i = 0; i < vdf->wq.size(); i++) { + clear_vdf_value(&vdf->wq[i]->start_val); + delete vdf->wq[i]; + } + vdf->wq.clear(); + } +} + +int hw_proof_wait_value(struct vdf_state *vdf, size_t pos) +{ + while (!(vdf->valid_values[pos / 8] & (1 << (pos % 8)))) { + usleep(100000); + if (vdf->stopping) { + return -1; + } + } + return 0; +} + +void hw_proof_handle_value(struct vdf_state *vdf, struct vdf_value *val) +{ + uint64_t interval = vdf->interval; + //uint64_t iters = vdf->raw_values.back().iters; + uint64_t last_iters = vdf->last_val.iters; + //uint64_t start_iters = iters; + //uint64_t end_iters = val->iters; + //uint64_t mask = interval - 1; + //start_iters = (start_iters + mask) & ~mask; + //end_iters &= ~mask; + uint64_t start_iters = last_iters / interval * interval + interval; + uint64_t end_iters = val->iters / interval * interval; + uint64_t elapsed_us; + uint64_t log_interval = 10 * 1000000; + bool print_stats = false; + + if (val->iters == end_iters) { + hw_proof_add_intermediate(vdf, val, val->iters / interval); + if (end_iters) { + end_iters -= interval; + } + } + //iters = start_iters; + + if (end_iters && start_iters <= end_iters) { + uint32_t n_steps = (end_iters - start_iters) / interval; + //fprintf(stderr, "VDF %d: computing target iters=%lu delta=%lu\n", + //vdf->idx, end_iters, end_iters - iters); + if (start_iters > vdf->target_iters) { + LOG_ERROR("VDF %d: Fail at iters=%lu end_iters=%lu", + vdf->idx, last_iters, end_iters); + abort(); + } + //iters += interval; + hw_proof_add_work(vdf, start_iters, n_steps); + } + + //vdf->raw_values.push_back(*val); + vdf->cur_iters = val->iters; + std::swap(vdf->last_val, *val); + + elapsed_us = vdf_get_elapsed_us(vdf->start_time); + if (elapsed_us / log_interval > vdf->log_cnt) { + vdf->log_cnt = elapsed_us / log_interval; + print_stats = true; + } + if (print_stats || vdf->cur_iters >= vdf->target_iters) { + hw_proof_print_stats(vdf, elapsed_us, false); + } + if (vdf->cur_iters >= vdf->target_iters) { + vdf->completed = true; + } + + hw_proof_process_work(vdf); +} + +void hw_stop_proof(struct vdf_state *vdf) +{ + vdf->stopping = true; + hw_proof_print_stats(vdf, vdf_get_elapsed_us(vdf->start_time), true); + hw_proof_wait_values(vdf, false); +} + +class HwProver : public ParallelProver { + public: + HwProver(Segment segm, integer D, struct vdf_state *vdf) + : ParallelProver(segm, D) + { + this->vdf = vdf; + k = FindK(segm.length); + l = vdf->interval / k; + pos_offset = segm.start / vdf->interval; + } + + form* GetForm(uint64_t pos) { + pos += pos_offset; + if (hw_proof_wait_value(vdf, pos)) { + // Provide arbitrary value when stopping - proof won't be computed + return &vdf->values[0][0]; + } + return hw_proof_value_at(vdf, pos); + } + + void start() { + GenerateProof(); + } + + void stop() { + } + + bool PerformExtraStep() { + return !vdf->stopping; + } + + void OnFinish() { + is_finished = true; + } + + bool IsFinished() { + return is_finished; + } + + uint32_t FindK(uint64_t iters) { + uint8_t d = 1; + const uint8_t divisors[] = HW_VDF_VALUE_INTERVAL_DIVISORS; + uint64_t interval = vdf->interval; + uint64_t n_steps = iters + interval * 4, n_steps2; + size_t i; + + for (i = 0; i < sizeof(divisors) / sizeof(*divisors); i++) { + d = divisors[i]; + n_steps2 = iters / d + ((interval / d) << (d + 1)); + + if (n_steps2 > n_steps) { + return i ? divisors[i - 1] : 1; + } + n_steps = n_steps2; + } + return divisors[i - 1]; + } + + private: + struct vdf_state *vdf; + uint32_t pos_offset; +}; + +void hw_compute_proof(struct vdf_state *vdf, size_t proof_idx, struct vdf_proof *out_proof, uint8_t thr_idx) +{ + form x, y, proof_val; + uint64_t proof_iters, start_iters, iters; + size_t pos, start_pos; + PulmarkReducer reducer; + bool is_chkp; + timepoint_t start_time = vdf_get_cur_time(); + + vdf->proofs_resize_mtx.lock(); + if (proof_idx != SIZE_MAX) { + out_proof = &vdf->proofs[proof_idx]; + } + + proof_iters = out_proof->iters; + start_iters = proof_iters - out_proof->seg_iters; + is_chkp = !(out_proof->flags & HW_VDF_PROOF_FLAG_IS_REQ); + vdf->proofs_resize_mtx.unlock(); + + start_pos = start_iters / vdf->interval; + pos = proof_iters / vdf->interval; + iters = pos * vdf->interval; + + if (hw_proof_wait_value(vdf, start_pos) || hw_proof_wait_value(vdf, pos)) { + LOG_INFO("VDF %d: Proof stopped", vdf->idx); + goto out; + } + x = *hw_proof_value_at(vdf, start_pos); + y = *hw_proof_value_at(vdf, pos); + if (!y.check_valid(vdf->D)) { + LOG_ERROR("VDF %d: invalid form at pos=%lu", vdf->idx, pos); + abort(); + } + while (iters < proof_iters) { + nudupl_form(y, y, vdf->D, vdf->L); + reducer.reduce(y); + iters++; + } + if (!y.check_valid(vdf->D)) { + LOG_ERROR("VDF %d: invalid y", vdf->idx); + abort(); + } + + + { + Segment seg(start_iters, proof_iters - start_iters, x, y); + HwProver prover(seg, vdf->D, vdf); + + if (!is_chkp && seg.length > g_chkp_thres) { + LOG_INFO("VDF %d: Warning: too long final proof segment length=%lu", + vdf->idx, seg.length); + } + + prover.start(); + + if (prover.IsFinished()) { + size_t d_bits; + uint64_t elapsed_us = vdf_get_elapsed_us(start_time); + bool is_valid = false; + proof_val = prover.GetProof(); + + LOG_INFO("VDF %d: Proof done for iters=%lu, length=%lu in %.3fs%s", + vdf->idx, proof_iters, seg.length, + (double)elapsed_us / 1000000, is_chkp ? " [checkpoint]" : ""); + + VerifyWesolowskiProof(vdf->D, x, y, proof_val, seg.length, is_valid); + if (!is_valid) { + LOG_ERROR("VDF %d: Proof NOT VALID", vdf->idx); + abort(); + } + + d_bits = mpz_sizeinbase(vdf->D.impl, 2); + + vdf->proofs_resize_mtx.lock(); + if (proof_idx != SIZE_MAX) { + out_proof = &vdf->proofs[proof_idx]; + } + + bqfc_serialize(out_proof->y, y.a.impl, y.b.impl, d_bits); + bqfc_serialize(out_proof->proof, proof_val.a.impl, proof_val.b.impl, d_bits); + + if (out_proof->flags & HW_VDF_PROOF_FLAG_IS_REQ) { + vdf->done_proofs.push_back((uint16_t)proof_idx); + } else { + integer B = GetB(vdf->D, x, y); + + mpz_export(out_proof->B, NULL, 1, 1, 0, 0, B.impl); + } + out_proof->flags |= HW_VDF_PROOF_FLAG_DONE; + vdf->proofs_resize_mtx.unlock(); + } else { + LOG_INFO("VDF %d: Proof stopped", vdf->idx); + } + } + +out: + if (thr_idx < vdf->max_aux_threads) { + vdf->aux_threads_busy &= ~(1UL << thr_idx); + vdf->n_proof_threads -= PARALLEL_PROVER_N_THREADS; + } +} + +int hw_retrieve_proof(struct vdf_state *vdf, struct vdf_proof **out_proof) +{ +#if 0 + if (!vdf->proofs.empty()) { + for (size_t i = 0; i < vdf->proofs.size(); i++) { + uint64_t iters = vdf->proofs[i]->iters; + size_t last_chkp = iters / vdf->chkp_interval; + if (iters && (!last_chkp || vdf->chkp_proofs[last_chkp - 1]->iters)) { + *proof = vdf->proofs[i]; + vdf->proofs.erase(vdf->proofs.begin() + i); + return last_chkp; + } + } + } +#endif + if (!vdf->done_proofs.empty()) { + for (size_t i = 0; i < vdf->done_proofs.size(); i++) { + uint16_t idx = vdf->done_proofs[i]; + struct vdf_proof *proof = &vdf->proofs[idx]; + uint16_t j = proof->prev; + int cnt = 0; + bool done = true; + + while (j != HW_VDF_PROOF_NONE) { + if (!(vdf->proofs[j].flags & HW_VDF_PROOF_FLAG_DONE)) { + done = false; + break; + } + j = vdf->proofs[j].prev; + cnt++; + } + + if (done) { + *out_proof = proof; + vdf->done_proofs.erase(vdf->done_proofs.begin() + i); + return cnt; + } + } + } + return -1; +} + +void init_vdf_state(struct vdf_state *vdf, struct vdf_proof_opts *opts, const char *d_str, const uint8_t *init_form, uint64_t n_iters, uint8_t idx) +{ + //int ret; + //struct vdf_value initial; + size_t num_values; + vdf->cur_iters = 0; + vdf->iters_offset = 0; + vdf->done_values = 1; + vdf->done_iters = 0; + vdf->elapsed_us = 0; + vdf->start_time = vdf_get_cur_time(); + vdf->interval = HW_VDF_VALUE_INTERVAL; + vdf->chkp_interval = HW_VDF_CHKP_INTERVAL; + vdf->target_iters = (n_iters + vdf->interval - 1) / vdf->interval * vdf->interval; + vdf->idx = idx; + vdf->completed = false; + vdf->stopping = false; + vdf->aux_threads_busy = 0; + vdf->n_proof_threads = 0; + vdf->n_bad = 0; + vdf->n_skipped = 0; + vdf->log_cnt = 0; + vdf->wq_warn_thres[0] = 1; + vdf->wq_warn_thres[1] = HW_VDF_WQ_WARN_MULT * HW_VDF_WQ_WARN_MULT; + + vdf->max_aux_threads = HW_VDF_DEFAULT_MAX_AUX_THREADS; + if (opts && opts->max_aux_threads) { + vdf->max_aux_threads = opts->max_aux_threads; + } + vdf->max_proof_threads = vdf->max_aux_threads - (vdf->max_aux_threads + 7) / 8; + if (opts && opts->max_proof_threads) { + vdf->max_proof_threads = opts->max_proof_threads; + } + + mpz_set_str(vdf->D.impl, d_str, 0); + mpz_set(vdf->L.impl, vdf->D.impl); + mpz_neg(vdf->L.impl, vdf->L.impl); + mpz_root(vdf->L.impl, vdf->L.impl, 4); + + num_values = vdf->target_iters / vdf->interval + 1; + vdf->values.reserve((num_values + g_values_mult - 1) / g_values_mult); + vdf->valid_values.resize((num_values + 7) / 8, 0); + + //mpz_init_set_ui(initial.a, 2); + //mpz_init_set_ui(initial.b, 1); + //initial.iters = 0; + init_vdf_value(&vdf->last_val); + // TODO: verify validity of initial form + bqfc_deserialize(vdf->last_val.a, vdf->last_val.b, vdf->D.impl, init_form, + BQFC_FORM_SIZE, BQFC_MAX_D_BITS); + hw_proof_get_form(hw_proof_value_at(vdf, 0), vdf, &vdf->last_val); + vdf->valid_values[0] = 1 << 0; + //vdf->raw_values.push_back(initial); + vdf->init_done = true; +} + +void clear_vdf_state(struct vdf_state *vdf) +{ + vdf->proofs.clear(); + vdf->req_proofs.clear(); + vdf->queued_proofs.clear(); + vdf->done_proofs.clear(); + + for (size_t i = 0; i < vdf->values.size(); i++) { + delete[] vdf->values[i]; + } + vdf->values.clear(); + vdf->valid_values.clear(); + mpz_clears(vdf->last_val.a, vdf->last_val.b, NULL); + vdf->init_done = false; +} diff --git a/src/hw/hw_proof.hpp b/src/hw/hw_proof.hpp new file mode 100644 index 00000000..36684131 --- /dev/null +++ b/src/hw/hw_proof.hpp @@ -0,0 +1,103 @@ +#ifndef HW_PROOF_H +#define HW_PROOF_H + +#include "vdf_base.hpp" +#include "hw_interface.hpp" +#include "hw_util.hpp" +#include "bqfc.h" + +#include +#include +#include +#include + +#define HW_VDF_VALUE_INTERVAL 4000 +#define HW_VDF_VALUE_INTERVAL_DIVISORS { 2, 4, 5, 8, 10, 16, 20 } +#define HW_VDF_CHKP_INTERVAL 1000000 +#define HW_VDF_MAX_AUX_THREADS 64 +#define HW_VDF_DEFAULT_MAX_AUX_THREADS 4 +#define HW_VDF_WQ_WARN_MULT 2 +#define HW_VDF_B_SIZE 33 + +#define HW_VDF_PROOF_FLAG_DONE 1 +#define HW_VDF_PROOF_FLAG_IS_REQ 2 +#define HW_VDF_PROOF_FLAG_STARTED 4 +#define HW_VDF_PROOF_NONE ((uint16_t)0xffff) + +struct vdf_work { + //size_t raw_idx; + struct vdf_value start_val; + uint64_t start_iters; + uint32_t n_steps; +}; + +struct vdf_proof_req { + uint64_t iters; + bool is_chkp; +}; + +struct vdf_proof { + uint64_t iters; + uint64_t seg_iters; + uint8_t y[BQFC_FORM_SIZE]; + uint8_t proof[BQFC_FORM_SIZE]; + uint8_t B[HW_VDF_B_SIZE]; + + uint8_t flags; + uint16_t prev; + uint16_t ref_cnt; +}; + +struct vdf_proof_opts { + uint8_t max_aux_threads; + uint8_t max_proof_threads; +}; + +struct vdf_state { + uint64_t target_iters; + uint64_t iters_offset; + uint64_t cur_iters; + std::atomic done_values; + std::atomic done_iters; + std::atomic elapsed_us; + timepoint_t start_time; + //std::vector raw_values; + struct vdf_value last_val; + std::vector
values; + std::vector valid_values; + std::mutex valid_values_mtx; + std::deque req_proofs; + std::vector proofs; + std::mutex proofs_resize_mtx; + std::vector queued_proofs; /* sorted queued proofs */ + std::vector done_proofs; /* requested and not sent */ + integer D, L, a2; + std::deque wq; + uint32_t wq_warn_thres[2]; + //std::mutex wq_mtx; + uint32_t interval; + uint32_t chkp_interval; + uint32_t n_bad; + uint32_t n_skipped; + uint32_t log_cnt; + std::atomic aux_threads_busy; + std::atomic n_proof_threads; + uint8_t idx; + uint8_t max_aux_threads; + uint8_t max_proof_threads; + bool completed; + bool stopping; + bool init_done; +}; + +int hw_proof_add_value(struct vdf_state *vdf, struct vdf_value *val); +form *hw_proof_last_good_form(struct vdf_state *vdf, size_t *out_pos); +void hw_proof_handle_value(struct vdf_state *vdf, struct vdf_value *val); +void hw_stop_proof(struct vdf_state *vdf); +void hw_request_proof(struct vdf_state *vdf, uint64_t iters, bool is_chkp); +void hw_compute_proof(struct vdf_state *vdf, size_t proof_idx, struct vdf_proof *out_proof, uint8_t thr_idx); +int hw_retrieve_proof(struct vdf_state *vdf, struct vdf_proof **proof); +void init_vdf_state(struct vdf_state *vdf, struct vdf_proof_opts *params, const char *d_str, const uint8_t *init_form, uint64_t n_iters, uint8_t idx); +void clear_vdf_state(struct vdf_state *vdf); + +#endif // HW_PROOF_H diff --git a/src/hw/hw_test.cpp b/src/hw/hw_test.cpp new file mode 100644 index 00000000..20df7694 --- /dev/null +++ b/src/hw/hw_test.cpp @@ -0,0 +1,121 @@ +//#include "chia_driver.hpp" +//#include "chia_vdf.hpp" + +//#include +//#include +//#include +//#include +//#include "alloc.hpp" +//#include "create_discriminant.h" + +//#include "libft4222.h" + +//#include +#include "hw_interface.hpp" +#include "hw_proof.hpp" +#include "vdf_base.hpp" +#include "bqfc.h" + +#include +#include + +#include + +static const char *discrs[] = { + "-0xac566497f63870a7b661f5482f47336cd1aa85ab43914828b7998f255916729c2ad965bcf7fe231721d96706ea7d823ed4adf663a0263714bb80144aebafcdd2915b6c7ef68c2d19447be83e7f39b4a7442640914053d2e7d6a561aa29b9449c815717af7da97a823798f402d073901a1f2bd8cd879b8b1afe2496649197021f", + "-0xc3657f850b3f2b659d70273704564bc69b849fe1d8c70b096933efdcf7143931b393676f500d79624da783d73e0c5303ae48fb9543502c4161586d8fdaf03709d2115df21aeeee4a58614050cbdfe74024063b9620de084d8ef46f474fa57983c4bebfa7e8a69efeb523a167558fe1487a086c11337e20b773ad3d4710671417", + "-0xffbd9edace9d59e0a395f0358698e8cd68a3dcb90af740d1fe14f58a06678e11d47e19b4f9b9237689084b724db8a912bb32d64614bbb5c4df5c54e9b574b8f7b7c59c8ac2522aae4777220696ee4dd11942e9e85b07de0454a491db7b19baa4c2f1eb3ae8930c44984c767c664d85e337b8e90cf1c5d3d30a9ec7ddcc3b26d7" +}; + +void init_chia(void) +{ + VdfBaseInit(); + //init_gmp(); + //set_rounding_mode(); + //fesetround(FE_TOWARDZERO); +} + +int hw_test_main(int argc, char **argv) +{ + uint64_t n_iters = 1000000; + uint8_t n_vdfs = 3; + uint8_t n_completed = 0; + uint8_t vdfs_mask; + uint8_t init_form[BQFC_FORM_SIZE] = { 0x08 }; + struct vdf_state vdfs[N_HW_VDFS]; + struct vdf_value values[N_HW_VDFS]; + struct vdf_proof proofs[N_HW_VDFS]; + std::thread proof_threads[N_HW_VDFS]; + //std::thread vdf_threads[N_HW_VDFS]; + ChiaDriver *drv; + uint64_t read_cnt = 0; + uint32_t temp_period = chia_vdf_is_emu ? 200 : 2000; + + if (argc > 1) { + n_vdfs = strtoul(argv[1], NULL, 0); + if (n_vdfs > 3 || n_vdfs < 1) { + n_vdfs = 2; + } + } + if (argc > 2) { + n_iters = strtoul(argv[2], NULL, 0); + } + init_chia(); + drv = init_hw(HW_VDF_DEF_FREQ, HW_VDF_DEF_VOLTAGE); + if (!drv) { + return 1; + } + + for (uint8_t i = 0; i < n_vdfs; i++) { + struct vdf_state *vdf = &vdfs[i]; + + init_vdf_state(vdf, NULL, discrs[i], init_form, n_iters, i); + + //run_hw(vdf->d, n_iters, vdf); + //vdf_threads[i] = std::thread(start_vdf_job, vdf, i); + start_hw_vdf(drv, vdf->D.impl, vdf->last_val.a, vdf->last_val.b, vdf->target_iters, i); + init_vdf_value(&values[i]); + } + + vdfs_mask = (1 << n_vdfs) - 1; + while (vdfs_mask) { + uint8_t temp_flag = read_cnt % temp_period ? 0 : HW_VDF_TEMP_FLAG; + read_hw_status(drv, vdfs_mask | temp_flag, values); + for (uint8_t i = 0; i < n_vdfs; i++) { + if (vdfs_mask & (1 << i)) { + hw_proof_add_value(&vdfs[i], &values[i]); + } + + if (vdfs[i].completed && (vdfs_mask & (1 << i))) { + stop_hw_vdf(drv, i); + vdfs_mask &= ~(1 << i); + n_completed++; + proofs[i].iters = n_iters; + proofs[i].seg_iters = n_iters; + proof_threads[i] = std::thread(hw_compute_proof, &vdfs[i], SIZE_MAX, &proofs[i], 255); + } + } + //if (i == n_vdfs) { + //fprintf(stderr, "Proofs completed: %d\n", (int)i); + //break; + //} + if (chia_vdf_is_emu) { + usleep(50000); + } + read_cnt++; + } + + for (uint8_t i = 0; i < n_vdfs; i++) { + proof_threads[i].join(); + clear_vdf_state(&vdfs[i]); + clear_vdf_value(&values[i]); + } + stop_hw(drv); + return 0; +} + +int main(int argc, char **argv) +{ + init_chia(); + return hw_test_main(argc, argv); +} diff --git a/src/hw/hw_util.cpp b/src/hw/hw_util.cpp new file mode 100644 index 00000000..77f7f7c2 --- /dev/null +++ b/src/hw/hw_util.cpp @@ -0,0 +1,21 @@ +#include "hw_util.hpp" + +#include +#include + +void vdf_do_log(const char *msg, ...) +{ + va_list ap; + struct tm cal; + char time_str[25]; + struct timespec ts; + + clock_gettime(CLOCK_REALTIME, &ts); + localtime_r(&ts.tv_sec, &cal); + strftime(time_str, sizeof(time_str), "%FT%T", &cal); + fprintf(stderr, "%s.%03ld ", time_str, ts.tv_nsec / 1000000); + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); +} diff --git a/src/hw/hw_util.hpp b/src/hw/hw_util.hpp new file mode 100644 index 00000000..bb2c7805 --- /dev/null +++ b/src/hw/hw_util.hpp @@ -0,0 +1,36 @@ +#ifndef HW_UTIL_H +#define HW_UTIL_H + +#include +#include + +void vdf_do_log(const char *msg, ...); + +#ifndef VDF_ENABLE_LOG_DEBUG +# define VDF_ENABLE_LOG_DEBUG 0 +#endif + +#if VDF_ENABLE_LOG_DEBUG +# define LOG_DEBUG(msg, ...) vdf_do_log(msg "\n", ##__VA_ARGS__) +#else +# define LOG_DEBUG(msg, ...) ((void)msg) +#endif +#define LOG_INFO(msg, ...) vdf_do_log(msg "\n", ##__VA_ARGS__) +#define LOG_ERROR(msg, ...) vdf_do_log(msg "\n", ##__VA_ARGS__) + +#define LOG_SIMPLE(msg, ...) fprintf(stderr, msg "\n", ##__VA_ARGS__) + +typedef std::chrono::time_point timepoint_t; + +static inline timepoint_t vdf_get_cur_time(void) +{ + return std::chrono::high_resolution_clock::now(); +} + +static inline uint64_t vdf_get_elapsed_us(timepoint_t &t1) +{ + auto t2 = vdf_get_cur_time(); + return std::chrono::duration_cast(t2 - t1).count(); +} + +#endif /* HW_UTIL_H */ diff --git a/src/hw/hw_vdf_client.cpp b/src/hw/hw_vdf_client.cpp new file mode 100644 index 00000000..c27ac51a --- /dev/null +++ b/src/hw/hw_vdf_client.cpp @@ -0,0 +1,563 @@ +#include "hw_interface.hpp" +#include "hw_proof.hpp" +#include "hw_util.hpp" +#include "bqfc.h" +#include "vdf_base.hpp" +#include "chia_driver.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum conn_state { + WAITING, + RUNNING, + IDLING, + STOPPED, + CLOSED +}; + +struct vdf_conn { + struct vdf_state vdf; + int sock; + char read_buf[512]; + uint32_t buf_pos; + enum conn_state state; +}; + +struct vdf_client_opts { + double freq; + double voltage; + uint32_t ip; + int port; + int n_vdfs; + uint32_t auto_freq_period; + bool do_list; + bool auto_freq; + struct vdf_proof_opts vpo; + uint8_t vdfs_mask; +}; + +struct vdf_client { + struct vdf_conn conns[N_HW_VDFS]; + struct vdf_value values[N_HW_VDFS]; + struct vdf_client_opts opts; + ChiaDriver *drv; +}; + +struct vdf_proof_segm { + uint8_t iters[sizeof(uint64_t)]; + uint8_t B[HW_VDF_B_SIZE]; + uint8_t proof[BQFC_FORM_SIZE]; +}; + +void write_data(struct vdf_conn *conn, const char *buf, size_t size); + +static volatile bool g_stopping = false; + +void signal_handler(int sig) +{ + LOG_INFO("Interrupted"); + g_stopping = true; +} + +void init_conn(struct vdf_conn *conn, uint32_t ip, int port) +{ + int ret; + struct sockaddr_in sa = { AF_INET, htons(port), { htonl(ip) } }; + conn->sock = socket(AF_INET, SOCK_STREAM, 0); + LOG_INFO("Connecting to %s:%d", inet_ntoa(sa.sin_addr), port); + ret = connect(conn->sock, (struct sockaddr *)&sa, sizeof(sa)); + if (ret < 0) { + perror("connect"); + sleep(1); + return; + } + + ret = fcntl(conn->sock, F_SETFL, O_NONBLOCK); + if (ret < 0) { + perror("fcntl"); + close(conn->sock); + conn->sock = -1; + return; + } + conn->state = WAITING; + conn->buf_pos = 0; + LOG_INFO("VDF %d: Connected to timelord, waiting for challenge", conn->vdf.idx); +} + +void init_vdf_client(struct vdf_client *client) +{ + if (!client->opts.vdfs_mask) { + for (uint8_t i = 0; i < client->opts.n_vdfs; i++) { + client->opts.vdfs_mask |= 1 << i; + } + } + for (uint8_t i = 0; i < N_HW_VDFS; i++) { + client->conns[i].state = CLOSED; + if (!(client->opts.vdfs_mask & (1 << i))) { + continue; + } + client->conns[i].vdf.idx = i; + client->conns[i].sock = -1; + memset(client->conns[i].read_buf, 0, sizeof(client->conns[i].read_buf)); + client->conns[i].buf_pos = 0; + + init_vdf_value(&client->values[i]); + } +} + +void clear_vdf_client(struct vdf_client *client) +{ + for (uint8_t i = 0; i < N_HW_VDFS; i++) { + if (client->opts.vdfs_mask & (1 << i)) { + clear_vdf_value(&client->values[i]); + } + } +} + +void stop_conn(struct vdf_client *client, struct vdf_conn *conn) +{ + if (conn->sock >= 0) { + write_data(conn, "STOP", 4); + } + if (conn->vdf.init_done) { + hw_stop_proof(&conn->vdf); + clear_vdf_state(&conn->vdf); + stop_hw_vdf(client->drv, conn->vdf.idx); + } + conn->state = STOPPED; + LOG_INFO("VDF %d: Stopped at iters=%lu", conn->vdf.idx, conn->vdf.cur_iters); +} + +void close_conn(struct vdf_conn *conn) +{ + if (conn->state != CLOSED) { + close(conn->sock); + conn->sock = -1; + conn->state = CLOSED; + LOG_INFO("VDF %d: Connection closed", conn->vdf.idx); + } +} + +ssize_t read_data(struct vdf_client *client, struct vdf_conn *conn) +{ + ssize_t bytes = read(conn->sock, conn->read_buf + conn->buf_pos, + sizeof(conn->read_buf) - conn->buf_pos); + if ((bytes < 0 && errno != EAGAIN) || bytes == 0) { + if (bytes == 0) { + LOG_ERROR("VDF %d: Unexpected EOF", conn->vdf.idx); + } else { + perror("read"); + } + stop_conn(client, conn); + close_conn(conn); + } else if (bytes > 0) { + conn->buf_pos += bytes; + return conn->buf_pos; + } + return bytes; +} + +void write_data(struct vdf_conn *conn, const char *buf, size_t size) +{ + ssize_t bytes = write(conn->sock, buf, size); + if (bytes < 0) { + perror("write"); + throw std::runtime_error("Write error"); + } +} + +void handle_iters(struct vdf_client *client, struct vdf_conn *conn) +{ + char *buf = conn->read_buf; + char iters_size_buf[3] = {0}, iters_buf[16]; + uint64_t iters; + uint32_t bytes = conn->buf_pos, iters_size; + + while (bytes) { + memcpy(iters_size_buf, buf, 2); + iters_size = strtoul(iters_size_buf, NULL, 10); + if (iters_size > sizeof(iters_buf) || bytes < 2 + iters_size) { + LOG_ERROR("Bad iters data size: %u", bytes); + throw std::runtime_error("Bad data size"); + } + //buf[2 + iters_size] = '\0'; + memcpy(iters_buf, &buf[2], iters_size); + iters_buf[iters_size] = '\0'; + iters = strtoul(iters_buf, NULL, 10); + + if (iters) { + LOG_DEBUG("VDF %d: Requested proof for iters=%lu", conn->vdf.idx, iters); + hw_request_proof(&conn->vdf, iters, false); + } else { + LOG_INFO("VDF %d: Stop requested", conn->vdf.idx); + stop_conn(client, conn); + bytes -= 2 + iters_size; + break; + } + + bytes -= 2 + iters_size; + buf += 2 + iters_size; + } + if (!bytes) { + conn->buf_pos = 0; + } + if (!conn->vdf.req_proofs.empty()) { + size_t n_proofs = conn->vdf.req_proofs.size(); + char iters_str[100]; + size_t pos = 0; + + for (size_t i = 0; i < n_proofs; i++) { + pos += snprintf(&iters_str[pos], sizeof(iters_str) - pos, "%s%lu", + i ? ", " : "", conn->vdf.req_proofs[i].iters); + if (pos >= sizeof(iters_str) - 1) { + break; + } + } + LOG_INFO("VDF %d: Queued proofs for iters: [%s]", conn->vdf.idx, iters_str); + } +} + +void tl_enc_hex(char *out_data, uint8_t *data, size_t size) +{ + // Hex encode proof data for timelord + for (size_t i = 0; i < size; i++) { + snprintf(&out_data[i * 2], 3, "%02hhx", data[i]); + } +} + +void handle_proofs(struct vdf_client *client, struct vdf_conn *conn) +{ + struct vdf_proof *proof; + int i; + while ((i = hw_retrieve_proof(&conn->vdf, &proof)) >= 0) { + uint8_t data[8 + 8 + 1 + BQFC_FORM_SIZE * 2]; + char tl_data[sizeof(data) * 2 + 5] = {0}; + + LOG_INFO("VDF %d: Proof retrieved for iters=%lu", conn->vdf.idx, proof->iters); + + Int64ToBytes(&data[0], proof->iters); + Int64ToBytes(&data[8], BQFC_FORM_SIZE); + memcpy(&data[16], proof->y, BQFC_FORM_SIZE); + data[16 + BQFC_FORM_SIZE] = i; + memcpy(&data[17 + BQFC_FORM_SIZE], proof->proof, BQFC_FORM_SIZE); + + tl_enc_hex(&tl_data[4], data, sizeof(data)); + Int32ToBytes((uint8_t *)tl_data, (sizeof(data) + i * sizeof(vdf_proof_segm)) * 2); + write_data(conn, tl_data, sizeof(tl_data) - 1); + while (i) { + struct vdf_proof_segm *segm = (struct vdf_proof_segm *)data; + + i--; + //proof = conn->vdf.chkp_proofs[i]; + proof = &conn->vdf.proofs[proof->prev]; + Int64ToBytes(segm->iters, proof->seg_iters); + memcpy(segm->B, proof->B, sizeof(proof->B)); + memcpy(segm->proof, proof->proof, sizeof(proof->proof)); + + tl_enc_hex(tl_data, data, sizeof(*segm)); + write_data(conn, tl_data, sizeof(*segm) * 2); + } + } +} + +void handle_conn(struct vdf_client *client, struct vdf_conn *conn) +{ + ssize_t bytes; + char *buf = conn->read_buf; + struct vdf_state *vdf = &conn->vdf; + + if (g_stopping && conn->state != CLOSED && conn->state != STOPPED) { + LOG_INFO("VDF %d: Global stop requested", conn->vdf.idx); + stop_conn(client, conn); + } + + if (conn->state == WAITING) { + uint64_t d_size; + char d_str[350]; + uint64_t n_iters = 2000UL * 1000 * 1000; + uint8_t *init_form; + + bytes = read_data(client, conn); + if (bytes < 5) { + /* Expecting discr size and discriminant */ + return; + } + + if (buf[0] != 'S' && buf[0] != 'N' && buf[0] != 'T') { + throw std::runtime_error("Bad initial data from timelord"); + } + + d_size = strtoul(&buf[1], NULL, 10); + if ((uint64_t)bytes < 4 + d_size + 1) { + /* Expecting initial form after discriminant */ + return; + } + memcpy(d_str, &buf[4], d_size); + d_str[d_size] = '\0'; + if ((uint64_t)bytes != 4 + d_size + 1 + buf[4 + d_size]) { + LOG_ERROR("Bad data size: %zd", bytes); + throw std::runtime_error("Bad data size"); + } + + init_form = (uint8_t *)&buf[4 + d_size + 1]; + init_vdf_state(vdf, &client->opts.vpo, d_str, init_form, n_iters, vdf->idx); + start_hw_vdf(client->drv, vdf->D.impl, vdf->last_val.a, vdf->last_val.b, + vdf->target_iters, vdf->idx); + write_data(conn, "OK", 2); + conn->state = RUNNING; + conn->buf_pos = 0; + LOG_INFO("VDF %d: Received challenge, running", vdf->idx); + } else if (conn->state == RUNNING || conn->state == IDLING) { + handle_proofs(client, conn); + bytes = read_data(client, conn); + if (bytes <= 0) { + return; + } + + handle_iters(client, conn); + } + if (conn->state == STOPPED) { + bytes = read_data(client, conn); + if (bytes != 3 || memcmp(buf, "ACK", 3)) { + LOG_ERROR("Bad data size after stop: %zd", bytes); + } + close_conn(conn); + } else if (conn->state == CLOSED && !g_stopping) { + init_conn(conn, client->opts.ip, client->opts.port); + } +} + +void event_loop(struct vdf_client *client) +{ + uint64_t loop_cnt = 0; + uint32_t temp_period = chia_vdf_is_emu ? 200 : 20000; + while(true) { + uint8_t running_mask = 0; + uint8_t temp_flag = loop_cnt % temp_period ? 0 : HW_VDF_TEMP_FLAG; + + for (uint8_t i = 0; i < N_HW_VDFS; i++) { + if (!(client->opts.vdfs_mask & (1 << i))) { + continue; + } + handle_conn(client, &client->conns[i]); + if (client->conns[i].state == RUNNING) { + running_mask |= 1 << i; + } + } + + if (running_mask) { + read_hw_status(client->drv, running_mask | temp_flag, client->values); + } else if (g_stopping) { + uint8_t n_closed = 0; + for (uint8_t i = 0; i < N_HW_VDFS; i++) { + if (client->conns[i].state == CLOSED) { + n_closed++; + } + } + if (n_closed == N_HW_VDFS) { + LOG_INFO("All VDFs stopped, exiting"); + break; + } + } + + for (uint8_t i = 0; i < N_HW_VDFS; i++) { + if (running_mask & (1 << i)) { + struct vdf_state *vdf = &client->conns[i].vdf; + + if (hw_proof_add_value(vdf, &client->values[i]) < 0) { + size_t pos = 0; + form *f; + + stop_hw_vdf(client->drv, vdf->idx); + f = hw_proof_last_good_form(vdf, &pos); + vdf->iters_offset = pos * vdf->interval; + + if (client->opts.auto_freq) { + adjust_hw_freq(client->drv, running_mask & ~(1 << i), -1); + } + + LOG_INFO("VDF %d: Restarting VDF at %lu iters", + vdf->idx, vdf->iters_offset); + start_hw_vdf(client->drv, vdf->D.impl, f->a.impl, f->b.impl, + vdf->target_iters - vdf->iters_offset, vdf->idx); + } + if (client->conns[i].vdf.completed) { + stop_hw_vdf(client->drv, i); + client->conns[i].state = IDLING; + } + } + } + + if (client->opts.auto_freq && !(loop_cnt % 256)) { + uint64_t elapsed = vdf_get_elapsed_us(client->drv->last_freq_update); + if (elapsed / 1000000 >= client->opts.auto_freq_period) { + adjust_hw_freq(client->drv, running_mask, 1); + } + } + + if (chia_vdf_is_emu) { + usleep(50000); + } + loop_cnt++; + } +} + +int parse_opts(int argc, char **argv, struct vdf_client_opts *opts) +{ + const struct option long_opts[] = { + {"freq", required_argument, NULL, 1}, + {"voltage", required_argument, NULL, 1}, + {"ip", required_argument, NULL, 1}, + {"vdfs-mask", required_argument, NULL, 1}, + {"vdf-threads", required_argument, NULL, 1}, + {"proof-threads", required_argument, NULL, 1}, + {"list", no_argument, NULL, 1}, + {"auto-freq-period", required_argument, NULL, 1}, + {0} + }; + int long_idx = -1; + int ret; + + opts->voltage = HW_VDF_DEF_VOLTAGE; + opts->freq = HW_VDF_DEF_FREQ; + opts->ip = INADDR_LOOPBACK; + opts->port = 0; + opts->n_vdfs = 3; + opts->do_list = false; + opts->auto_freq = false; + opts->vpo.max_aux_threads = HW_VDF_DEFAULT_MAX_AUX_THREADS; + opts->vpo.max_proof_threads = 0; + opts->vdfs_mask = 0; + + while ((ret = getopt_long(argc, argv, "", long_opts, &long_idx)) == 1) { + if (long_idx == 0) { + opts->freq = strtod(optarg, NULL); + } else if (long_idx == 1) { + opts->voltage = strtod(optarg, NULL); + } else if (long_idx == 2) { + opts->ip = ntohl(inet_addr(optarg)); + } else if (long_idx == 3) { + opts->vdfs_mask = strtoul(optarg, NULL, 0); + } else if (long_idx == 4) { + opts->vpo.max_aux_threads = strtoul(optarg, NULL, 0); + } else if (long_idx == 5) { + opts->vpo.max_proof_threads = strtoul(optarg, NULL, 0); + } else if (long_idx == 6) { + opts->do_list = true; + } else if (long_idx == 7) { + opts->auto_freq = true; + opts->auto_freq_period = strtoul(optarg, NULL, 0); + } + } + if (ret != -1) { + LOG_SIMPLE("Invalid option"); + return -1; + } + if (opts->do_list) { + return 0; + } + if (opts->voltage == 0.0 || opts->freq == 0.0) { + LOG_SIMPLE("Invalid freq or voltage specified"); + return -1; + } + if (opts->freq < 200 || opts->freq > 2200) { + LOG_SIMPLE("Frequency is outside the allowed range"); + return -1; + } + if (opts->voltage < 0.7 || opts->voltage > 1.0) { + LOG_SIMPLE("Voltage is outside the allowed range"); + return -1; + } + if (opts->ip == INADDR_NONE) { + LOG_SIMPLE("Invalid IP address specified"); + return -1; + } + if (opts->vdfs_mask > 7) { + LOG_SIMPLE("Invalid VDFs mask"); + return -1; + } + if (opts->vpo.max_aux_threads < 2 || opts->vpo.max_aux_threads > HW_VDF_MAX_AUX_THREADS) { + LOG_SIMPLE("Number of VDF threads must be between 2 and %d", + HW_VDF_MAX_AUX_THREADS); + return -1; + } + if (opts->vpo.max_proof_threads >= opts->vpo.max_aux_threads) { + LOG_SIMPLE("Number of proof threads must be less than VDF threads"); + return -1; + } + if (opts->auto_freq && opts->auto_freq_period < 10) { + LOG_SIMPLE("Invalid auto freq period"); + return -1; + } + + if (optind == argc) { + return -1; + } + opts->port = atoi(argv[optind]); + if (argc > optind + 1) { + opts->n_vdfs = atoi(argv[optind + 1]); + } + if (!opts->port || opts->n_vdfs < 1 || opts->n_vdfs > 3) { + LOG_SIMPLE("Invalid port or VDF count"); + return -1; + } + + return 0; +} + +int hw_vdf_client_main(int argc, char **argv) +{ + struct vdf_client client; + struct sigaction sa = {0}; + + if (parse_opts(argc, argv, &client.opts) < 0) { + LOG_SIMPLE("\nUsage: %s [OPTIONS] PORT [N_VDFS]\n" + "List of options [default, min - max]:\n" + " --freq N - set ASIC frequency [%d, 200 - 2200]\n" + " --voltage N - set board voltage [%.2f, 0.7 - 1.0]\n" + " --ip A.B.C.D - timelord IP address [localhost]\n" + " --vdfs-mask N - mask for enabling VDF engines [7, 1 - 7]\n" + " --vdf-threads N - number of software threads per VDF engine [4, 2 - 64]\n" + " --proof-threads N - number of proof threads per VDF engine\n" + " --auto-freq-period N - auto-adjust frequency every N seconds [0, 10 - inf]\n" + " --list - list available devices and exit", + argv[0], (int)HW_VDF_DEF_FREQ, HW_VDF_DEF_VOLTAGE); + return 1; + } + + if (client.opts.do_list) { + LOG_SIMPLE("List of available devices:"); + return list_hw() ? 1 : 0; + } + + client.drv = init_hw(client.opts.freq, client.opts.voltage); + if (!client.drv) { + return 1; + } + + init_vdf_client(&client); + + sa.sa_handler = signal_handler; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + event_loop(&client); + + stop_hw(client.drv); + clear_vdf_client(&client); + return 0; +} + +int main(int argc, char **argv) +{ + VdfBaseInit(); + return hw_vdf_client_main(argc, argv); +} diff --git a/src/hw/pll_freqs.cpp b/src/hw/pll_freqs.cpp new file mode 100644 index 00000000..4ded3202 --- /dev/null +++ b/src/hw/pll_freqs.cpp @@ -0,0 +1,8018 @@ +#include "pll_freqs.hpp" + +double pll_filter_ranges[VALID_PLL_FILTER_RANGES] = { + 7.5, + 11.0, + 18.0, + 30.0, + 50.0, + 80.0, + 130.0, + 200.0 +}; + +pll_entry pll_entries[VALID_PLL_FREQS] = { + {18.75, {0, 2, 31}}, + {19.35483870967742, {0, 2, 30}}, + {19.375, {9, 30, 31}}, + {19.444444444444443, {8, 27, 31}}, + {19.53125, {7, 24, 31}}, + {19.642857142857142, {6, 21, 31}}, + {19.791666666666668, {5, 18, 31}}, + {20.0, {0, 2, 29}}, + {20.071684587813618, {8, 27, 30}}, + {20.13888888888889, {8, 28, 31}}, + {20.161290322580644, {7, 24, 30}}, + {20.276497695852534, {6, 21, 30}}, + {20.3125, {3, 12, 31}}, + {20.43010752688172, {5, 18, 30}}, + {20.53571428571429, {6, 22, 31}}, + {20.625, {9, 32, 31}}, + {20.64516129032258, {4, 15, 30}}, + {20.666666666666668, {9, 30, 29}}, + {20.689655172413794, {0, 2, 28}}, + {20.74074074074074, {8, 27, 29}}, + {20.788530465949822, {8, 28, 30}}, + {20.833333333333332, {7, 24, 29}}, + {20.833333333333336, {2, 9, 31}}, + {20.952380952380953, {6, 21, 29}}, + {20.967741935483872, {3, 12, 30}}, + {21.09375, {7, 26, 31}}, + {21.11111111111111, {5, 18, 29}}, + {21.19815668202765, {6, 22, 30}}, + {21.25, {4, 16, 31}}, + {21.29032258064516, {9, 32, 30}}, + {21.333333333333332, {4, 15, 29}}, + {21.379310344827587, {9, 30, 28}}, + {21.428571428571427, {0, 2, 27}}, + {21.42857142857143, {6, 23, 31}}, + {21.455938697318008, {8, 27, 28}}, + {21.48148148148148, {8, 28, 29}}, + {21.50537634408602, {8, 29, 30}}, + {21.505376344086024, {2, 9, 30}}, + {21.52777777777778, {8, 30, 31}}, + {21.551724137931036, {7, 24, 28}}, + {21.666666666666668, {3, 12, 29}}, + {21.67487684729064, {6, 21, 28}}, + {21.774193548387096, {7, 26, 30}}, + {21.839080459770116, {5, 18, 28}}, + {21.875, {1, 6, 31}}, + {21.90476190476191, {6, 22, 29}}, + {21.93548387096774, {4, 16, 30}}, + {22.0, {9, 32, 29}}, + {22.06896551724138, {4, 15, 28}}, + {22.11981566820277, {6, 23, 30}}, + {22.142857142857142, {9, 30, 27}}, + {22.22222222222222, {0, 2, 26}}, + {22.222222222222225, {2, 9, 29}}, + {22.321428571428573, {7, 24, 27}}, + {22.413793103448278, {3, 12, 28}}, + {22.448979591836736, {6, 21, 27}}, + {22.5, {7, 26, 29}}, + {22.580645161290324, {1, 6, 30}}, + {22.61904761904762, {5, 18, 27}}, + {22.65625, {7, 28, 31}}, + {22.66009852216749, {6, 22, 28}}, + {22.666666666666668, {4, 16, 29}}, + {22.75862068965517, {9, 32, 28}}, + {22.857142857142858, {4, 15, 27}}, + {22.916666666666664, {8, 32, 31}}, + {22.916666666666668, {2, 10, 31}}, + {22.939068100358423, {8, 31, 30}}, + {22.962962962962962, {9, 30, 26}}, + {22.962962962962965, {8, 30, 29}}, + {22.988505747126435, {8, 29, 28}}, + {22.98850574712644, {2, 9, 28}}, + {23.015873015873016, {8, 28, 27}}, + {23.041474654377883, {6, 24, 30}}, + {23.045267489711932, {8, 27, 26}}, + {23.076923076923077, {0, 2, 25}}, + {23.125, {9, 36, 31}}, + {23.14814814814815, {7, 24, 26}}, + {23.214285714285715, {3, 12, 27}}, + {23.225806451612904, {4, 17, 30}}, + {23.275862068965516, {7, 26, 28}}, + {23.28042328042328, {6, 21, 26}}, + {23.333333333333332, {1, 6, 29}}, + {23.387096774193548, {7, 28, 30}}, + {23.4375, {3, 14, 31}}, + {23.448275862068964, {4, 16, 28}}, + {23.45679012345679, {5, 18, 26}}, + {23.469387755102044, {6, 22, 27}}, + {23.571428571428573, {9, 32, 27}}, + {23.61111111111111, {8, 33, 31}}, + {23.645320197044338, {6, 23, 28}}, + {23.65591397849462, {8, 32, 30}}, + {23.655913978494624, {2, 10, 30}}, + {23.703703703703702, {4, 15, 26}}, + {23.75, {4, 18, 31}}, + {23.754789272030653, {8, 30, 28}}, + {23.809523809523807, {8, 29, 27}}, + {23.80952380952381, {6, 24, 29}}, + {23.809523809523814, {2, 9, 27}}, + {23.846153846153847, {9, 30, 25}}, + {23.868312757201647, {8, 28, 26}}, + {23.870967741935484, {9, 36, 30}}, + {23.93162393162393, {8, 27, 25}}, + {23.958333333333336, {5, 22, 31}}, + {23.963133640552996, {6, 25, 30}}, + {24.0, {0, 2, 24}}, + {24.03846153846154, {7, 24, 25}}, + {24.074074074074073, {3, 12, 26}}, + {24.107142857142858, {7, 26, 27}}, + {24.137931034482758, {1, 6, 28}}, + {24.166666666666668, {7, 28, 29}}, + {24.175824175824175, {6, 21, 25}}, + {24.193548387096776, {3, 14, 30}}, + {24.21875, {7, 30, 31}}, + {24.285714285714285, {4, 16, 27}}, + {24.305555555555554, {8, 34, 31}}, + {24.338624338624342, {6, 22, 26}}, + {24.35897435897436, {5, 18, 25}}, + {24.372759856630825, {8, 33, 30}}, + {24.375, {9, 38, 31}}, + {24.444444444444443, {9, 32, 26}}, + {24.444444444444446, {2, 10, 29}}, + {24.48979591836735, {6, 23, 27}}, + {24.516129032258064, {4, 18, 30}}, + {24.521072796934867, {8, 31, 28}}, + {24.603174603174605, {8, 30, 27}}, + {24.615384615384617, {4, 15, 25}}, + {24.630541871921185, {6, 24, 28}}, + {24.666666666666668, {9, 36, 29}}, + {24.691358024691358, {8, 29, 26}}, + {24.69135802469136, {2, 9, 26}}, + {24.731182795698928, {5, 22, 30}}, + {24.761904761904763, {6, 25, 29}}, + {24.786324786324787, {8, 28, 25}}, + {24.8, {9, 30, 24}}, + {24.82758620689655, {4, 17, 28}}, + {24.88479262672811, {6, 26, 30}}, + {24.888888888888886, {8, 27, 24}}, + {25.0, {0, 2, 23}}, + {25.089605734767023, {8, 34, 30}}, + {25.142857142857142, {6, 21, 24}}, + {25.161290322580644, {9, 38, 30}}, + {25.185185185185183, {8, 33, 29}}, + {25.185185185185187, {4, 16, 26}}, + {25.274725274725277, {6, 22, 25}}, + {25.287356321839077, {8, 32, 28}}, + {25.28735632183908, {2, 10, 28}}, + {25.333333333333332, {4, 18, 29}}, + {25.333333333333336, {5, 18, 24}}, + {25.384615384615383, {9, 32, 25}}, + {25.396825396825395, {8, 31, 27}}, + {25.3968253968254, {6, 23, 26}}, + {25.510204081632654, {6, 24, 27}}, + {25.514403292181072, {8, 30, 26}}, + {25.517241379310345, {9, 36, 28}}, + {25.555555555555557, {5, 22, 29}}, + {25.6, {4, 15, 24}}, + {25.615763546798032, {6, 25, 28}}, + {25.625, {9, 40, 31}}, + {25.64102564102564, {8, 29, 25}}, + {25.641025641025642, {2, 9, 25}}, + {25.694444444444443, {8, 36, 31}}, + {25.714285714285715, {4, 17, 27}}, + {25.77777777777778, {8, 28, 24}}, + {25.78125, {7, 32, 31}}, + {25.806451612903224, {0, 3, 30}}, + {25.833333333333332, {9, 30, 23}}, + {25.862068965517242, {3, 14, 28}}, + {25.892857142857142, {7, 28, 27}}, + {25.892857142857146, {6, 28, 31}}, + {25.925925925925924, {8, 27, 23}}, + {25.925925925925927, {1, 6, 26}}, + {25.96153846153846, {7, 26, 25}}, + {26.0, {3, 12, 24}}, + {26.041666666666668, {7, 24, 23}}, + {26.053639846743295, {8, 33, 28}}, + {26.08695652173913, {0, 2, 22}}, + {26.153846153846153, {4, 16, 25}}, + {26.190476190476186, {8, 32, 27}}, + {26.19047619047619, {6, 21, 23}}, + {26.190476190476193, {2, 10, 27}}, + {26.20689655172414, {4, 18, 28}}, + {26.25, {4, 20, 31}}, + {26.28571428571429, {6, 22, 24}}, + {26.33744855967078, {8, 31, 26}}, + {26.373626373626376, {6, 23, 25}}, + {26.38888888888889, {5, 18, 23}}, + {26.4, {9, 32, 24}}, + {26.428571428571427, {9, 36, 27}}, + {26.436781609195403, {5, 22, 28}}, + {26.451612903225808, {9, 40, 30}}, + {26.455026455026456, {6, 24, 26}}, + {26.495726495726498, {8, 30, 25}}, + {26.523297491039425, {8, 36, 30}}, + {26.53061224489796, {6, 25, 27}}, + {26.5625, {3, 16, 31}}, + {26.60098522167488, {6, 26, 28}}, + {26.612903225806452, {7, 32, 30}}, + {26.666666666666664, {8, 29, 24}}, + {26.666666666666668, {4, 15, 23}}, + {26.66666666666667, {2, 9, 24}}, + {26.724137931034484, {7, 30, 28}}, + {26.728110599078345, {6, 28, 30}}, + {26.785714285714285, {3, 14, 27}}, + {26.78571428571429, {6, 29, 31}}, + {26.81992337164751, {8, 34, 28}}, + {26.85185185185185, {8, 28, 23}}, + {26.875, {9, 42, 31}}, + {26.881720430107528, {5, 24, 30}}, + {26.896551724137932, {9, 38, 28}}, + {26.923076923076923, {1, 6, 25}}, + {26.956521739130434, {9, 30, 22}}, + {26.984126984126984, {8, 33, 27}}, + {27.0, {7, 26, 24}}, + {27.053140096618357, {8, 27, 22}}, + {27.083333333333332, {3, 12, 23}}, + {27.083333333333336, {2, 12, 31}}, + {27.096774193548388, {4, 20, 30}}, + {27.142857142857142, {4, 18, 27}}, + {27.16049382716049, {8, 32, 26}}, + {27.160493827160494, {2, 10, 26}}, + {27.17391304347826, {7, 24, 22}}, + {27.2, {4, 16, 24}}, + {27.240143369175627, {8, 37, 30}}, + {27.272727272727273, {0, 2, 21}}, + {27.32919254658385, {6, 21, 22}}, + {27.333333333333332, {9, 40, 29}}, + {27.34375, {7, 34, 31}}, + {27.35042735042735, {8, 31, 25}}, + {27.380952380952383, {6, 22, 23}}, + {27.407407407407405, {8, 36, 29}}, + {27.40740740740741, {9, 36, 26}}, + {27.419354838709676, {3, 16, 30}}, + {27.42857142857143, {6, 23, 24}}, + {27.472527472527474, {6, 24, 25}}, + {27.5, {9, 32, 23}}, + {27.513227513227516, {6, 25, 26}}, + {27.536231884057973, {5, 18, 22}}, + {27.551020408163264, {6, 26, 27}}, + {27.555555555555557, {8, 30, 24}}, + {27.586206896551722, {0, 3, 28}}, + {27.619047619047624, {6, 28, 29}}, + {27.64976958525346, {6, 29, 30}}, + {27.678571428571427, {7, 30, 27}}, + {27.67857142857143, {6, 30, 31}}, + {27.692307692307693, {4, 17, 25}}, + {27.741935483870968, {9, 42, 30}}, + {27.777777777777775, {8, 29, 23}}, + {27.77777777777778, {3, 14, 26}}, + {27.777777777777782, {2, 9, 23}}, + {27.82608695652174, {4, 15, 22}}, + {27.857142857142858, {9, 38, 27}}, + {27.884615384615383, {7, 28, 25}}, + {27.956989247311828, {8, 38, 30}}, + {27.95698924731183, {2, 12, 30}}, + {27.983539094650205, {8, 33, 26}}, + {28.0, {1, 6, 24}}, + {28.019323671497585, {8, 28, 22}}, + {28.125, {7, 26, 23}}, + {28.125000000000004, {5, 26, 31}}, + {28.14814814814815, {4, 18, 26}}, + {28.181818181818183, {9, 30, 21}}, + {28.2051282051282, {8, 32, 25}}, + {28.205128205128208, {2, 10, 25}}, + {28.225806451612904, {7, 34, 30}}, + {28.26086956521739, {3, 12, 22}}, + {28.275862068965516, {9, 40, 28}}, + {28.28282828282828, {8, 27, 21}}, + {28.333333333333332, {4, 16, 23}}, + {28.352490421455936, {8, 36, 28}}, + {28.387096774193548, {4, 21, 30}}, + {28.395061728395063, {5, 22, 26}}, + {28.40909090909091, {7, 24, 21}}, + {28.444444444444443, {8, 31, 24}}, + {28.448275862068964, {7, 32, 28}}, + {28.46153846153846, {9, 36, 25}}, + {28.47222222222222, {8, 40, 31}}, + {28.57142857142857, {6, 21, 21}}, + {28.571428571428573, {0, 2, 20}}, + {28.571428571428577, {6, 22, 22}}, + {28.666666666666668, {9, 42, 29}}, + {28.67383512544803, {8, 39, 30}}, + {28.695652173913043, {9, 32, 22}}, + {28.703703703703702, {7, 30, 26}}, + {28.703703703703706, {8, 30, 23}}, + {28.73563218390805, {5, 24, 28}}, + {28.75, {4, 22, 31}}, + {28.78787878787879, {5, 18, 21}}, + {28.8, {4, 17, 24}}, + {28.806584362139915, {8, 34, 26}}, + {28.846153846153847, {3, 14, 25}}, + {28.88888888888889, {9, 38, 26}}, + {28.888888888888893, {2, 12, 29}}, + {28.90625, {7, 36, 31}}, + {28.96551724137931, {4, 20, 28}}, + {28.98550724637681, {8, 29, 22}}, + {28.985507246376816, {2, 9, 22}}, + {29.0, {7, 28, 24}}, + {29.032258064516128, {1, 8, 30}}, + {29.03225806451613, {5, 26, 30}}, + {29.05982905982906, {8, 33, 25}}, + {29.09090909090909, {4, 15, 21}}, + {29.118773946360154, {8, 37, 28}}, + {29.166666666666664, {8, 41, 31}}, + {29.166666666666668, {1, 6, 23}}, + {29.23076923076923, {4, 18, 25}}, + {29.285714285714285, {9, 40, 27}}, + {29.292929292929294, {8, 28, 21}}, + {29.310344827586206, {3, 16, 28}}, + {29.33333333333333, {8, 32, 24}}, + {29.333333333333332, {4, 21, 29}}, + {29.333333333333336, {2, 10, 24}}, + {29.347826086956523, {7, 26, 22}}, + {29.365079365079364, {8, 36, 27}}, + {29.375, {9, 46, 31}}, + {29.390681003584227, {8, 40, 30}}, + {29.464285714285715, {7, 32, 27}}, + {29.48717948717949, {5, 22, 25}}, + {29.493087557603687, {6, 31, 30}}, + {29.523809523809526, {9, 30, 20}}, + {29.545454545454547, {3, 12, 21}}, + {29.55665024630542, {6, 29, 28}}, + {29.565217391304348, {4, 16, 22}}, + {29.59183673469388, {6, 28, 27}}, + {29.6, {9, 36, 24}}, + {29.629629629629626, {8, 27, 20}}, + {29.62962962962963, {8, 31, 23}}, + {29.655172413793103, {9, 42, 28}}, + {29.67032967032967, {6, 26, 25}}, + {29.677419354838708, {4, 22, 30}}, + {29.6875, {3, 18, 31}}, + {29.714285714285715, {6, 25, 24}}, + {29.761904761904763, {7, 24, 20}}, + {29.807692307692307, {7, 30, 25}}, + {29.813664596273295, {6, 23, 22}}, + {29.838709677419356, {7, 36, 30}}, + {29.86111111111111, {8, 42, 31}}, + {29.870129870129873, {6, 22, 21}}, + {29.885057471264368, {8, 38, 28}}, + {29.88505747126437, {2, 12, 28}}, + {29.91452991452991, {8, 34, 25}}, + {29.931972789115644, {6, 21, 20}}, + {29.95169082125604, {8, 30, 22}}, + {30.0, {0, 2, 19}}, + {30.000000000000004, {5, 26, 29}}, + {30.10752688172043, {8, 41, 30}}, + {30.107526881720432, {2, 13, 30}}, + {30.158730158730158, {8, 37, 27}}, + {30.15873015873016, {5, 18, 20}}, + {30.17241379310345, {7, 34, 28}}, + {30.208333333333332, {7, 28, 23}}, + {30.208333333333336, {5, 28, 31}}, + {30.22222222222222, {8, 33, 24}}, + {30.3030303030303, {8, 29, 21}}, + {30.303030303030308, {2, 9, 21}}, + {30.322580645161292, {9, 46, 30}}, + {30.344827586206897, {4, 21, 28}}, + {30.357142857142858, {3, 16, 27}}, + {30.37037037037037, {9, 40, 26}}, + {30.4, {4, 18, 24}}, + {30.414746543778804, {6, 32, 30}}, + {30.434782608695652, {1, 6, 22}}, + {30.45267489711934, {8, 36, 26}}, + {30.46875, {7, 38, 31}}, + {30.476190476190474, {4, 15, 20}}, + {30.476190476190478, {6, 31, 29}}, + {30.541871921182267, {6, 30, 28}}, + {30.555555555555554, {8, 32, 23}}, + {30.555555555555557, {2, 10, 23}}, + {30.612244897959187, {6, 29, 27}}, + {30.625, {9, 48, 31}}, + {30.64516129032258, {3, 18, 30}}, + {30.65134099616858, {8, 39, 28}}, + {30.666666666666668, {4, 22, 29}}, + {30.66666666666667, {5, 22, 24}}, + {30.681818181818183, {7, 26, 21}}, + {30.68783068783069, {8, 28, 20}}, + {30.714285714285715, {9, 42, 27}}, + {30.76923076923077, {0, 3, 25}}, + {30.82437275985663, {8, 42, 30}}, + {30.833333333333332, {9, 36, 23}}, + {30.857142857142858, {6, 26, 24}}, + {30.8641975308642, {5, 24, 26}}, + {30.90909090909091, {4, 16, 21}}, + {30.917874396135264, {8, 31, 22}}, + {30.952380952380953, {3, 12, 20}}, + {30.952380952380956, {2, 12, 27}}, + {30.967741935483872, {4, 23, 30}}, + {31.0, {9, 30, 19}}, + {31.03448275862069, {1, 8, 28}}, + {31.034482758620694, {5, 26, 28}}, + {31.055900621118013, {6, 24, 22}}, + {31.111111111111107, {8, 27, 19}}, + {31.11111111111111, {4, 20, 26}}, + {31.168831168831172, {6, 23, 21}}, + {31.182795698924732, {5, 28, 30}}, + {31.2, {9, 38, 24}}, + {31.25, {7, 24, 19}}, + {31.250000000000004, {2, 14, 31}}, + {31.275720164609055, {8, 37, 26}}, + {31.292517006802726, {6, 22, 20}}, + {31.304347826086957, {4, 17, 22}}, + {31.313131313131315, {8, 30, 21}}, + {31.333333333333332, {9, 46, 29}}, + {31.336405529953918, {6, 33, 30}}, + {31.417624521072796, {8, 40, 28}}, + {31.428571428571427, {6, 21, 19}}, + {31.42857142857143, {6, 32, 29}}, + {31.451612903225808, {7, 38, 30}}, + {31.48148148148148, {8, 33, 23}}, + {31.52173913043478, {7, 28, 22}}, + {31.527093596059114, {6, 31, 28}}, + {31.53846153846154, {9, 40, 25}}, + {31.54121863799283, {8, 43, 30}}, + {31.57894736842105, {0, 2, 18}}, + {31.612903225806452, {9, 48, 30}}, + {31.62393162393162, {8, 36, 25}}, + {31.63265306122449, {6, 30, 27}}, + {31.666666666666668, {5, 18, 19}}, + {31.724137931034484, {4, 22, 28}}, + {31.73076923076923, {7, 32, 25}}, + {31.746031746031743, {8, 29, 20}}, + {31.746031746031747, {8, 39, 27}}, + {31.74603174603175, {2, 9, 20}}, + {31.818181818181817, {1, 6, 21}}, + {31.85185185185185, {9, 42, 26}}, + {31.868131868131872, {6, 28, 25}}, + {31.875, {9, 50, 31}}, + {31.88405797101449, {8, 32, 22}}, + {31.884057971014496, {2, 10, 22}}, + {31.896551724137932, {7, 36, 28}}, + {31.944444444444443, {8, 45, 31}}, + {31.944444444444446, {5, 22, 23}}, + {32.0, {4, 15, 19}}, + {32.03125, {7, 40, 31}}, + {32.05128205128205, {5, 24, 25}}, + {32.098765432098766, {8, 38, 26}}, + {32.142857142857146, {7, 26, 20}}, + {32.17391304347826, {9, 36, 22}}, + {32.183908045977006, {8, 41, 28}}, + {32.18390804597701, {2, 13, 28}}, + {32.22222222222222, {8, 28, 19}}, + {32.25806451612903, {0, 4, 30}}, + {32.25806451612904, {2, 14, 30}}, + {32.291666666666664, {7, 30, 23}}, + {32.29166666666667, {5, 30, 31}}, + {32.298136645962735, {6, 25, 22}}, + {32.30769230769231, {4, 20, 25}}, + {32.323232323232325, {8, 31, 21}}, + {32.38095238095238, {4, 16, 20}}, + {32.407407407407405, {8, 34, 23}}, + {32.41379310344828, {9, 46, 28}}, + {32.46753246753247, {6, 24, 21}}, + {32.47863247863248, {8, 37, 25}}, + {32.5, {3, 12, 19}}, + {32.512315270935964, {6, 32, 28}}, + {32.53968253968254, {8, 40, 27}}, + {32.59259259259259, {8, 43, 29}}, + {32.592592592592595, {4, 21, 26}}, + {32.608695652173914, {3, 14, 22}}, + {32.63157894736842, {9, 30, 18}}, + {32.638888888888886, {8, 46, 31}}, + {32.6530612244898, {6, 23, 20}}, + {32.666666666666664, {9, 48, 29}}, + {32.69230769230769, {3, 16, 25}}, + {32.72727272727273, {4, 17, 21}}, + {32.748538011695906, {8, 27, 18}}, + {32.758620689655174, {3, 18, 28}}, + {32.8, {9, 40, 24}}, + {32.804232804232804, {8, 30, 20}}, + {32.8125, {3, 20, 31}}, + {32.85024154589372, {8, 33, 22}}, + {32.857142857142854, {4, 22, 27}}, + {32.85714285714286, {6, 22, 19}}, + {32.888888888888886, {8, 36, 24}}, + {32.89473684210526, {7, 24, 18}}, + {32.903225806451616, {9, 50, 30}}, + {32.92181069958848, {8, 39, 26}}, + {32.95019157088122, {8, 42, 28}}, + {32.95454545454545, {7, 28, 21}}, + {32.96703296703297, {6, 29, 25}}, + {32.97491039426523, {8, 45, 30}}, + {33.0, {9, 32, 19}}, + {33.035714285714285, {7, 36, 27}}, + {33.04347826086956, {4, 18, 22}}, + {33.064516129032256, {7, 40, 30}}, + {33.07692307692308, {9, 42, 25}}, + {33.08270676691729, {6, 21, 18}}, + {33.10344827586207, {4, 23, 28}}, + {33.125, {9, 52, 31}}, + {33.142857142857146, {6, 28, 24}}, + {33.17972350230415, {6, 35, 30}}, + {33.33333333333333, {8, 29, 19}}, + {33.333333333333336, {0, 2, 17}}, + {33.49753694581281, {6, 33, 28}}, + {33.54037267080746, {6, 26, 22}}, + {33.54838709677419, {4, 25, 30}}, + {33.57142857142857, {9, 46, 27}}, + {33.59375, {7, 42, 31}}, + {33.6, {4, 20, 24}}, + {33.62068965517241, {7, 38, 28}}, + {33.63636363636363, {9, 36, 21}}, + {33.65384615384615, {7, 34, 25}}, + {33.673469387755105, {6, 32, 27}}, + {33.68421052631579, {4, 15, 18}}, + {33.69175627240143, {8, 46, 30}}, + {33.69565217391305, {7, 30, 22}}, + {33.71647509578544, {8, 43, 28}}, + {33.74485596707819, {8, 40, 26}}, + {33.75, {7, 26, 19}}, + {33.76623376623377, {6, 25, 21}}, + {33.77777777777778, {8, 37, 24}}, + {33.793103448275865, {9, 48, 28}}, + {33.81642512077294, {8, 34, 22}}, + {33.84615384615385, {4, 21, 25}}, + {33.86243386243386, {8, 31, 20}}, + {33.86243386243387, {6, 31, 26}}, + {33.87096774193548, {3, 20, 30}}, + {33.91304347826087, {9, 38, 22}}, + {33.91812865497076, {8, 28, 18}}, + {33.92857142857143, {3, 18, 27}}, + {34.0, {4, 16, 19}}, + {34.013605442176875, {6, 24, 20}}, + {34.02777777777778, {8, 48, 31}}, + {34.065934065934066, {6, 30, 25}}, + {34.07407407407407, {8, 45, 29}}, + {34.074074074074076, {4, 22, 26}}, + {34.09090909090909, {3, 14, 21}}, + {34.10138248847926, {6, 36, 30}}, + {34.12698412698413, {8, 42, 27}}, + {34.166666666666664, {9, 40, 23}}, + {34.18803418803419, {8, 39, 25}}, + {34.193548387096776, {9, 52, 30}}, + {34.21052631578947, {3, 12, 18}}, + {34.25925925925926, {8, 36, 23}}, + {34.285714285714285, {4, 17, 20}}, + {34.28571428571429, {6, 23, 19}}, + {34.343434343434346, {8, 33, 21}}, + {34.375, {7, 32, 23}}, + {34.4, {9, 42, 24}}, + {34.40860215053763, {8, 47, 30}}, + {34.40860215053764, {2, 15, 30}}, + {34.44444444444444, {9, 30, 17}}, + {34.44444444444445, {5, 30, 29}}, + {34.48275862068966, {0, 4, 28}}, + {34.523809523809526, {7, 28, 20}}, + {34.54545454545455, {4, 18, 21}}, + {34.5679012345679, {8, 27, 17}}, + {34.567901234567906, {2, 13, 26}}, + {34.58646616541354, {6, 22, 18}}, + {34.61538461538461, {1, 8, 25}}, + {34.61538461538462, {5, 26, 25}}, + {34.666666666666664, {8, 38, 24}}, + {34.66666666666667, {2, 12, 24}}, + {34.67741935483871, {7, 42, 30}}, + {34.69387755102041, {6, 33, 27}}, + {34.72222222222222, {7, 24, 17}}, + {34.73684210526316, {9, 32, 18}}, + {34.78260869565217, {0, 3, 22}}, + {34.81481481481481, {8, 46, 29}}, + {34.81481481481482, {9, 46, 26}}, + {34.82142857142857, {7, 38, 27}}, + {34.82142857142858, {6, 38, 31}}, + {34.83870967741935, {4, 26, 30}}, + {34.84848484848485, {5, 22, 21}}, + {34.92063492063492, {6, 21, 17}}, + {34.920634920634924, {2, 10, 20}}, + {35.0, {1, 6, 19}}, + {35.02304147465438, {6, 37, 30}}, + {35.04273504273504, {8, 40, 25}}, + {35.064935064935064, {6, 26, 21}}, + {35.08771929824561, {8, 29, 18}}, + {35.08771929824562, {2, 9, 18}}, + {35.12544802867384, {8, 48, 30}}, + {35.15625, {7, 44, 31}}, + {35.16483516483517, {6, 31, 25}}, + {35.172413793103445, {9, 50, 28}}, + {35.18518518518518, {8, 37, 23}}, + {35.18518518518519, {5, 18, 17}}, + {35.2, {4, 21, 24}}, + {35.22727272727273, {7, 30, 21}}, + {35.238095238095234, {6, 36, 29}}, + {35.23809523809524, {9, 36, 20}}, + {35.24904214559387, {8, 45, 28}}, + {35.294117647058826, {0, 2, 16}}, + {35.333333333333336, {9, 52, 29}}, + {35.3448275862069, {7, 40, 28}}, + {35.35353535353535, {8, 34, 21}}, + {35.374149659863946, {6, 25, 20}}, + {35.38461538461539, {4, 22, 25}}, + {35.39094650205761, {8, 42, 26}}, + {35.416666666666664, {3, 16, 23}}, + {35.41666666666667, {2, 16, 31}}, + {35.42857142857143, {6, 30, 24}}, + {35.45454545454545, {9, 38, 21}}, + {35.467980295566505, {6, 35, 28}}, + {35.483870967741936, {1, 10, 30}}, + {35.526315789473685, {7, 26, 18}}, + {35.55555555555555, {8, 47, 29}}, + {35.55555555555556, {4, 15, 17}}, + {35.57692307692308, {7, 36, 25}}, + {35.625, {9, 56, 31}}, + {35.63218390804598, {5, 30, 28}}, + {35.65217391304348, {9, 40, 22}}, + {35.714285714285715, {6, 24, 19}}, + {35.748792270531396, {8, 36, 22}}, + {35.78947368421053, {4, 16, 18}}, + {35.80246913580247, {8, 28, 17}}, + {35.802469135802475, {5, 28, 26}}, + {35.833333333333336, {9, 42, 23}}, + {35.842293906810035, {8, 49, 30}}, + {35.86206896551724, {4, 25, 28}}, + {35.869565217391305, {7, 32, 22}}, + {35.8974358974359, {8, 41, 25}}, + {35.9375, {3, 22, 31}}, + {35.9447004608295, {6, 38, 30}}, + {35.97883597883598, {8, 33, 20}}, + {36.0, {4, 17, 19}}, + {36.00000000000001, {5, 26, 24}}, + {36.01532567049808, {8, 46, 28}}, + {36.0248447204969, {6, 28, 22}}, + {36.090225563909776, {6, 23, 18}}, + {36.11111111111111, {8, 38, 23}}, + {36.111111111111114, {3, 12, 17}}, + {36.12903225806452, {4, 27, 30}}, + {36.15384615384615, {9, 46, 25}}, + {36.19047619047619, {4, 18, 20}}, + {36.206896551724135, {3, 20, 28}}, + {36.21399176954732, {8, 43, 26}}, + {36.231884057971016, {5, 24, 22}}, + {36.25, {7, 28, 19}}, + {36.25730994152047, {8, 30, 18}}, + {36.26373626373626, {6, 32, 25}}, + {36.29032258064516, {7, 44, 30}}, + {36.2962962962963, {9, 48, 26}}, + {36.36363636363637, {0, 3, 21}}, + {36.42857142857143, {9, 50, 27}}, + {36.44444444444444, {8, 40, 24}}, + {36.453201970443345, {6, 36, 28}}, + {36.458333333333336, {7, 34, 23}}, + {36.470588235294116, {9, 30, 16}}, + {36.507936507936506, {8, 45, 27}}, + {36.50793650793651, {6, 22, 17}}, + {36.52173913043478, {4, 20, 22}}, + {36.53846153846154, {3, 18, 25}}, + {36.55172413793103, {9, 52, 28}}, + {36.55913978494623, {8, 50, 30}}, + {36.55913978494624, {2, 16, 30}}, + {36.57142857142858, {6, 31, 24}}, + {36.60130718954248, {8, 27, 16}}, + {36.607142857142854, {7, 40, 27}}, + {36.60714285714286, {6, 40, 31}}, + {36.666666666666664, {9, 32, 17}}, + {36.66666666666667, {2, 10, 19}}, + {36.71497584541063, {8, 37, 22}}, + {36.71875, {7, 46, 31}}, + {36.734693877551024, {6, 26, 20}}, + {36.75213675213675, {8, 42, 25}}, + {36.76470588235294, {7, 24, 16}}, + {36.774193548387096, {9, 56, 30}}, + {36.7816091954023, {8, 47, 28}}, + {36.781609195402304, {2, 15, 28}}, + {36.8, {4, 22, 24}}, + {36.80555555555556, {8, 52, 31}}, + {36.8421052631579, {1, 6, 18}}, + {36.86635944700461, {6, 39, 30}}, + {36.875, {9, 58, 31}}, + {36.904761904761905, {7, 30, 20}}, + {36.90476190476191, {5, 30, 27}}, + {36.92307692307692, {4, 23, 25}}, + {36.95652173913044, {3, 16, 22}}, + {36.97478991596638, {6, 21, 16}}, + {37.0, {9, 36, 19}}, + {37.03703703703703, {8, 34, 20}}, + {37.03703703703704, {8, 29, 17}}, + {37.06896551724138, {7, 42, 28}}, + {37.096774193548384, {3, 22, 30}}, + {37.142857142857146, {6, 25, 19}}, + {37.17948717948718, {5, 28, 25}}, + {37.241379310344826, {4, 26, 28}}, + {37.254901960784316, {5, 18, 16}}, + {37.267080745341616, {6, 29, 22}}, + {37.27272727272727, {9, 40, 21}}, + {37.27598566308243, {8, 51, 30}}, + {37.3015873015873, {8, 46, 27}}, + {37.33333333333333, {8, 41, 24}}, + {37.333333333333336, {2, 13, 24}}, + {37.362637362637365, {6, 33, 25}}, + {37.37373737373737, {8, 36, 21}}, + {37.391304347826086, {9, 42, 22}}, + {37.41935483870968, {4, 28, 30}}, + {37.42690058479532, {8, 31, 18}}, + {37.4384236453202, {6, 37, 28}}, + {37.5, {0, 2, 15}}, + {37.50000000000001, {5, 26, 23}}, + {37.547892720306514, {8, 48, 28}}, + {37.59398496240602, {6, 24, 18}}, + {37.6, {9, 46, 24}}, + {37.6068376068376, {8, 43, 25}}, + {37.63440860215054, {5, 34, 30}}, + {37.64705882352941, {4, 15, 16}}, + {37.66233766233767, {6, 28, 21}}, + {37.68115942028985, {8, 38, 22}}, + {37.68115942028986, {2, 12, 22}}, + {37.69230769230769, {9, 48, 25}}, + {37.714285714285715, {6, 32, 24}}, + {37.755102040816325, {6, 36, 27}}, + {37.77777777777778, {4, 16, 17}}, + {37.777777777777786, {2, 16, 29}}, + {37.78801843317973, {6, 40, 30}}, + {37.857142857142854, {9, 52, 27}}, + {37.86008230452675, {8, 45, 26}}, + {37.87878787878788, {5, 24, 21}}, + {37.89473684210526, {4, 17, 18}}, + {37.903225806451616, {7, 46, 30}}, + {37.908496732026144, {8, 28, 16}}, + {37.93103448275862, {1, 10, 28}}, + {37.96296296296296, {8, 40, 23}}, + {37.99283154121864, {8, 52, 30}}, + {38.0, {4, 18, 19}}, + {38.04347826086956, {7, 34, 22}}, + {38.064516129032256, {9, 58, 30}}, + {38.09523809523809, {8, 47, 27}}, + {38.095238095238095, {0, 3, 20}}, + {38.0952380952381, {6, 23, 17}}, + {38.125, {9, 60, 31}}, + {38.1578947368421, {7, 28, 18}}, + {38.18181818181818, {4, 20, 21}}, + {38.19444444444444, {8, 54, 31}}, + {38.22222222222222, {8, 42, 24}}, + {38.23529411764706, {3, 12, 16}}, + {38.26086956521739, {4, 21, 22}}, + {38.27160493827161, {8, 30, 17}}, + {38.28125, {7, 48, 31}}, + {38.314176245210724, {8, 49, 28}}, + {38.333333333333336, {5, 22, 19}}, + {38.38383838383839, {8, 37, 21}}, + {38.392857142857146, {7, 42, 27}}, + {38.4, {4, 23, 24}}, + {38.42364532019705, {6, 38, 28}}, + {38.46153846153846, {0, 4, 25}}, + {38.46153846153847, {2, 14, 25}}, + {38.50931677018634, {6, 30, 22}}, + {38.51851851851851, {8, 51, 29}}, + {38.51851851851852, {4, 25, 26}}, + {38.541666666666664, {7, 36, 23}}, + {38.54166666666667, {5, 36, 31}}, + {38.57142857142857, {6, 26, 19}}, + {38.59649122807017, {8, 32, 18}}, + {38.59649122807018, {2, 10, 18}}, + {38.62068965517241, {4, 27, 28}}, + {38.63636363636363, {3, 16, 21}}, + {38.64734299516908, {8, 39, 22}}, + {38.655462184873954, {6, 22, 16}}, + {38.666666666666664, {4, 28, 29}}, + {38.66666666666667, {5, 28, 24}}, + {38.68312757201646, {8, 46, 26}}, + {38.70967741935484, {0, 5, 30}}, + {38.75, {9, 30, 15}}, + {38.775510204081634, {6, 37, 27}}, + {38.793103448275865, {7, 44, 28}}, + {38.8235294117647, {9, 32, 16}}, + {38.85714285714286, {6, 33, 24}}, + {38.888888888888886, {8, 27, 15}}, + {38.88888888888889, {2, 13, 23}}, + {38.94736842105263, {9, 36, 18}}, + {38.961038961038966, {6, 29, 21}}, + {39.0, {9, 38, 19}}, + {39.04761904761905, {9, 40, 20}}, + {39.0625, {7, 24, 15}}, + {39.08045977011494, {8, 50, 28}}, + {39.08045977011495, {2, 16, 28}}, + {39.09090909090909, {9, 42, 21}}, + {39.097744360902254, {6, 25, 18}}, + {39.11111111111111, {8, 43, 24}}, + {39.130434782608695, {1, 8, 22}}, + {39.1304347826087, {5, 26, 22}}, + {39.15343915343915, {8, 36, 20}}, + {39.166666666666664, {9, 46, 23}}, + {39.2, {9, 48, 24}}, + {39.2156862745098, {8, 29, 16}}, + {39.21568627450981, {2, 9, 16}}, + {39.23076923076923, {9, 50, 25}}, + {39.25925925925926, {9, 52, 26}}, + {39.285714285714285, {6, 21, 15}}, + {39.310344827586206, {9, 56, 28}}, + {39.31623931623931, {8, 45, 25}}, + {39.333333333333336, {9, 58, 29}}, + {39.354838709677416, {9, 60, 30}}, + {39.375, {9, 62, 31}}, + {39.39393939393939, {8, 38, 21}}, + {39.3939393939394, {2, 12, 21}}, + {39.40886699507389, {6, 39, 28}}, + {39.42307692307692, {7, 40, 25}}, + {39.42652329749104, {8, 54, 30}}, + {39.45578231292517, {6, 28, 20}}, + {39.473684210526315, {3, 14, 18}}, + {39.50617283950617, {8, 31, 17}}, + {39.50617283950618, {2, 15, 26}}, + {39.516129032258064, {7, 48, 30}}, + {39.56043956043956, {6, 35, 25}}, + {39.58333333333333, {8, 56, 31}}, + {39.583333333333336, {5, 18, 15}}, + {39.61352657004831, {8, 40, 22}}, + {39.63133640552996, {6, 42, 30}}, + {39.6551724137931, {3, 22, 28}}, + {39.682539682539684, {6, 24, 17}}, + {39.705882352941174, {7, 26, 16}}, + {39.74358974358975, {5, 30, 25}}, + {39.75155279503106, {6, 31, 22}}, + {39.76608187134503, {8, 33, 18}}, + {39.77272727272727, {7, 34, 21}}, + {39.78494623655914, {5, 36, 30}}, + {39.79591836734694, {6, 38, 27}}, + {39.81481481481482, {8, 42, 23}}, + {39.84375, {7, 50, 31}}, + {39.84674329501915, {8, 51, 28}}, + {40.0, {0, 2, 14}}, + {40.00000000000001, {2, 14, 24}}, + {40.143369175627235, {8, 55, 30}}, + {40.17094017094017, {8, 46, 25}}, + {40.17857142857143, {7, 44, 27}}, + {40.211640211640216, {8, 37, 20}}, + {40.21739130434783, {7, 36, 22}}, + {40.229885057471265, {5, 34, 28}}, + {40.25974025974026, {6, 30, 21}}, + {40.27777777777778, {8, 28, 15}}, + {40.32258064516129, {3, 24, 30}}, + {40.32921810699589, {8, 48, 26}}, + {40.33613445378152, {6, 23, 16}}, + {40.35087719298246, {5, 22, 18}}, + {40.38461538461539, {3, 20, 25}}, + {40.39408866995074, {6, 40, 28}}, + {40.40404040404041, {8, 39, 21}}, + {40.476190476190474, {3, 16, 20}}, + {40.47619047619048, {2, 16, 27}}, + {40.51724137931034, {7, 46, 28}}, + {40.52287581699346, {8, 30, 16}}, + {40.55299539170507, {6, 43, 30}}, + {40.57971014492753, {8, 41, 22}}, + {40.57971014492754, {2, 13, 22}}, + {40.6015037593985, {6, 26, 18}}, + {40.61302681992338, {8, 52, 28}}, + {40.625, {3, 12, 15}}, + {40.645161290322584, {9, 62, 30}}, + {40.65934065934066, {6, 36, 25}}, + {40.666666666666664, {9, 60, 29}}, + {40.689655172413794, {9, 58, 28}}, + {40.714285714285715, {9, 56, 27}}, + {40.74074074074073, {8, 32, 17}}, + {40.74074074074074, {2, 10, 17}}, + {40.76923076923077, {9, 52, 25}}, + {40.78947368421053, {7, 30, 18}}, + {40.8, {9, 50, 24}}, + {40.816326530612244, {6, 39, 27}}, + {40.81632653061225, {6, 29, 20}}, + {40.833333333333336, {9, 48, 23}}, + {40.86021505376343, {8, 56, 30}}, + {40.86021505376344, {2, 18, 30}}, + {40.869565217391305, {9, 46, 22}}, + {40.888888888888886, {8, 45, 24}}, + {40.90909090909091, {1, 8, 21}}, + {40.909090909090914, {5, 26, 21}}, + {40.93567251461988, {8, 34, 18}}, + {40.95238095238095, {9, 42, 20}}, + {40.952380952380956, {6, 42, 29}}, + {40.97222222222222, {8, 58, 31}}, + {40.993788819875775, {6, 32, 22}}, + {41.0, {9, 40, 19}}, + {41.02564102564102, {8, 47, 25}}, + {41.02564102564103, {2, 15, 25}}, + {41.05263157894737, {9, 38, 18}}, + {41.07142857142857, {3, 22, 27}}, + {41.07142857142858, {6, 22, 15}}, + {41.11111111111111, {8, 36, 19}}, + {41.111111111111114, {9, 36, 17}}, + {41.12903225806452, {7, 50, 30}}, + {41.142857142857146, {6, 35, 24}}, + {41.15226337448559, {8, 49, 26}}, + {41.1764705882353, {1, 6, 16}}, + {41.25, {9, 32, 15}}, + {41.269841269841265, {8, 38, 20}}, + {41.26984126984127, {6, 25, 17}}, + {41.29032258064516, {4, 31, 30}}, + {41.30434782608695, {3, 18, 22}}, + {41.333333333333336, {9, 30, 14}}, + {41.33333333333334, {5, 30, 24}}, + {41.34615384615385, {7, 42, 25}}, + {41.37931034482759, {0, 5, 28}}, + {41.40625, {7, 52, 31}}, + {41.41414141414141, {8, 40, 21}}, + {41.42857142857143, {6, 28, 19}}, + {41.474654377880185, {6, 44, 30}}, + {41.48148148148148, {8, 27, 14}}, + {41.53846153846154, {4, 26, 25}}, + {41.54589371980676, {8, 42, 22}}, + {41.55844155844156, {6, 31, 21}}, + {41.577060931899645, {8, 57, 30}}, + {41.6, {4, 25, 24}}, + {41.666666666666664, {7, 24, 14}}, + {41.66666666666667, {2, 9, 15}}, + {41.73913043478261, {4, 23, 22}}, + {41.75824175824176, {6, 37, 25}}, + {41.77777777777777, {8, 46, 24}}, + {41.81818181818182, {4, 22, 21}}, + {41.830065359477125, {8, 31, 16}}, + {41.83673469387755, {6, 40, 27}}, + {41.875, {9, 66, 31}}, + {41.88034188034188, {8, 48, 25}}, + {41.904761904761905, {6, 21, 14}}, + {41.935483870967744, {1, 12, 30}}, + {41.964285714285715, {7, 46, 27}}, + {41.9753086419753, {8, 50, 26}}, + {41.97530864197531, {8, 33, 17}}, + {41.97530864197532, {2, 16, 26}}, + {42.0, {4, 20, 19}}, + {42.016806722689076, {6, 24, 16}}, + {42.02898550724638, {5, 28, 22}}, + {42.04545454545455, {7, 36, 21}}, + {42.06349206349206, {8, 52, 27}}, + {42.06896551724138, {9, 60, 28}}, + {42.10526315789474, {0, 3, 18}}, + {42.142857142857146, {9, 58, 27}}, + {42.1455938697318, {8, 54, 28}}, + {42.17687074829932, {6, 30, 20}}, + {42.1875, {7, 26, 15}}, + {42.222222222222214, {8, 56, 29}}, + {42.22222222222222, {5, 18, 14}}, + {42.2360248447205, {6, 33, 22}}, + {42.241379310344826, {7, 48, 28}}, + {42.285714285714285, {6, 36, 24}}, + {42.29390681003584, {8, 58, 30}}, + {42.30769230769231, {1, 10, 25}}, + {42.32804232804233, {8, 39, 20}}, + {42.35294117647059, {4, 17, 16}}, + {42.36111111111111, {8, 60, 31}}, + {42.364532019704434, {6, 42, 28}}, + {42.391304347826086, {7, 38, 22}}, + {42.3963133640553, {6, 45, 30}}, + {42.4, {9, 52, 24}}, + {42.42424242424242, {8, 41, 21}}, + {42.42424242424243, {2, 13, 21}}, + {42.5, {4, 16, 15}}, + {42.51207729468599, {8, 43, 22}}, + {42.52873563218391, {5, 36, 28}}, + {42.58064516129032, {4, 32, 30}}, + {42.59259259259259, {8, 45, 23}}, + {42.592592592592595, {5, 22, 17}}, + {42.608695652173914, {9, 48, 22}}, + {42.64705882352941, {7, 28, 16}}, + {42.66666666666666, {8, 47, 24}}, + {42.666666666666664, {4, 15, 14}}, + {42.66666666666667, {2, 15, 24}}, + {42.708333333333336, {7, 40, 23}}, + {42.72727272727273, {9, 46, 21}}, + {42.73504273504273, {8, 49, 25}}, + {42.74193548387097, {7, 52, 30}}, + {42.758620689655174, {4, 30, 28}}, + {42.798353909465014, {8, 51, 26}}, + {42.857142857142854, {0, 2, 13}}, + {42.85714285714286, {6, 23, 15}}, + {42.911877394636015, {8, 55, 28}}, + {42.96296296296296, {8, 28, 14}}, + {42.96875, {7, 54, 31}}, + {43.0, {9, 42, 19}}, + {43.01075268817204, {8, 59, 30}}, + {43.01075268817205, {2, 19, 30}}, + {43.05555555555556, {8, 30, 15}}, + {43.055555555555564, {5, 30, 23}}, + {43.07692307692308, {4, 27, 25}}, + {43.10344827586207, {3, 24, 28}}, + {43.125, {9, 68, 31}}, + {43.13725490196078, {8, 32, 16}}, + {43.13725490196079, {2, 10, 16}}, + {43.1578947368421, {9, 40, 18}}, + {43.18181818181818, {3, 18, 21}}, + {43.2, {4, 26, 24}}, + {43.20987654320987, {8, 34, 17}}, + {43.20987654320988, {5, 34, 26}}, + {43.225806451612904, {9, 66, 30}}, + {43.26923076923077, {7, 44, 25}}, + {43.27485380116959, {8, 36, 18}}, + {43.31797235023041, {6, 46, 30}}, + {43.33333333333333, {8, 38, 19}}, + {43.333333333333336, {3, 12, 14}}, + {43.34975369458128, {6, 43, 28}}, + {43.386243386243386, {8, 40, 20}}, + {43.38624338624339, {6, 40, 26}}, + {43.421052631578945, {7, 32, 18}}, + {43.42857142857143, {6, 37, 24}}, + {43.43434343434343, {8, 42, 21}}, + {43.44827586206897, {9, 62, 28}}, + {43.47826086956522, {0, 4, 22}}, + {43.478260869565226, {2, 14, 22}}, + {43.51851851851851, {8, 46, 23}}, + {43.51851851851852, {7, 46, 26}}, + {43.529411764705884, {9, 36, 16}}, + {43.5374149659864, {6, 31, 20}}, + {43.54838709677419, {3, 26, 30}}, + {43.55555555555556, {8, 48, 24}}, + {43.57142857142857, {9, 60, 27}}, + {43.589743589743584, {8, 50, 25}}, + {43.5897435897436, {2, 16, 25}}, + {43.60902255639098, {6, 28, 18}}, + {43.62139917695473, {8, 52, 26}}, + {43.63636363636363, {4, 23, 21}}, + {43.65079365079365, {8, 54, 27}}, + {43.678160919540225, {8, 56, 28}}, + {43.67816091954023, {2, 18, 28}}, + {43.69747899159664, {6, 25, 16}}, + {43.7037037037037, {9, 58, 26}}, + {43.72759856630824, {8, 60, 30}}, + {43.75, {1, 6, 15}}, + {43.80952380952381, {4, 22, 20}}, + {43.80952380952382, {6, 22, 14}}, + {43.84615384615385, {9, 56, 25}}, + {43.85964912280702, {5, 24, 18}}, + {43.87096774193548, {4, 33, 30}}, + {43.87755102040817, {6, 42, 27}}, + {43.939393939393945, {5, 28, 21}}, + {43.956043956043956, {6, 39, 25}}, + {43.96551724137931, {7, 50, 28}}, + {44.0, {9, 32, 14}}, + {44.047619047619044, {6, 36, 23}}, + {44.04761904761905, {7, 36, 20}}, + {44.086021505376344, {5, 40, 30}}, + {44.11764705882353, {3, 14, 16}}, + {44.13793103448276, {4, 31, 28}}, + {44.15584415584416, {6, 33, 21}}, + {44.166666666666664, {9, 52, 23}}, + {44.21052631578947, {4, 20, 18}}, + {44.23076923076923, {3, 22, 25}}, + {44.23963133640554, {6, 47, 30}}, + {44.285714285714285, {9, 30, 13}}, + {44.28571428571429, {6, 30, 19}}, + {44.31818181818182, {7, 38, 21}}, + {44.33497536945813, {6, 44, 28}}, + {44.34782608695652, {9, 50, 22}}, + {44.354838709677416, {7, 54, 30}}, + {44.375, {9, 70, 31}}, + {44.444444444444436, {8, 47, 23}}, + {44.44444444444444, {8, 27, 13}}, + {44.44444444444445, {2, 9, 14}}, + {44.516129032258064, {9, 68, 30}}, + {44.53125, {7, 56, 31}}, + {44.54545454545455, {9, 48, 21}}, + {44.56521739130435, {7, 40, 22}}, + {44.57142857142858, {6, 38, 24}}, + {44.61538461538461, {4, 28, 25}}, + {44.642857142857146, {7, 24, 13}}, + {44.666666666666664, {9, 66, 29}}, + {44.705882352941174, {4, 18, 16}}, + {44.72049689440994, {6, 35, 22}}, + {44.73684210526316, {3, 16, 18}}, + {44.76190476190476, {9, 46, 20}}, + {44.761904761904766, {6, 46, 29}}, + {44.791666666666664, {7, 42, 23}}, + {44.79166666666667, {5, 42, 31}}, + {44.8, {4, 27, 24}}, + {44.827586206896555, {1, 12, 28}}, + {44.871794871794876, {5, 34, 25}}, + {44.89795918367347, {6, 21, 13}}, + {44.92753623188406, {5, 30, 22}}, + {45.0, {7, 26, 14}}, + {45.00000000000001, {5, 26, 19}}, + {45.05494505494506, {6, 40, 25}}, + {45.09803921568628, {5, 22, 16}}, + {45.112781954887225, {6, 29, 18}}, + {45.138888888888886, {8, 64, 31}}, + {45.16129032258065, {0, 6, 30}}, + {45.18518518518518, {9, 60, 26}}, + {45.19230769230769, {7, 46, 25}}, + {45.21072796934866, {8, 58, 28}}, + {45.21739130434783, {4, 25, 22}}, + {45.238095238095234, {8, 56, 27}}, + {45.23809523809524, {5, 18, 13}}, + {45.26315789473684, {9, 42, 18}}, + {45.267489711934154, {8, 54, 26}}, + {45.2991452991453, {8, 52, 25}}, + {45.3125, {7, 28, 15}}, + {45.32019704433498, {6, 45, 28}}, + {45.33333333333333, {8, 50, 24}}, + {45.333333333333336, {4, 16, 14}}, + {45.33333333333334, {2, 16, 24}}, + {45.370370370370374, {8, 48, 23}}, + {45.378151260504204, {6, 26, 16}}, + {45.38461538461539, {9, 58, 25}}, + {45.41062801932367, {8, 46, 22}}, + {45.45454545454545, {0, 4, 21}}, + {45.45454545454546, {2, 14, 21}}, + {45.5026455026455, {8, 42, 20}}, + {45.50264550264551, {6, 42, 26}}, + {45.51724137931034, {4, 32, 28}}, + {45.535714285714285, {7, 50, 27}}, + {45.55555555555556, {9, 40, 17}}, + {45.588235294117645, {7, 30, 16}}, + {45.6, {9, 56, 24}}, + {45.614035087719294, {8, 38, 18}}, + {45.6140350877193, {2, 12, 18}}, + {45.625, {9, 72, 31}}, + {45.65217391304348, {3, 20, 22}}, + {45.67901234567901, {8, 36, 17}}, + {45.67901234567902, {5, 36, 26}}, + {45.689655172413794, {7, 52, 28}}, + {45.714285714285715, {4, 15, 13}}, + {45.7516339869281, {8, 34, 16}}, + {45.806451612903224, {9, 70, 30}}, + {45.83333333333333, {8, 32, 15}}, + {45.833333333333336, {2, 10, 15}}, + {45.878136200716845, {8, 63, 30}}, + {45.88235294117647, {9, 38, 16}}, + {45.91836734693878, {6, 44, 27}}, + {45.925925925925924, {4, 30, 26}}, + {45.92592592592593, {8, 30, 14}}, + {45.962732919254655, {6, 36, 22}}, + {45.96774193548387, {7, 56, 30}}, + {45.97701149425287, {8, 59, 28}}, + {45.97701149425288, {2, 19, 28}}, + {46.0, {4, 22, 19}}, + {46.03174603174603, {8, 28, 13}}, + {46.03174603174604, {6, 28, 17}}, + {46.05263157894737, {7, 34, 18}}, + {46.082949308755765, {6, 49, 30}}, + {46.08695652173913, {9, 52, 22}}, + {46.090534979423865, {8, 55, 26}}, + {46.09375, {7, 58, 31}}, + {46.15384615384615, {0, 2, 12}}, + {46.206896551724135, {9, 66, 28}}, + {46.222222222222214, {8, 51, 24}}, + {46.23655913978495, {5, 42, 30}}, + {46.25, {9, 36, 15}}, + {46.25850340136054, {6, 33, 20}}, + {46.2962962962963, {5, 24, 17}}, + {46.30541871921182, {6, 46, 28}}, + {46.31578947368421, {4, 21, 18}}, + {46.36363636363637, {9, 50, 21}}, + {46.37681159420289, {8, 47, 22}}, + {46.3768115942029, {2, 15, 22}}, + {46.4, {4, 28, 24}}, + {46.42857142857143, {3, 12, 13}}, + {46.42857142857144, {6, 38, 23}}, + {46.45161290322581, {4, 35, 30}}, + {46.464646464646464, {8, 45, 21}}, + {46.52777777777778, {8, 66, 31}}, + {46.55172413793103, {3, 26, 28}}, + {46.56084656084656, {8, 43, 20}}, + {46.59090909090909, {7, 40, 21}}, + {46.59498207885304, {8, 64, 30}}, + {46.61654135338346, {6, 30, 18}}, + {46.666666666666664, {1, 6, 14}}, + {46.66666666666667, {2, 13, 19}}, + {46.73913043478261, {7, 42, 22}}, + {46.74329501915708, {8, 60, 28}}, + {46.753246753246756, {6, 35, 21}}, + {46.774193548387096, {3, 28, 30}}, + {46.78362573099415, {8, 39, 18}}, + {46.82539682539682, {8, 58, 27}}, + {46.85714285714286, {6, 40, 24}}, + {46.875, {3, 14, 15}}, + {46.89655172413793, {4, 33, 28}}, + {46.913580246913575, {8, 56, 26}}, + {46.91358024691358, {8, 37, 17}}, + {46.92307692307692, {9, 60, 25}}, + {46.93877551020409, {6, 22, 13}}, + {46.95652173913044, {4, 26, 22}}, + {46.969696969696976, {5, 30, 21}}, + {47.0, {9, 46, 19}}, + {47.004608294930875, {6, 50, 30}}, + {47.008547008547005, {8, 54, 25}}, + {47.05882352941177, {0, 3, 16}}, + {47.096774193548384, {9, 72, 30}}, + {47.111111111111114, {8, 52, 24}}, + {47.11538461538461, {7, 48, 25}}, + {47.1264367816092, {5, 40, 28}}, + {47.142857142857146, {9, 32, 13}}, + {47.2, {9, 58, 24}}, + {47.204968944099384, {6, 37, 22}}, + {47.22222222222222, {8, 33, 15}}, + {47.22222222222223, {2, 16, 23}}, + {47.252747252747255, {6, 42, 25}}, + {47.27272727272727, {4, 25, 21}}, + {47.290640394088676, {6, 47, 28}}, + {47.31182795698924, {8, 65, 30}}, + {47.31182795698925, {2, 21, 30}}, + {47.32142857142857, {7, 52, 27}}, + {47.32142857142858, {6, 52, 31}}, + {47.333333333333336, {9, 70, 29}}, + {47.34299516908213, {8, 48, 22}}, + {47.36842105263158, {1, 8, 18}}, + {47.407407407407405, {8, 31, 14}}, + {47.41379310344828, {7, 54, 28}}, + {47.435897435897445, {5, 36, 25}}, + {47.47474747474747, {8, 46, 21}}, + {47.5, {4, 18, 15}}, + {47.509578544061306, {8, 61, 28}}, + {47.58064516129032, {7, 58, 30}}, + {47.58620689655172, {9, 68, 28}}, + {47.61904761904761, {8, 29, 13}}, + {47.61904761904762, {6, 24, 14}}, + {47.61904761904763, {2, 9, 13}}, + {47.65625, {7, 60, 31}}, + {47.69230769230769, {9, 30, 12}}, + {47.72727272727273, {3, 20, 21}}, + {47.73662551440329, {8, 57, 26}}, + {47.74193548387097, {4, 36, 30}}, + {47.77777777777778, {9, 42, 17}}, + {47.777777777777786, {5, 42, 29}}, + {47.82608695652174, {1, 10, 22}}, + {47.857142857142854, {9, 66, 27}}, + {47.86324786324786, {8, 27, 12}}, + {47.916666666666664, {3, 22, 23}}, + {47.91666666666667, {5, 22, 15}}, + {47.92626728110599, {6, 51, 30}}, + {47.953216374269005, {8, 40, 18}}, + {47.95918367346939, {6, 46, 27}}, + {48.0, {4, 17, 14}}, + {48.028673835125446, {8, 66, 30}}, + {48.05194805194805, {6, 36, 21}}, + {48.07692307692308, {7, 24, 12}}, + {48.120300751879704, {6, 31, 18}}, + {48.125, {9, 76, 31}}, + {48.148148148148145, {8, 38, 17}}, + {48.14814814814815, {2, 12, 17}}, + {48.18181818181818, {9, 52, 21}}, + {48.214285714285715, {7, 26, 13}}, + {48.23529411764706, {9, 40, 16}}, + {48.275862068965516, {0, 6, 28}}, + {48.309178743961354, {8, 49, 22}}, + {48.333333333333336, {7, 28, 14}}, + {48.35164835164835, {6, 21, 12}}, + {48.36601307189542, {8, 36, 16}}, + {48.38709677419355, {1, 14, 30}}, + {48.41269841269841, {8, 60, 27}}, + {48.421052631578945, {4, 22, 18}}, + {48.4375, {7, 30, 15}}, + {48.447204968944106, {6, 38, 22}}, + {48.46153846153846, {9, 62, 25}}, + {48.48484848484848, {8, 47, 21}}, + {48.48484848484849, {2, 15, 21}}, + {48.529411764705884, {7, 32, 16}}, + {48.559670781893004, {8, 58, 26}}, + {48.57142857142857, {4, 16, 13}}, + {48.61111111111111, {8, 34, 15}}, + {48.611111111111114, {7, 34, 17}}, + {48.666666666666664, {9, 72, 29}}, + {48.67724867724868, {8, 45, 20}}, + {48.677248677248684, {6, 45, 26}}, + {48.68421052631579, {7, 36, 18}}, + {48.69565217391305, {4, 27, 22}}, + {48.717948717948715, {8, 56, 25}}, + {48.71794871794872, {5, 18, 12}}, + {48.73949579831933, {6, 28, 16}}, + {48.74551971326165, {8, 67, 30}}, + {48.75, {9, 38, 15}}, + {48.8, {9, 60, 24}}, + {48.80952380952381, {7, 40, 20}}, + {48.80952380952382, {6, 40, 23}}, + {48.84792626728111, {6, 52, 30}}, + {48.86363636363637, {7, 42, 21}}, + {48.888888888888886, {8, 32, 14}}, + {48.88888888888889, {2, 10, 14}}, + {48.91304347826087, {7, 44, 22}}, + {48.958333333333336, {7, 46, 23}}, + {48.96551724137931, {9, 70, 28}}, + {48.9795918367347, {6, 23, 13}}, + {49.0, {9, 48, 19}}, + {49.01960784313726, {5, 24, 16}}, + {49.03225806451613, {4, 37, 30}}, + {49.03846153846154, {7, 50, 25}}, + {49.04214559386973, {8, 63, 28}}, + {49.074074074074076, {8, 52, 23}}, + {49.09090909090909, {4, 26, 21}}, + {49.107142857142854, {7, 54, 27}}, + {49.10714285714286, {6, 54, 31}}, + {49.122807017543856, {8, 41, 18}}, + {49.12280701754386, {2, 13, 18}}, + {49.13793103448276, {7, 56, 28}}, + {49.142857142857146, {6, 42, 24}}, + {49.166666666666664, {9, 58, 23}}, + {49.193548387096776, {7, 60, 30}}, + {49.20634920634921, {8, 30, 13}}, + {49.206349206349216, {5, 30, 20}}, + {49.21875, {7, 62, 31}}, + {49.23076923076923, {4, 15, 12}}, + {49.26108374384237, {6, 49, 28}}, + {49.27536231884058, {8, 50, 22}}, + {49.275362318840585, {2, 16, 22}}, + {49.285714285714285, {9, 68, 27}}, + {49.30555555555556, {8, 70, 31}}, + {49.333333333333336, {9, 36, 14}}, + {49.33333333333334, {5, 36, 24}}, + {49.350649350649356, {6, 37, 21}}, + {49.375, {9, 78, 31}}, + {49.382716049382715, {8, 39, 17}}, + {49.38271604938272, {2, 19, 26}}, + {49.411764705882355, {4, 20, 16}}, + {49.425287356321846, {5, 42, 28}}, + {49.45054945054945, {6, 44, 25}}, + {49.46236559139785, {8, 68, 30}}, + {49.462365591397855, {2, 22, 30}}, + {49.473684210526315, {9, 46, 18}}, + {49.494949494949495, {8, 48, 21}}, + {49.523809523809526, {6, 25, 14}}, + {49.56521739130435, {9, 56, 22}}, + {49.572649572649574, {8, 28, 12}}, + {49.6, {4, 30, 24}}, + {49.62406015037594, {6, 32, 18}}, + {49.629629629629626, {9, 66, 26}}, + {49.62962962962963, {8, 66, 29}}, + {49.6551724137931, {4, 35, 28}}, + {49.673202614379086, {8, 37, 16}}, + {49.67741935483871, {9, 76, 30}}, + {49.68944099378882, {6, 39, 22}}, + {49.735449735449734, {8, 46, 20}}, + {49.76958525345622, {6, 53, 30}}, + {49.77777777777777, {8, 55, 24}}, + {49.808429118773944, {8, 64, 28}}, + {50.0, {0, 2, 11}}, + {50.00000000000001, {5, 26, 17}}, + {50.179211469534046, {8, 69, 30}}, + {50.205761316872426, {8, 60, 26}}, + {50.2415458937198, {8, 51, 22}}, + {50.24630541871921, {6, 50, 28}}, + {50.285714285714285, {6, 43, 24}}, + {50.292397660818715, {8, 42, 18}}, + {50.32258064516129, {4, 38, 30}}, + {50.34013605442177, {6, 36, 20}}, + {50.3448275862069, {9, 72, 28}}, + {50.37037037037037, {8, 33, 14}}, + {50.370370370370374, {4, 33, 26}}, + {50.4, {9, 62, 24}}, + {50.420168067226896, {6, 29, 16}}, + {50.427350427350426, {8, 58, 25}}, + {50.43478260869565, {4, 28, 22}}, + {50.476190476190474, {9, 52, 20}}, + {50.47619047619048, {6, 52, 29}}, + {50.505050505050505, {8, 49, 21}}, + {50.526315789473685, {4, 23, 18}}, + {50.53763440860215, {5, 46, 30}}, + {50.549450549450555, {6, 22, 12}}, + {50.574712643678154, {8, 65, 28}}, + {50.57471264367816, {2, 21, 28}}, + {50.588235294117645, {9, 42, 16}}, + {50.617283950617285, {8, 40, 17}}, + {50.625, {9, 80, 31}}, + {50.64935064935066, {6, 38, 21}}, + {50.66666666666666, {8, 56, 24}}, + {50.666666666666664, {4, 18, 14}}, + {50.66666666666667, {2, 18, 24}}, + {50.69124423963134, {6, 54, 30}}, + {50.69444444444444, {8, 72, 31}}, + {50.714285714285715, {9, 70, 27}}, + {50.72463768115942, {5, 34, 22}}, + {50.76923076923077, {9, 32, 12}}, + {50.78125, {7, 64, 31}}, + {50.793650793650784, {8, 47, 20}}, + {50.79365079365079, {8, 31, 13}}, + {50.7936507936508, {6, 31, 17}}, + {50.806451612903224, {7, 62, 30}}, + {50.833333333333336, {9, 60, 23}}, + {50.86206896551724, {7, 58, 28}}, + {50.877192982456144, {5, 28, 18}}, + {50.892857142857146, {7, 56, 27}}, + {50.89605734767025, {8, 70, 30}}, + {50.90909090909091, {4, 27, 21}}, + {50.925925925925924, {8, 54, 23}}, + {50.93167701863354, {6, 40, 22}}, + {50.96153846153846, {7, 52, 25}}, + {50.96774193548387, {9, 78, 30}}, + {50.98039215686274, {8, 38, 16}}, + {50.98039215686275, {2, 12, 16}}, + {51.0, {9, 50, 19}}, + {51.02040816326531, {6, 24, 13}}, + {51.028806584362144, {8, 61, 26}}, + {51.03448275862069, {4, 36, 28}}, + {51.041666666666664, {7, 48, 23}}, + {51.04166666666667, {5, 48, 31}}, + {51.08695652173913, {7, 46, 22}}, + {51.11111111111111, {8, 45, 19}}, + {51.111111111111114, {5, 22, 14}}, + {51.12781954887218, {6, 33, 18}}, + {51.13636363636363, {7, 44, 21}}, + {51.19047619047619, {7, 42, 20}}, + {51.1904761904762, {6, 42, 23}}, + {51.2, {4, 31, 24}}, + {51.207729468599034, {8, 52, 22}}, + {51.231527093596064, {6, 51, 28}}, + {51.25, {9, 40, 15}}, + {51.28205128205128, {8, 29, 12}}, + {51.282051282051285, {2, 9, 12}}, + {51.30434782608695, {9, 58, 22}}, + {51.31578947368421, {7, 38, 18}}, + {51.333333333333336, {9, 76, 29}}, + {51.34099616858238, {8, 66, 28}}, + {51.388888888888886, {8, 36, 15}}, + {51.38888888888889, {5, 36, 23}}, + {51.42857142857143, {4, 17, 13}}, + {51.461988304093566, {8, 43, 18}}, + {51.470588235294116, {7, 34, 16}}, + {51.51515151515151, {8, 50, 21}}, + {51.51515151515152, {2, 16, 21}}, + {51.53846153846154, {9, 66, 25}}, + {51.55555555555556, {8, 57, 24}}, + {51.5625, {7, 32, 15}}, + {51.578947368421055, {9, 48, 18}}, + {51.58730158730158, {8, 64, 27}}, + {51.61290322580645, {0, 7, 30}}, + {51.64835164835165, {6, 46, 25}}, + {51.666666666666664, {9, 30, 11}}, + {51.66666666666667, {5, 30, 19}}, + {51.70068027210885, {6, 37, 20}}, + {51.724137931034484, {1, 14, 28}}, + {51.76470588235294, {4, 21, 16}}, + {51.785714285714285, {7, 28, 13}}, + {51.78571428571429, {6, 28, 15}}, + {51.81818181818182, {9, 56, 21}}, + {51.85185185185185, {8, 27, 11}}, + {51.851851851851855, {2, 13, 17}}, + {51.875, {9, 82, 31}}, + {51.92307692307692, {7, 26, 12}}, + {51.94805194805195, {6, 39, 21}}, + {52.0, {9, 38, 14}}, + {52.04081632653061, {6, 50, 27}}, + {52.08333333333333, {8, 74, 31}}, + {52.083333333333336, {7, 24, 11}}, + {52.10084033613446, {6, 30, 16}}, + {52.10727969348659, {8, 67, 28}}, + {52.13675213675213, {8, 60, 25}}, + {52.142857142857146, {9, 72, 27}}, + {52.17391304347826, {0, 5, 22}}, + {52.21674876847291, {6, 52, 28}}, + {52.222222222222214, {8, 46, 19}}, + {52.22222222222222, {9, 46, 17}}, + {52.25806451612903, {9, 80, 30}}, + {52.27272727272727, {3, 22, 21}}, + {52.287581699346404, {8, 39, 16}}, + {52.30769230769231, {4, 16, 12}}, + {52.32974910394265, {8, 72, 30}}, + {52.34375, {7, 66, 31}}, + {52.38095238095237, {8, 32, 13}}, + {52.38095238095238, {6, 21, 11}}, + {52.38095238095239, {2, 10, 13}}, + {52.41379310344828, {4, 37, 28}}, + {52.41935483870968, {7, 64, 30}}, + {52.44444444444444, {8, 58, 24}}, + {52.5, {4, 20, 15}}, + {52.52525252525252, {8, 51, 21}}, + {52.53456221198157, {6, 56, 30}}, + {52.56410256410257, {5, 40, 25}}, + {52.57142857142858, {6, 45, 24}}, + {52.58620689655172, {7, 60, 28}}, + {52.592592592592595, {9, 70, 26}}, + {52.63157894736842, {0, 4, 18}}, + {52.631578947368425, {2, 14, 18}}, + {52.666666666666664, {9, 78, 29}}, + {52.67489711934156, {8, 63, 26}}, + {52.67857142857143, {7, 58, 27}}, + {52.68817204301076, {5, 48, 30}}, + {52.72727272727273, {4, 28, 21}}, + {52.74725274725275, {6, 23, 12}}, + {52.77777777777777, {8, 56, 23}}, + {52.77777777777778, {5, 18, 11}}, + {52.8, {4, 32, 24}}, + {52.857142857142854, {9, 36, 13}}, + {52.8735632183908, {8, 68, 28}}, + {52.87356321839081, {2, 22, 28}}, + {52.88461538461539, {7, 54, 25}}, + {52.903225806451616, {4, 40, 30}}, + {52.91005291005291, {8, 49, 20}}, + {52.94117647058823, {1, 8, 16}}, + {52.94117647058824, {5, 26, 16}}, + {52.991452991452995, {8, 30, 12}}, + {53.0, {9, 52, 19}}, + {53.03030303030303, {5, 34, 21}}, + {53.04347826086956, {9, 60, 22}}, + {53.04659498207885, {8, 73, 30}}, + {53.06122448979592, {6, 25, 13}}, + {53.061224489795926, {6, 38, 20}}, + {53.07692307692308, {9, 68, 25}}, + {53.08641975308642, {8, 42, 17}}, + {53.086419753086425, {5, 42, 26}}, + {53.10344827586207, {9, 76, 28}}, + {53.125, {3, 16, 15}}, + {53.12500000000001, {5, 50, 31}}, + {53.14009661835748, {8, 54, 22}}, + {53.17460317460318, {8, 66, 27}}, + {53.20197044334976, {6, 53, 28}}, + {53.225806451612904, {3, 32, 30}}, + {53.24675324675325, {6, 40, 21}}, + {53.26086956521739, {7, 48, 22}}, + {53.33333333333333, {8, 47, 19}}, + {53.333333333333336, {4, 15, 11}}, + {53.33333333333334, {2, 19, 24}}, + {53.40909090909091, {7, 46, 21}}, + {53.41614906832299, {6, 42, 22}}, + {53.44827586206897, {3, 30, 28}}, + {53.45622119815669, {6, 57, 30}}, + {53.47222222222222, {8, 76, 31}}, + {53.49794238683127, {8, 64, 26}}, + {53.535353535353536, {8, 52, 21}}, + {53.54838709677419, {9, 82, 30}}, + {53.57142857142857, {3, 14, 13}}, + {53.57142857142858, {6, 29, 15}}, + {53.59477124183007, {8, 40, 16}}, + {53.6, {9, 66, 24}}, + {53.62318840579711, {5, 36, 22}}, + {53.63636363636363, {9, 58, 21}}, + {53.63984674329502, {8, 69, 28}}, + {53.68421052631579, {9, 50, 18}}, + {53.7037037037037, {8, 28, 11}}, + {53.70370370370371, {5, 28, 17}}, + {53.714285714285715, {6, 46, 24}}, + {53.75, {9, 42, 15}}, + {53.76344086021505, {8, 74, 30}}, + {53.763440860215056, {2, 24, 30}}, + {53.78151260504202, {6, 31, 16}}, + {53.793103448275865, {4, 38, 28}}, + {53.80116959064327, {8, 45, 18}}, + {53.84615384615385, {1, 6, 12}}, + {53.90625, {7, 68, 31}}, + {53.91304347826087, {4, 30, 22}}, + {53.94736842105263, {7, 40, 18}}, + {53.96825396825396, {8, 50, 20}}, + {53.96825396825397, {8, 33, 13}}, + {53.968253968253975, {2, 16, 20}}, + {54.0, {4, 26, 19}}, + {54.02298850574713, {5, 46, 28}}, + {54.03225806451613, {7, 66, 30}}, + {54.07407407407407, {8, 72, 29}}, + {54.074074074074076, {9, 72, 26}}, + {54.08163265306123, {6, 52, 27}}, + {54.106280193236714, {8, 55, 22}}, + {54.11764705882353, {4, 22, 16}}, + {54.13533834586467, {6, 35, 18}}, + {54.166666666666664, {3, 12, 11}}, + {54.16666666666667, {2, 12, 15}}, + {54.187192118226605, {6, 54, 28}}, + {54.193548387096776, {4, 41, 30}}, + {54.222222222222214, {8, 60, 24}}, + {54.285714285714285, {4, 18, 13}}, + {54.28571428571429, {6, 37, 19}}, + {54.310344827586206, {7, 62, 28}}, + {54.32098765432098, {8, 65, 26}}, + {54.32098765432099, {8, 43, 17}}, + {54.34782608695652, {3, 24, 22}}, + {54.375, {9, 86, 31}}, + {54.3778801843318, {6, 58, 30}}, + {54.38596491228071, {5, 30, 18}}, + {54.4, {4, 33, 24}}, + {54.406130268199234, {8, 70, 28}}, + {54.411764705882355, {7, 36, 16}}, + {54.421768707483, {6, 39, 20}}, + {54.44444444444444, {9, 48, 17}}, + {54.44444444444445, {5, 48, 29}}, + {54.464285714285715, {7, 60, 27}}, + {54.48028673835125, {8, 75, 30}}, + {54.48275862068966, {9, 78, 28}}, + {54.54545454545455, {0, 2, 10}}, + {54.61538461538461, {9, 70, 25}}, + {54.629629629629626, {8, 58, 23}}, + {54.6583850931677, {6, 43, 22}}, + {54.666666666666664, {9, 40, 14}}, + {54.66666666666667, {5, 40, 24}}, + {54.6875, {7, 34, 15}}, + {54.7008547008547, {8, 31, 12}}, + {54.73684210526316, {4, 25, 18}}, + {54.76190476190476, {3, 22, 20}}, + {54.761904761904766, {6, 22, 11}}, + {54.78260869565217, {9, 62, 22}}, + {54.80769230769231, {7, 56, 25}}, + {54.81481481481481, {8, 36, 14}}, + {54.81481481481482, {4, 36, 26}}, + {54.83870967741935, {1, 16, 30}}, + {54.83870967741936, {5, 50, 30}}, + {54.85714285714286, {6, 47, 24}}, + {54.86111111111111, {8, 78, 31}}, + {54.90196078431372, {8, 41, 16}}, + {54.90196078431373, {2, 13, 16}}, + {54.94505494505495, {6, 24, 12}}, + {54.97076023391812, {8, 46, 18}}, + {55.0, {9, 32, 11}}, + {55.02645502645502, {8, 51, 20}}, + {55.02645502645503, {6, 51, 26}}, + {55.07246376811594, {8, 56, 22}}, + {55.072463768115945, {2, 18, 22}}, + {55.10204081632653, {6, 26, 13}}, + {55.111111111111114, {8, 61, 24}}, + {55.12820512820513, {5, 42, 25}}, + {55.1440329218107, {8, 66, 26}}, + {55.172413793103445, {0, 7, 28}}, + {55.19713261648745, {8, 76, 30}}, + {55.2, {9, 68, 24}}, + {55.208333333333336, {7, 52, 23}}, + {55.23809523809524, {4, 28, 20}}, + {55.23809523809525, {6, 28, 14}}, + {55.26315789473684, {3, 20, 18}}, + {55.294117647058826, {9, 46, 16}}, + {55.29953917050692, {6, 59, 30}}, + {55.333333333333336, {9, 82, 29}}, + {55.357142857142854, {7, 30, 13}}, + {55.35714285714286, {6, 30, 15}}, + {55.38461538461539, {4, 17, 12}}, + {55.43478260869565, {7, 50, 22}}, + {55.45454545454545, {9, 60, 21}}, + {55.46218487394958, {6, 32, 16}}, + {55.46875, {7, 70, 31}}, + {55.483870967741936, {4, 42, 30}}, + {55.55555555555555, {8, 29, 11}}, + {55.55555555555556, {5, 24, 14}}, + {55.555555555555564, {2, 9, 11}}, + {55.625, {9, 88, 31}}, + {55.6390977443609, {6, 36, 18}}, + {55.645161290322584, {7, 68, 30}}, + {55.65217391304348, {4, 31, 22}}, + {55.68181818181818, {7, 48, 21}}, + {55.714285714285715, {9, 38, 13}}, + {55.71428571428572, {6, 38, 19}}, + {55.76923076923077, {7, 28, 12}}, + {55.782312925170075, {6, 40, 20}}, + {55.78947368421053, {9, 52, 18}}, + {55.833333333333336, {9, 66, 23}}, + {55.84415584415585, {6, 42, 21}}, + {55.86206896551724, {9, 80, 28}}, + {55.88235294117647, {3, 18, 16}}, + {55.900621118012424, {6, 44, 22}}, + {55.913978494623656, {8, 77, 30}}, + {55.91397849462366, {2, 25, 30}}, + {55.93869731800766, {8, 72, 28}}, + {55.95238095238095, {7, 46, 20}}, + {55.952380952380956, {6, 46, 23}}, + {55.96707818930041, {8, 67, 26}}, + {56.0, {4, 20, 14}}, + {56.03448275862069, {7, 64, 28}}, + {56.03864734299517, {8, 57, 22}}, + {56.043956043956044, {6, 50, 25}}, + {56.06060606060607, {5, 36, 21}}, + {56.08465608465609, {8, 52, 20}}, + {56.122448979591844, {6, 54, 27}}, + {56.12903225806452, {9, 86, 30}}, + {56.14035087719297, {8, 47, 18}}, + {56.140350877192986, {2, 15, 18}}, + {56.15384615384615, {9, 72, 25}}, + {56.1576354679803, {6, 56, 28}}, + {56.19047619047619, {9, 58, 20}}, + {56.209150326797385, {8, 42, 16}}, + {56.22119815668203, {6, 60, 30}}, + {56.25, {7, 26, 11}}, + {56.25000000000001, {5, 26, 15}}, + {56.2962962962963, {8, 37, 14}}, + {56.321839080459775, {5, 48, 28}}, + {56.34920634920635, {8, 70, 27}}, + {56.36363636363637, {9, 30, 10}}, + {56.4102564102564, {8, 32, 12}}, + {56.410256410256416, {2, 10, 12}}, + {56.42857142857143, {9, 78, 27}}, + {56.45161290322581, {3, 34, 30}}, + {56.470588235294116, {4, 23, 16}}, + {56.481481481481474, {8, 60, 23}}, + {56.48148148148148, {7, 60, 26}}, + {56.52173913043478, {1, 12, 22}}, + {56.55172413793103, {4, 40, 28}}, + {56.56565656565656, {8, 27, 10}}, + {56.578947368421055, {7, 42, 18}}, + {56.630824372759854, {8, 78, 30}}, + {56.666666666666664, {4, 16, 11}}, + {56.66666666666667, {2, 16, 19}}, + {56.70498084291187, {8, 73, 28}}, + {56.73076923076923, {7, 58, 25}}, + {56.774193548387096, {4, 43, 30}}, + {56.79012345679012, {8, 45, 17}}, + {56.79012345679013, {2, 22, 26}}, + {56.8, {9, 70, 24}}, + {56.81818181818182, {7, 24, 10}}, + {56.8421052631579, {4, 26, 18}}, + {56.86274509803922, {5, 28, 16}}, + {56.875, {9, 90, 31}}, + {56.888888888888886, {8, 63, 24}}, + {56.89655172413793, {3, 32, 28}}, + {56.92307692307692, {9, 36, 12}}, + {56.94444444444444, {8, 40, 15}}, + {56.94444444444445, {5, 40, 23}}, + {56.98924731182796, {5, 52, 30}}, + {57.0, {9, 56, 19}}, + {57.00483091787439, {8, 58, 22}}, + {57.03125, {7, 72, 31}}, + {57.03703703703704, {9, 76, 26}}, + {57.14285714285714, {6, 21, 10}}, + {57.142857142857146, {6, 23, 11}}, + {57.14285714285715, {6, 45, 22}}, + {57.241379310344826, {9, 82, 28}}, + {57.25806451612903, {7, 70, 30}}, + {57.26495726495727, {8, 66, 25}}, + {57.27272727272727, {9, 62, 21}}, + {57.291666666666664, {7, 54, 23}}, + {57.29166666666667, {5, 54, 31}}, + {57.30994152046784, {8, 48, 18}}, + {57.333333333333336, {9, 42, 14}}, + {57.33333333333334, {5, 42, 24}}, + {57.34767025089606, {8, 79, 30}}, + {57.35294117647059, {7, 38, 16}}, + {57.391304347826086, {4, 32, 22}}, + {57.407407407407405, {3, 30, 26}}, + {57.40740740740741, {8, 30, 11}}, + {57.40740740740742, {5, 30, 17}}, + {57.41935483870968, {9, 88, 30}}, + {57.47126436781609, {8, 74, 28}}, + {57.4712643678161, {2, 24, 28}}, + {57.5, {4, 22, 15}}, + {57.51633986928104, {8, 43, 16}}, + {57.57575757575757, {8, 56, 21}}, + {57.57575757575758, {5, 18, 10}}, + {57.6, {4, 35, 24}}, + {57.608695652173914, {7, 52, 22}}, + {57.61316872427983, {8, 69, 26}}, + {57.638888888888886, {8, 82, 31}}, + {57.64705882352941, {9, 48, 16}}, + {57.69230769230769, {3, 14, 12}}, + {57.758620689655174, {7, 66, 28}}, + {57.77777777777777, {8, 51, 19}}, + {57.77777777777778, {8, 38, 14}}, + {57.777777777777786, {2, 12, 14}}, + {57.8125, {7, 36, 15}}, + {57.857142857142854, {9, 80, 27}}, + {57.89473684210526, {1, 10, 18}}, + {57.93103448275862, {4, 41, 28}}, + {57.93650793650794, {8, 72, 27}}, + {57.95454545454545, {7, 50, 21}}, + {57.97101449275362, {8, 59, 22}}, + {57.97101449275363, {2, 19, 22}}, + {58.0, {4, 28, 19}}, + {58.02469135802468, {8, 46, 17}}, + {58.0246913580247, {5, 46, 26}}, + {58.035714285714285, {7, 64, 27}}, + {58.03571428571429, {6, 64, 31}}, + {58.064516129032256, {0, 8, 30}}, + {58.06451612903226, {2, 26, 30}}, + {58.095238095238095, {9, 60, 20}}, + {58.11965811965812, {8, 33, 12}}, + {58.125, {9, 92, 31}}, + {58.12807881773399, {6, 58, 28}}, + {58.163265306122454, {6, 56, 27}}, + {58.18181818181818, {4, 15, 10}}, + {58.201058201058196, {8, 54, 20}}, + {58.2010582010582, {6, 54, 26}}, + {58.23754789272031, {8, 75, 28}}, + {58.24175824175825, {6, 52, 25}}, + {58.26086956521739, {9, 66, 22}}, + {58.285714285714285, {6, 50, 24}}, + {58.33333333333333, {8, 41, 15}}, + {58.333333333333336, {1, 6, 11}}, + {58.38509316770187, {6, 46, 22}}, + {58.4, {9, 72, 24}}, + {58.43621399176955, {8, 70, 26}}, + {58.44155844155844, {6, 44, 21}}, + {58.46153846153846, {4, 18, 12}}, + {58.47953216374269, {8, 49, 18}}, + {58.503401360544224, {6, 42, 20}}, + {58.51851851851851, {8, 78, 29}}, + {58.51851851851852, {9, 78, 26}}, + {58.57142857142857, {9, 40, 13}}, + {58.57142857142858, {6, 40, 19}}, + {58.58585858585859, {8, 28, 10}}, + {58.59375, {7, 74, 31}}, + {58.62068965517241, {1, 16, 28}}, + {58.62068965517242, {5, 50, 28}}, + {58.64661654135339, {6, 38, 18}}, + {58.65384615384615, {7, 60, 25}}, + {58.66666666666666, {8, 65, 24}}, + {58.666666666666664, {4, 21, 14}}, + {58.66666666666667, {2, 21, 24}}, + {58.69565217391305, {3, 26, 22}}, + {58.70967741935484, {9, 90, 30}}, + {58.73015873015873, {8, 36, 13}}, + {58.730158730158735, {5, 36, 20}}, + {58.75, {9, 46, 15}}, + {58.781362007168454, {8, 81, 30}}, + {58.8235294117647, {0, 4, 16}}, + {58.82352941176471, {2, 14, 16}}, + {58.87096774193548, {7, 72, 30}}, + {58.888888888888886, {9, 52, 17}}, + {58.88888888888889, {8, 52, 19}}, + {58.92857142857143, {7, 32, 13}}, + {58.93719806763284, {8, 60, 22}}, + {58.94736842105263, {4, 27, 18}}, + {58.97435897435897, {8, 68, 25}}, + {58.97435897435898, {5, 22, 12}}, + {58.986175115207374, {6, 63, 30}}, + {59.0, {9, 58, 19}}, + {59.00383141762452, {8, 76, 28}}, + {59.02777777777778, {8, 84, 31}}, + {59.04761904761905, {6, 30, 14}}, + {59.09090909090909, {3, 12, 10}}, + {59.11330049261084, {6, 59, 28}}, + {59.130434782608695, {4, 33, 22}}, + {59.13978494623657, {5, 54, 30}}, + {59.166666666666664, {9, 70, 23}}, + {59.18367346938776, {6, 28, 13}}, + {59.2, {4, 36, 24}}, + {59.21052631578947, {7, 44, 18}}, + {59.23076923076923, {9, 76, 25}}, + {59.25925925925925, {8, 47, 17}}, + {59.25925925925926, {8, 31, 11}}, + {59.25925925925927, {2, 15, 17}}, + {59.285714285714285, {9, 82, 27}}, + {59.310344827586206, {4, 42, 28}}, + {59.333333333333336, {9, 88, 29}}, + {59.34065934065934, {6, 26, 12}}, + {59.354838709677416, {4, 45, 30}}, + {59.375, {3, 18, 15}}, + {59.37500000000001, {5, 56, 31}}, + {59.42028985507247, {5, 40, 22}}, + {59.42857142857143, {6, 51, 24}}, + {59.48275862068966, {7, 68, 28}}, + {59.49820788530466, {8, 82, 30}}, + {59.52380952380952, {8, 74, 27}}, + {59.523809523809526, {6, 24, 11}}, + {59.55555555555556, {8, 66, 24}}, + {59.59595959595959, {8, 58, 21}}, + {59.61538461538461, {7, 30, 12}}, + {59.62732919254659, {6, 47, 22}}, + {59.64912280701754, {8, 50, 18}}, + {59.649122807017555, {2, 16, 18}}, + {59.67741935483871, {3, 36, 30}}, + {59.72222222222222, {8, 42, 15}}, + {59.72222222222223, {5, 42, 23}}, + {59.740259740259745, {6, 22, 10}}, + {59.770114942528735, {8, 77, 28}}, + {59.77011494252874, {2, 25, 28}}, + {59.78260869565217, {7, 54, 22}}, + {59.82142857142857, {7, 66, 27}}, + {59.82142857142858, {6, 66, 31}}, + {59.82905982905982, {8, 34, 12}}, + {59.86394557823129, {6, 43, 20}}, + {59.90338164251208, {8, 61, 22}}, + {59.9078341013825, {6, 64, 30}}, + {60.0, {0, 2, 9}}, + {60.00000000000001, {5, 26, 14}}, + {60.08230452674897, {8, 72, 26}}, + {60.09852216748769, {6, 60, 28}}, + {60.130718954248366, {8, 45, 16}}, + {60.150375939849624, {6, 39, 18}}, + {60.15625, {7, 76, 31}}, + {60.18518518518518, {8, 64, 23}}, + {60.204081632653065, {6, 58, 27}}, + {60.21505376344086, {8, 83, 30}}, + {60.215053763440864, {2, 27, 30}}, + {60.22727272727273, {7, 52, 21}}, + {60.25641025641026, {5, 46, 25}}, + {60.294117647058826, {7, 40, 16}}, + {60.31746031746031, {8, 56, 20}}, + {60.317460317460316, {8, 37, 13}}, + {60.31746031746032, {6, 37, 17}}, + {60.3448275862069, {3, 34, 28}}, + {60.416666666666664, {7, 28, 11}}, + {60.41666666666667, {5, 28, 15}}, + {60.439560439560445, {6, 54, 25}}, + {60.44444444444444, {8, 67, 24}}, + {60.483870967741936, {7, 74, 30}}, + {60.49382716049383, {8, 48, 17}}, + {60.504201680672274, {6, 35, 16}}, + {60.526315789473685, {3, 22, 18}}, + {60.536398467432946, {8, 78, 28}}, + {60.57142857142858, {6, 52, 24}}, + {60.57692307692308, {7, 62, 25}}, + {60.6060606060606, {8, 29, 10}}, + {60.606060606060616, {2, 9, 10}}, + {60.625, {9, 96, 31}}, + {60.645161290322584, {4, 46, 30}}, + {60.666666666666664, {9, 90, 29}}, + {60.68376068376069, {8, 70, 25}}, + {60.689655172413794, {4, 43, 28}}, + {60.714285714285715, {3, 16, 13}}, + {60.71428571428572, {5, 50, 27}}, + {60.74074074074074, {8, 40, 14}}, + {60.76923076923077, {9, 78, 25}}, + {60.78431372549021, {5, 30, 16}}, + {60.8, {4, 37, 24}}, + {60.81871345029239, {8, 51, 18}}, + {60.82949308755761, {6, 65, 30}}, + {60.833333333333336, {9, 72, 23}}, + {60.869565217391305, {0, 6, 22}}, + {60.90534979423868, {8, 73, 26}}, + {60.90909090909091, {9, 66, 21}}, + {60.91954022988506, {5, 52, 28}}, + {60.93189964157706, {8, 84, 30}}, + {60.9375, {7, 38, 15}}, + {60.95238095238095, {4, 31, 20}}, + {60.952380952380956, {6, 31, 14}}, + {61.0, {9, 60, 19}}, + {61.03896103896104, {6, 46, 21}}, + {61.05263157894737, {4, 28, 18}}, + {61.083743842364534, {6, 61, 28}}, + {61.11111111111111, {8, 32, 11}}, + {61.111111111111114, {2, 10, 11}}, + {61.1764705882353, {4, 25, 16}}, + {61.206896551724135, {7, 70, 28}}, + {61.22448979591837, {6, 29, 13}}, + {61.25, {9, 48, 15}}, + {61.29032258064516, {1, 18, 30}}, + {61.29032258064517, {5, 56, 30}}, + {61.30268199233716, {8, 79, 28}}, + {61.33333333333333, {8, 68, 24}}, + {61.333333333333336, {4, 22, 14}}, + {61.33333333333334, {2, 22, 24}}, + {61.36363636363637, {7, 26, 10}}, + {61.37566137566138, {8, 57, 20}}, + {61.37931034482759, {9, 88, 28}}, + {61.40350877192983, {5, 34, 18}}, + {61.42857142857143, {9, 42, 13}}, + {61.43790849673202, {8, 46, 16}}, + {61.458333333333336, {7, 58, 23}}, + {61.48148148148148, {9, 82, 26}}, + {61.53846153846154, {0, 3, 12}}, + {61.6, {9, 76, 24}}, + {61.607142857142854, {7, 68, 27}}, + {61.60714285714286, {6, 68, 31}}, + {61.61616161616161, {8, 60, 21}}, + {61.64874551971326, {8, 85, 30}}, + {61.654135338345874, {6, 40, 18}}, + {61.666666666666664, {9, 36, 11}}, + {61.66666666666667, {5, 36, 19}}, + {61.714285714285715, {6, 53, 24}}, + {61.71875, {7, 78, 31}}, + {61.72839506172839, {8, 49, 17}}, + {61.7283950617284, {2, 24, 26}}, + {61.73913043478261, {9, 70, 22}}, + {61.751152073732726, {6, 66, 30}}, + {61.76470588235294, {3, 20, 16}}, + {61.80555555555555, {8, 88, 31}}, + {61.81818181818182, {4, 16, 10}}, + {61.83574879227053, {8, 63, 22}}, + {61.8421052631579, {7, 46, 18}}, + {61.875, {9, 98, 31}}, + {61.904761904761905, {6, 25, 11}}, + {61.90476190476191, {2, 12, 13}}, + {61.935483870967744, {4, 47, 30}}, + {61.95652173913044, {7, 56, 22}}, + {61.98830409356725, {8, 52, 18}}, + {62.0, {9, 30, 9}}, + {62.03703703703704, {8, 66, 23}}, + {62.06896551724138, {0, 8, 28}}, + {62.06896551724139, {2, 26, 28}}, + {62.096774193548384, {7, 76, 30}}, + {62.10526315789474, {9, 58, 18}}, + {62.11180124223603, {6, 49, 22}}, + {62.121212121212125, {5, 40, 21}}, + {62.142857142857146, {9, 86, 27}}, + {62.18487394957983, {6, 36, 16}}, + {62.222222222222214, {8, 27, 9}}, + {62.22222222222222, {2, 13, 14}}, + {62.244897959183675, {6, 60, 27}}, + {62.30769230769231, {9, 80, 25}}, + {62.31884057971015, {5, 42, 22}}, + {62.337662337662344, {6, 23, 10}}, + {62.35294117647059, {9, 52, 16}}, + {62.36559139784946, {8, 86, 30}}, + {62.365591397849464, {2, 28, 30}}, + {62.39316239316239, {8, 72, 25}}, + {62.4, {4, 38, 24}}, + {62.43386243386243, {8, 58, 20}}, + {62.43386243386244, {6, 58, 26}}, + {62.5, {7, 24, 9}}, + {62.50000000000001, {2, 14, 15}}, + {62.55144032921811, {8, 75, 26}}, + {62.58064516129032, {9, 96, 30}}, + {62.58503401360545, {6, 45, 20}}, + {62.608695652173914, {4, 35, 22}}, + {62.62626262626263, {8, 30, 10}}, + {62.63736263736264, {6, 56, 25}}, + {62.666666666666664, {9, 46, 14}}, + {62.66666666666667, {5, 46, 24}}, + {62.672811059907836, {6, 67, 30}}, + {62.698412698412696, {8, 78, 27}}, + {62.72727272727273, {9, 68, 21}}, + {62.74509803921568, {8, 47, 16}}, + {62.74509803921569, {2, 15, 16}}, + {62.758620689655174, {9, 90, 28}}, + {62.80193236714975, {8, 64, 22}}, + {62.820512820512825, {5, 48, 25}}, + {62.83524904214559, {8, 81, 28}}, + {62.857142857142854, {6, 21, 9}}, + {62.85714285714286, {6, 32, 14}}, + {62.903225806451616, {3, 38, 30}}, + {62.93103448275862, {7, 72, 28}}, + {62.96296296296296, {8, 33, 11}}, + {62.96296296296297, {2, 16, 17}}, + {63.0, {9, 62, 19}}, + {63.04347826086956, {3, 28, 22}}, + {63.05418719211823, {6, 63, 28}}, + {63.07692307692308, {9, 40, 12}}, + {63.08243727598566, {8, 87, 30}}, + {63.095238095238095, {7, 52, 20}}, + {63.0952380952381, {6, 52, 23}}, + {63.111111111111114, {8, 70, 24}}, + {63.125, {9, 100, 31}}, + {63.1578947368421, {0, 5, 18}}, + {63.19444444444444, {8, 90, 31}}, + {63.2, {9, 78, 24}}, + {63.2183908045977, {5, 54, 28}}, + {63.225806451612904, {4, 48, 30}}, + {63.23529411764706, {7, 42, 16}}, + {63.24786324786324, {8, 36, 12}}, + {63.26530612244898, {6, 30, 13}}, + {63.28125, {7, 80, 31}}, + {63.33333333333333, {8, 56, 19}}, + {63.333333333333336, {5, 18, 9}}, + {63.33333333333334, {5, 56, 29}}, + {63.35403726708074, {6, 50, 22}}, + {63.37448559670782, {8, 76, 26}}, + {63.392857142857146, {7, 70, 27}}, + {63.44086021505377, {5, 58, 30}}, + {63.44827586206897, {4, 45, 28}}, + {63.46153846153846, {7, 32, 12}}, + {63.47826086956522, {9, 72, 22}}, + {63.49206349206349, {8, 59, 20}}, + {63.492063492063494, {8, 39, 13}}, + {63.4920634920635, {2, 19, 20}}, + {63.529411764705884, {4, 26, 16}}, + {63.541666666666664, {7, 60, 23}}, + {63.54166666666667, {5, 60, 31}}, + {63.57142857142857, {9, 88, 27}}, + {63.594470046082954, {6, 68, 30}}, + {63.6015325670498, {8, 82, 28}}, + {63.63636363636363, {1, 6, 10}}, + {63.7037037037037, {8, 42, 14}}, + {63.70967741935484, {7, 78, 30}}, + {63.736263736263744, {6, 28, 12}}, + {63.75, {9, 50, 15}}, + {63.76811594202898, {8, 65, 22}}, + {63.76811594202899, {2, 21, 22}}, + {63.793103448275865, {3, 36, 28}}, + {63.79928315412186, {8, 88, 30}}, + {63.80952380952381, {9, 66, 20}}, + {63.80952380952382, {6, 66, 29}}, + {63.84615384615385, {9, 82, 25}}, + {63.865546218487395, {6, 37, 16}}, + {63.87096774193548, {9, 98, 30}}, + {63.888888888888886, {8, 45, 15}}, + {63.88888888888889, {5, 22, 11}}, + {63.945578231292515, {6, 46, 20}}, + {64.0, {4, 15, 9}}, + {64.03940886699507, {6, 64, 28}}, + {64.05228758169935, {8, 48, 16}}, + {64.0625, {7, 40, 15}}, + {64.1025641025641, {5, 24, 12}}, + {64.1304347826087, {7, 58, 22}}, + {64.13793103448276, {9, 92, 28}}, + {64.16666666666667, {9, 76, 23}}, + {64.19753086419752, {8, 51, 17}}, + {64.19753086419753, {8, 77, 26}}, + {64.21052631578948, {9, 60, 18}}, + {64.28571428571429, {6, 26, 11}}, + {64.32748538011695, {8, 54, 18}}, + {64.34782608695652, {4, 36, 22}}, + {64.36781609195401, {8, 83, 28}}, + {64.36781609195403, {2, 27, 28}}, + {64.375, {9, 102, 31}}, + {64.42307692307692, {7, 66, 25}}, + {64.44444444444444, {8, 28, 9}}, + {64.47368421052632, {7, 48, 18}}, + {64.51612903225806, {0, 9, 30}}, + {64.51612903225808, {2, 29, 30}}, + {64.54545454545455, {9, 70, 21}}, + {64.55026455026454, {8, 60, 20}}, + {64.55026455026456, {6, 60, 26}}, + {64.58333333333333, {7, 30, 11}}, + {64.58333333333334, {5, 30, 15}}, + {64.59627329192547, {6, 51, 22}}, + {64.61538461538461, {4, 20, 12}}, + {64.64646464646465, {8, 31, 10}}, + {64.65517241379311, {7, 74, 28}}, + {64.66165413533835, {6, 42, 18}}, + {64.66666666666667, {9, 96, 29}}, + {64.70588235294117, {1, 10, 16}}, + {64.73429951690821, {8, 66, 22}}, + {64.76190476190476, {6, 33, 14}}, + {64.77272727272727, {7, 56, 21}}, + {64.8, {9, 80, 24}}, + {64.81481481481481, {8, 34, 11}}, + {64.81481481481482, {5, 34, 17}}, + {64.82758620689656, {4, 46, 28}}, + {64.83516483516483, {6, 58, 25}}, + {64.84375, {7, 82, 31}}, + {64.88888888888889, {8, 72, 24}}, + {64.9122807017544, {5, 36, 18}}, + {64.93506493506494, {6, 24, 10}}, + {64.95726495726495, {8, 37, 12}}, + {65.0, {3, 12, 9}}, + {65.02057613168724, {8, 78, 26}}, + {65.02463054187193, {6, 65, 28}}, + {65.07936507936508, {8, 40, 13}}, + {65.07936507936509, {6, 40, 17}}, + {65.13409961685824, {8, 84, 28}}, + {65.14285714285715, {6, 56, 24}}, + {65.15151515151516, {5, 42, 21}}, + {65.16129032258064, {9, 100, 30}}, + {65.17857142857143, {7, 72, 27}}, + {65.18518518518518, {8, 43, 14}}, + {65.18518518518519, {4, 43, 26}}, + {65.21739130434783, {1, 14, 22}}, + {65.23297491039426, {8, 90, 30}}, + {65.26315789473684, {4, 30, 18}}, + {65.27777777777777, {8, 46, 15}}, + {65.27777777777779, {5, 46, 23}}, + {65.3061224489796, {6, 31, 13}}, + {65.3225806451613, {7, 80, 30}}, + {65.33333333333333, {9, 48, 14}}, + {65.33333333333334, {5, 48, 24}}, + {65.359477124183, {8, 49, 16}}, + {65.38461538461539, {3, 16, 12}}, + {65.4320987654321, {8, 52, 17}}, + {65.43778801843318, {6, 70, 30}}, + {65.45454545454545, {4, 17, 10}}, + {65.47619047619048, {7, 54, 20}}, + {65.49707602339181, {8, 55, 18}}, + {65.51724137931035, {1, 18, 28}}, + {65.54621848739497, {6, 38, 16}}, + {65.55555555555556, {9, 58, 17}}, + {65.59139784946237, {5, 60, 30}}, + {65.6, {4, 40, 24}}, + {65.60846560846561, {8, 61, 20}}, + {65.625, {3, 20, 15}}, + {65.65656565656565, {8, 64, 21}}, + {65.70048309178743, {8, 67, 22}}, + {65.71428571428571, {4, 22, 13}}, + {65.71428571428572, {6, 22, 9}}, + {65.74074074074075, {8, 70, 23}}, + {65.77777777777777, {8, 73, 24}}, + {65.78947368421052, {3, 24, 18}}, + {65.80645161290323, {4, 50, 30}}, + {65.8119658119658, {8, 76, 25}}, + {65.83333333333333, {9, 78, 23}}, + {65.8385093167702, {6, 52, 22}}, + {65.84362139917695, {8, 79, 26}}, + {65.87301587301587, {8, 82, 27}}, + {65.88235294117646, {4, 27, 16}}, + {65.90038314176245, {8, 85, 28}}, + {65.9090909090909, {7, 28, 10}}, + {65.92592592592592, {9, 88, 26}}, + {65.93406593406594, {6, 29, 12}}, + {65.94982078853046, {8, 91, 30}}, + {65.97222222222221, {8, 94, 31}}, + {66.0, {9, 32, 9}}, + {66.00985221674877, {6, 66, 28}}, + {66.07142857142857, {7, 36, 13}}, + {66.08695652173913, {4, 37, 22}}, + {66.12903225806451, {3, 40, 30}}, + {66.15384615384616, {9, 42, 12}}, + {66.16541353383458, {6, 43, 18}}, + {66.17647058823529, {7, 44, 16}}, + {66.20689655172414, {4, 47, 28}}, + {66.23376623376623, {6, 50, 21}}, + {66.25, {9, 52, 15}}, + {66.28571428571429, {6, 57, 24}}, + {66.30434782608695, {7, 60, 22}}, + {66.3157894736842, {9, 62, 18}}, + {66.32653061224491, {6, 64, 27}}, + {66.34615384615384, {7, 68, 25}}, + {66.3594470046083, {6, 71, 30}}, + {66.36363636363636, {9, 72, 21}}, + {66.37931034482759, {7, 76, 28}}, + {66.4, {9, 82, 24}}, + {66.40625, {7, 84, 31}}, + {66.42857142857143, {9, 92, 27}}, + {66.45161290322581, {9, 102, 30}}, + {66.66666666666666, {8, 29, 9}}, + {66.66666666666667, {0, 2, 8}}, + {66.875, {9, 106, 31}}, + {66.89655172413794, {9, 96, 28}}, + {66.92307692307692, {9, 86, 25}}, + {66.93548387096774, {7, 82, 30}}, + {66.95652173913044, {9, 76, 22}}, + {66.96428571428571, {7, 74, 27}}, + {66.96428571428572, {6, 74, 31}}, + {66.99507389162562, {6, 67, 28}}, + {67.0, {9, 66, 19}}, + {67.03296703296704, {6, 60, 25}}, + {67.04545454545455, {7, 58, 21}}, + {67.05882352941177, {9, 56, 16}}, + {67.08074534161491, {6, 53, 22}}, + {67.09677419354838, {4, 51, 30}}, + {67.10526315789474, {7, 50, 18}}, + {67.14285714285714, {9, 46, 13}}, + {67.1875, {7, 42, 15}}, + {67.2, {4, 41, 24}}, + {67.22689075630252, {6, 39, 16}}, + {67.24137931034483, {3, 38, 28}}, + {67.27272727272727, {9, 36, 10}}, + {67.28110599078342, {6, 72, 30}}, + {67.3076923076923, {7, 34, 12}}, + {67.33333333333333, {9, 100, 29}}, + {67.34693877551021, {6, 32, 13}}, + {67.36111111111111, {8, 96, 31}}, + {67.36842105263158, {4, 31, 18}}, + {67.38351254480285, {8, 93, 30}}, + {67.3913043478261, {3, 30, 22}}, + {67.4074074074074, {9, 90, 26}}, + {67.42857142857143, {6, 58, 24}}, + {67.43295019157088, {8, 87, 28}}, + {67.46031746031746, {8, 84, 27}}, + {67.48971193415638, {8, 81, 26}}, + {67.5, {7, 26, 9}}, + {67.52136752136752, {8, 78, 25}}, + {67.53246753246754, {6, 25, 10}}, + {67.55555555555556, {8, 75, 24}}, + {67.58620689655173, {4, 48, 28}}, + {67.5925925925926, {8, 72, 23}}, + {67.61904761904762, {9, 70, 20}}, + {67.63285024154588, {8, 69, 22}}, + {67.6470588235294, {3, 22, 16}}, + {67.66917293233082, {6, 44, 18}}, + {67.67676767676768, {8, 66, 21}}, + {67.6923076923077, {4, 21, 12}}, + {67.70833333333333, {7, 64, 23}}, + {67.70833333333334, {5, 64, 31}}, + {67.72486772486772, {8, 63, 20}}, + {67.72486772486774, {6, 63, 26}}, + {67.74193548387096, {1, 20, 30}}, + {67.77777777777777, {9, 60, 17}}, + {67.77777777777779, {5, 60, 29}}, + {67.816091954023, {5, 58, 28}}, + {67.82608695652173, {4, 38, 22}}, + {67.83625730994152, {8, 57, 18}}, + {67.85714285714286, {3, 18, 13}}, + {67.90123456790123, {8, 54, 17}}, + {67.90123456790124, {5, 54, 26}}, + {67.94871794871796, {5, 52, 25}}, + {67.96875, {7, 86, 31}}, + {67.97385620915031, {8, 51, 16}}, + {67.98029556650246, {6, 68, 28}}, + {68.0, {4, 16, 9}}, + {68.00000000000001, {5, 50, 24}}, + {68.02721088435375, {6, 49, 20}}, + {68.05555555555556, {8, 48, 15}}, + {68.10035842293907, {8, 94, 30}}, + {68.10344827586206, {7, 78, 28}}, + {68.11594202898551, {5, 46, 22}}, + {68.125, {9, 108, 31}}, + {68.13186813186813, {6, 30, 12}}, + {68.14814814814814, {8, 45, 14}}, + {68.14814814814815, {4, 45, 26}}, + {68.18181818181819, {3, 14, 10}}, + {68.19923371647509, {8, 88, 28}}, + {68.20276497695852, {6, 73, 30}}, + {68.23529411764706, {4, 28, 16}}, + {68.25396825396825, {8, 42, 13}}, + {68.25396825396827, {5, 42, 20}}, + {68.26923076923077, {7, 70, 25}}, + {68.27586206896552, {9, 98, 28}}, + {68.3127572016461, {8, 82, 26}}, + {68.32298136645963, {6, 54, 22}}, + {68.33333333333333, {9, 40, 11}}, + {68.33333333333334, {5, 40, 19}}, + {68.36734693877551, {6, 66, 27}}, + {68.37606837606837, {8, 39, 12}}, + {68.38709677419355, {4, 52, 30}}, + {68.42105263157895, {1, 12, 18}}, + {68.44444444444444, {8, 76, 24}}, + {68.46153846153847, {9, 88, 25}}, + {68.47826086956522, {7, 62, 22}}, + {68.51851851851852, {8, 36, 11}}, + {68.51851851851853, {5, 36, 17}}, + {68.54838709677419, {7, 84, 30}}, + {68.57142857142857, {4, 23, 13}}, + {68.57142857142858, {6, 23, 9}}, + {68.59903381642512, {8, 70, 22}}, + {68.62745098039215, {5, 34, 16}}, + {68.66666666666667, {9, 102, 29}}, + {68.68686868686869, {8, 33, 10}}, + {68.69565217391305, {9, 78, 22}}, + {68.75, {7, 32, 11}}, + {68.78306878306879, {8, 64, 20}}, + {68.8, {4, 42, 24}}, + {68.81720430107526, {8, 95, 30}}, + {68.81720430107528, {2, 31, 30}}, + {68.83116883116884, {6, 52, 21}}, + {68.88888888888889, {9, 30, 8}}, + {68.8888888888889, {5, 30, 14}}, + {68.9075630252101, {6, 40, 16}}, + {68.96551724137932, {0, 9, 28}}, + {69.0, {9, 68, 19}}, + {69.00584795321637, {8, 58, 18}}, + {69.03225806451613, {9, 106, 30}}, + {69.04761904761905, {6, 28, 11}}, + {69.0909090909091, {4, 18, 10}}, + {69.11764705882354, {7, 46, 16}}, + {69.12442396313365, {6, 74, 30}}, + {69.1358024691358, {8, 27, 8}}, + {69.13580246913581, {2, 27, 26}}, + {69.16666666666667, {9, 82, 23}}, + {69.17293233082708, {6, 45, 18}}, + {69.23076923076923, {1, 8, 12}}, + {69.23076923076924, {5, 26, 12}}, + {69.281045751634, {8, 52, 16}}, + {69.28571428571429, {9, 96, 27}}, + {69.31818181818181, {7, 60, 21}}, + {69.33333333333333, {4, 25, 14}}, + {69.33333333333334, {2, 25, 24}}, + {69.35483870967742, {3, 42, 30}}, + {69.375, {9, 110, 31}}, + {69.38775510204081, {6, 33, 13}}, + {69.41176470588235, {9, 58, 16}}, + {69.44444444444444, {7, 24, 8}}, + {69.47368421052632, {4, 32, 18}}, + {69.52380952380952, {9, 72, 20}}, + {69.52380952380953, {6, 72, 29}}, + {69.53125, {7, 88, 31}}, + {69.53405017921148, {8, 96, 30}}, + {69.56521739130434, {0, 7, 22}}, + {69.6, {9, 86, 24}}, + {69.62962962962962, {8, 46, 14}}, + {69.62962962962963, {4, 46, 26}}, + {69.64285714285714, {7, 38, 13}}, + {69.64285714285715, {6, 38, 15}}, + {69.65517241379311, {9, 100, 28}}, + {69.6774193548387, {4, 53, 30}}, + {69.69696969696969, {8, 68, 21}}, + {69.6969696969697, {5, 22, 10}}, + {69.71428571428572, {6, 60, 24}}, + {69.73180076628353, {8, 90, 28}}, + {69.73684210526316, {7, 52, 18}}, + {69.79166666666667, {7, 66, 23}}, + {69.82758620689656, {7, 80, 28}}, + {69.84126984126983, {6, 21, 8}}, + {69.84126984126985, {2, 21, 20}}, + {69.89247311827958, {5, 64, 30}}, + {69.95073891625616, {6, 70, 28}}, + {69.95884773662551, {8, 84, 26}}, + {70.0, {1, 6, 9}}, + {70.04608294930875, {6, 75, 30}}, + {70.08547008547008, {8, 40, 12}}, + {70.11494252873564, {5, 60, 28}}, + {70.12987012987013, {6, 26, 10}}, + {70.13888888888889, {8, 100, 31}}, + {70.16129032258064, {7, 86, 30}}, + {70.17543859649122, {8, 59, 18}}, + {70.17543859649123, {2, 19, 18}}, + {70.1923076923077, {7, 72, 25}}, + {70.22222222222221, {8, 78, 24}}, + {70.23809523809524, {7, 58, 20}}, + {70.25089605734767, {8, 97, 30}}, + {70.3125, {7, 44, 15}}, + {70.3225806451613, {9, 108, 30}}, + {70.32967032967034, {6, 31, 12}}, + {70.34482758620689, {4, 50, 28}}, + {70.37037037037037, {8, 37, 11}}, + {70.37037037037038, {5, 18, 8}}, + {70.4, {4, 43, 24}}, + {70.40816326530613, {6, 68, 27}}, + {70.43478260869566, {9, 80, 22}}, + {70.45454545454545, {7, 30, 10}}, + {70.47619047619047, {6, 36, 14}}, + {70.47619047619048, {4, 36, 20}}, + {70.49808429118774, {8, 91, 28}}, + {70.51282051282053, {5, 54, 25}}, + {70.52631578947368, {9, 66, 18}}, + {70.53140096618357, {8, 72, 22}}, + {70.53571428571429, {7, 78, 27}}, + {70.58823529411765, {0, 5, 16}}, + {70.625, {9, 112, 31}}, + {70.63492063492063, {8, 88, 27}}, + {70.65217391304348, {7, 64, 22}}, + {70.66666666666667, {9, 52, 14}}, + {70.67669172932331, {6, 46, 18}}, + {70.6896551724138, {3, 40, 28}}, + {70.7070707070707, {8, 34, 10}}, + {70.71428571428571, {9, 98, 27}}, + {70.74829931972789, {6, 51, 20}}, + {70.76923076923077, {4, 22, 12}}, + {70.78189300411522, {8, 85, 26}}, + {70.80745341614907, {6, 56, 22}}, + {70.83333333333333, {3, 16, 11}}, + {70.83333333333334, {2, 16, 15}}, + {70.85714285714286, {6, 61, 24}}, + {70.8994708994709, {8, 66, 20}}, + {70.9090909090909, {9, 38, 10}}, + {70.93596059113301, {6, 71, 28}}, + {70.94017094017093, {8, 82, 25}}, + {70.96774193548387, {0, 10, 30}}, + {71.0, {9, 70, 19}}, + {71.0144927536232, {5, 48, 22}}, + {71.03448275862068, {9, 102, 28}}, + {71.05263157894737, {3, 26, 18}}, + {71.09375, {7, 90, 31}}, + {71.1111111111111, {8, 47, 14}}, + {71.11111111111111, {4, 15, 8}}, + {71.15384615384616, {7, 36, 12}}, + {71.2, {9, 88, 24}}, + {71.21212121212122, {5, 46, 21}}, + {71.25, {9, 56, 15}}, + {71.26436781609195, {8, 92, 28}}, + {71.26436781609196, {2, 30, 28}}, + {71.29629629629629, {8, 76, 23}}, + {71.30434782608695, {4, 40, 22}}, + {71.33333333333333, {9, 106, 29}}, + {71.34502923976608, {8, 60, 18}}, + {71.42857142857143, {6, 24, 9}}, + {71.49758454106279, {8, 73, 22}}, + {71.52777777777777, {8, 102, 31}}, + {71.53846153846153, {9, 92, 25}}, + {71.55172413793103, {7, 82, 28}}, + {71.57894736842105, {4, 33, 18}}, + {71.5909090909091, {7, 62, 21}}, + {71.60493827160494, {8, 28, 8}}, + {71.60493827160495, {2, 28, 26}}, + {71.61290322580645, {9, 110, 30}}, + {71.66666666666667, {9, 42, 11}}, + {71.68458781362007, {8, 99, 30}}, + {71.71717171717172, {8, 70, 21}}, + {71.72413793103448, {4, 51, 28}}, + {71.73913043478261, {3, 32, 22}}, + {71.76470588235294, {9, 60, 16}}, + {71.7741935483871, {7, 88, 30}}, + {71.7948717948718, {8, 41, 12}}, + {71.81818181818181, {9, 78, 21}}, + {71.85185185185185, {9, 96, 26}}, + {71.85185185185186, {8, 96, 29}}, + {71.875, {3, 22, 15}}, + {71.889400921659, {6, 77, 30}}, + {71.89542483660131, {8, 54, 16}}, + {71.92118226600985, {6, 72, 28}}, + {71.9298245614035, {5, 40, 18}}, + {71.95767195767196, {8, 67, 20}}, + {72.0, {4, 17, 9}}, + {72.00000000000001, {2, 26, 24}}, + {72.03065134099616, {8, 93, 28}}, + {72.04301075268818, {5, 66, 30}}, + {72.0496894409938, {6, 57, 22}}, + {72.05882352941177, {7, 48, 16}}, + {72.10884353741497, {6, 52, 20}}, + {72.11538461538461, {7, 74, 25}}, + {72.14285714285714, {9, 100, 27}}, + {72.17391304347827, {9, 82, 22}}, + {72.18045112781955, {6, 47, 18}}, + {72.22222222222221, {8, 38, 11}}, + {72.22222222222223, {3, 12, 8}}, + {72.25806451612904, {4, 55, 30}}, + {72.26890756302521, {6, 42, 16}}, + {72.3076923076923, {9, 46, 12}}, + {72.32142857142857, {7, 80, 27}}, + {72.36842105263158, {7, 54, 18}}, + {72.38095238095238, {6, 37, 14}}, + {72.40143369175627, {8, 100, 30}}, + {72.41379310344827, {1, 20, 28}}, + {72.42798353909464, {8, 87, 26}}, + {72.44897959183673, {6, 70, 27}}, + {72.46376811594202, {8, 74, 22}}, + {72.46376811594203, {2, 24, 22}}, + {72.5, {7, 28, 9}}, + {72.51461988304094, {8, 61, 18}}, + {72.52747252747253, {6, 32, 12}}, + {72.54901960784315, {5, 36, 16}}, + {72.58064516129032, {3, 44, 30}}, + {72.5925925925926, {8, 48, 14}}, + {72.61904761904762, {7, 60, 20}}, + {72.63157894736842, {9, 68, 18}}, + {72.64957264957265, {8, 84, 25}}, + {72.65625, {7, 92, 31}}, + {72.66666666666667, {9, 108, 29}}, + {72.72727272727273, {0, 3, 10}}, + {72.79693486590037, {8, 94, 28}}, + {72.8, {9, 90, 24}}, + {72.8110599078341, {6, 78, 30}}, + {72.82608695652173, {7, 66, 22}}, + {72.8395061728395, {8, 58, 17}}, + {72.85714285714286, {9, 50, 13}}, + {72.88888888888889, {8, 81, 24}}, + {72.90322580645162, {9, 112, 30}}, + {72.90640394088669, {6, 73, 28}}, + {72.91666666666666, {8, 104, 31}}, + {72.91666666666667, {7, 34, 11}}, + {72.94117647058823, {4, 30, 16}}, + {73.0, {9, 72, 19}}, + {73.01587301587301, {8, 45, 13}}, + {73.01587301587303, {6, 22, 8}}, + {73.04347826086956, {4, 41, 22}}, + {73.07692307692308, {3, 18, 12}}, + {73.10344827586206, {4, 52, 28}}, + {73.11827956989247, {8, 101, 30}}, + {73.11827956989248, {2, 33, 30}}, + {73.125, {9, 116, 31}}, + {73.14285714285715, {6, 63, 24}}, + {73.14814814814814, {8, 78, 23}}, + {73.14814814814815, {7, 78, 26}}, + {73.20261437908496, {8, 55, 16}}, + {73.21428571428571, {7, 40, 13}}, + {73.21428571428572, {6, 40, 15}}, + {73.25102880658436, {8, 88, 26}}, + {73.27586206896552, {7, 84, 28}}, + {73.29192546583852, {6, 58, 22}}, + {73.33333333333333, {9, 32, 8}}, + {73.33333333333334, {2, 10, 9}}, + {73.38709677419355, {7, 90, 30}}, + {73.42995169082126, {8, 75, 22}}, + {73.4375, {7, 46, 15}}, + {73.46938775510205, {6, 35, 13}}, + {73.5042735042735, {8, 42, 12}}, + {73.52941176470588, {3, 24, 16}}, + {73.54838709677419, {4, 56, 30}}, + {73.5632183908046, {8, 95, 28}}, + {73.56321839080461, {2, 31, 28}}, + {73.57142857142857, {9, 102, 27}}, + {73.6, {4, 45, 24}}, + {73.61111111111111, {8, 52, 15}}, + {73.62637362637363, {6, 66, 25}}, + {73.63636363636364, {9, 80, 21}}, + {73.6842105263158, {0, 6, 18}}, + {73.73271889400922, {6, 79, 30}}, + {73.73737373737373, {8, 72, 21}}, + {73.75, {9, 58, 15}}, + {73.77777777777777, {8, 82, 24}}, + {73.79310344827586, {9, 106, 28}}, + {73.80952380952381, {6, 30, 11}}, + {73.80952380952382, {5, 30, 13}}, + {73.83512544802866, {8, 102, 30}}, + {73.84615384615384, {4, 23, 12}}, + {73.86363636363636, {7, 64, 21}}, + {73.89162561576356, {6, 74, 28}}, + {73.91304347826087, {1, 16, 22}}, + {73.94957983193277, {6, 43, 16}}, + {73.95833333333333, {7, 70, 23}}, + {73.95833333333334, {5, 70, 31}}, + {74.0, {9, 36, 9}}, + {74.02597402597404, {6, 56, 21}}, + {74.03846153846153, {7, 76, 25}}, + {74.07407407407406, {8, 69, 20}}, + {74.07407407407408, {8, 29, 8}}, + {74.10714285714286, {7, 82, 27}}, + {74.11764705882354, {9, 62, 16}}, + {74.13793103448276, {3, 42, 28}}, + {74.16666666666667, {9, 88, 23}}, + {74.19354838709677, {1, 22, 30}}, + {74.21875, {7, 94, 31}}, + {74.24242424242425, {5, 48, 21}}, + {74.28571428571429, {6, 25, 9}}, + {74.30555555555556, {8, 106, 31}}, + {74.32950191570882, {8, 96, 28}}, + {74.35897435897435, {8, 86, 25}}, + {74.35897435897436, {5, 28, 12}}, + {74.375, {9, 118, 31}}, + {74.39613526570048, {8, 76, 22}}, + {74.4, {9, 92, 24}}, + {74.44444444444444, {9, 66, 17}}, + {74.48275862068965, {4, 53, 28}}, + {74.48979591836735, {6, 72, 27}}, + {74.50980392156862, {8, 56, 16}}, + {74.50980392156863, {2, 18, 16}}, + {74.53416149068323, {6, 59, 22}}, + {74.54545454545455, {9, 40, 10}}, + {74.55197132616486, {8, 103, 30}}, + {74.6031746031746, {8, 46, 13}}, + {74.60317460317461, {6, 46, 17}}, + {74.61538461538461, {9, 96, 25}}, + {74.65437788018433, {6, 80, 30}}, + {74.66666666666666, {8, 83, 24}}, + {74.66666666666667, {4, 27, 14}}, + {74.71264367816093, {5, 64, 28}}, + {74.72527472527473, {6, 33, 12}}, + {74.73684210526316, {9, 70, 18}}, + {74.74747474747474, {8, 36, 10}}, + {74.78260869565217, {4, 42, 22}}, + {74.81481481481481, {9, 100, 26}}, + {74.82993197278913, {6, 54, 20}}, + {74.83870967741936, {4, 57, 30}}, + {74.85380116959064, {8, 63, 18}}, + {74.8768472906404, {6, 75, 28}}, + {74.89711934156378, {8, 90, 26}}, + {75.0, {0, 2, 7}}, + {75.00000000000001, {5, 26, 11}}, + {75.09578544061303, {8, 97, 28}}, + {75.13227513227514, {8, 70, 20}}, + {75.17241379310344, {9, 108, 28}}, + {75.18796992481204, {6, 49, 18}}, + {75.2, {4, 46, 24}}, + {75.2136752136752, {8, 43, 12}}, + {75.23809523809524, {9, 78, 20}}, + {75.26881720430107, {8, 104, 30}}, + {75.26881720430109, {2, 34, 30}}, + {75.29411764705883, {4, 31, 16}}, + {75.30864197530863, {8, 60, 17}}, + {75.30864197530865, {5, 60, 26}}, + {75.32467532467534, {6, 28, 10}}, + {75.33333333333333, {9, 112, 29}}, + {75.3623188405797, {8, 77, 22}}, + {75.36231884057972, {2, 25, 22}}, + {75.38461538461539, {9, 48, 12}}, + {75.39682539682539, {8, 94, 27}}, + {75.42857142857143, {6, 65, 24}}, + {75.43859649122808, {5, 42, 18}}, + {75.45454545454545, {9, 82, 21}}, + {75.48387096774194, {9, 116, 30}}, + {75.51020408163265, {6, 36, 13}}, + {75.55555555555556, {4, 16, 8}}, + {75.55555555555557, {2, 16, 14}}, + {75.57603686635946, {6, 81, 30}}, + {75.625, {9, 120, 31}}, + {75.63025210084034, {6, 44, 16}}, + {75.64102564102565, {5, 58, 25}}, + {75.65217391304348, {9, 86, 22}}, + {75.69444444444444, {8, 108, 31}}, + {75.71428571428571, {9, 52, 13}}, + {75.71428571428572, {6, 52, 19}}, + {75.7201646090535, {8, 91, 26}}, + {75.75757575757575, {8, 74, 21}}, + {75.75757575757576, {5, 24, 10}}, + {75.77639751552795, {6, 60, 22}}, + {75.78125, {7, 96, 31}}, + {75.78947368421052, {4, 35, 18}}, + {75.80645161290323, {3, 46, 30}}, + {75.81699346405229, {8, 57, 16}}, + {75.82417582417582, {6, 68, 25}}, + {75.83333333333333, {9, 90, 23}}, + {75.86206896551724, {0, 10, 28}}, + {75.89285714285714, {7, 84, 27}}, + {75.89285714285715, {6, 84, 31}}, + {75.92592592592592, {8, 40, 11}}, + {75.96153846153847, {7, 78, 25}}, + {75.98566308243728, {8, 105, 30}}, + {76.0, {4, 18, 9}}, + {76.00000000000001, {5, 56, 24}}, + {76.0233918128655, {8, 64, 18}}, + {76.04166666666667, {7, 72, 23}}, + {76.06837606837607, {8, 88, 25}}, + {76.08695652173913, {3, 34, 22}}, + {76.12903225806451, {4, 58, 30}}, + {76.13636363636364, {7, 66, 21}}, + {76.15384615384616, {9, 98, 25}}, + {76.19047619047618, {8, 47, 13}}, + {76.19047619047619, {6, 31, 11}}, + {76.1904761904762, {6, 23, 8}}, + {76.25, {9, 60, 15}}, + {76.29629629629629, {9, 102, 26}}, + {76.3157894736842, {3, 28, 18}}, + {76.32850241545893, {8, 78, 22}}, + {76.34408602150539, {5, 70, 30}}, + {76.36363636363636, {4, 20, 10}}, + {76.38888888888889, {8, 54, 15}}, + {76.3888888888889, {5, 54, 23}}, + {76.42857142857143, {9, 106, 27}}, + {76.44444444444444, {8, 85, 24}}, + {76.47058823529412, {1, 12, 16}}, + {76.49769585253456, {6, 82, 30}}, + {76.52173913043478, {4, 43, 22}}, + {76.53061224489797, {6, 74, 27}}, + {76.5432098765432, {8, 92, 26}}, + {76.54320987654322, {8, 30, 8}}, + {76.55172413793103, {9, 110, 28}}, + {76.5625, {7, 48, 15}}, + {76.57142857142858, {6, 66, 24}}, + {76.61290322580645, {7, 94, 30}}, + {76.62337662337663, {6, 58, 21}}, + {76.62835249042145, {8, 99, 28}}, + {76.66666666666666, {8, 68, 19}}, + {76.66666666666667, {5, 22, 9}}, + {76.69172932330827, {6, 50, 18}}, + {76.70250896057348, {8, 106, 30}}, + {76.72413793103448, {7, 88, 28}}, + {76.76767676767678, {8, 37, 10}}, + {76.7741935483871, {9, 118, 30}}, + {76.78571428571429, {7, 42, 13}}, + {76.8, {4, 47, 24}}, + {76.81159420289855, {5, 52, 22}}, + {76.84210526315789, {9, 72, 18}}, + {76.8472906403941, {6, 77, 28}}, + {76.85185185185185, {8, 82, 23}}, + {76.875, {9, 122, 31}}, + {76.92307692307692, {0, 4, 12}}, + {76.92307692307693, {2, 14, 12}}, + {76.98412698412699, {8, 96, 27}}, + {77.0, {9, 76, 19}}, + {77.01149425287358, {5, 66, 28}}, + {77.01863354037268, {6, 61, 22}}, + {77.03703703703702, {8, 51, 14}}, + {77.03703703703704, {4, 51, 26}}, + {77.08333333333333, {7, 36, 11}}, + {77.08333333333334, {5, 36, 15}}, + {77.12418300653594, {8, 58, 16}}, + {77.14285714285714, {6, 26, 9}}, + {77.17391304347827, {7, 70, 22}}, + {77.19298245614034, {8, 65, 18}}, + {77.19298245614036, {2, 21, 18}}, + {77.24137931034483, {4, 55, 28}}, + {77.24867724867724, {8, 72, 20}}, + {77.24867724867725, {6, 72, 26}}, + {77.27272727272727, {3, 16, 10}}, + {77.27272727272728, {5, 50, 21}}, + {77.29468599033817, {8, 79, 22}}, + {77.31092436974791, {6, 45, 16}}, + {77.33333333333333, {4, 28, 14}}, + {77.33333333333334, {2, 28, 24}}, + {77.34375, {7, 98, 31}}, + {77.36625514403292, {8, 93, 26}}, + {77.38095238095238, {7, 64, 20}}, + {77.3809523809524, {6, 64, 23}}, + {77.3913043478261, {9, 88, 22}}, + {77.39463601532567, {8, 100, 28}}, + {77.41935483870968, {0, 11, 30}}, + {77.5, {9, 30, 7}}, + {77.55102040816327, {6, 37, 13}}, + {77.58620689655173, {3, 44, 28}}, + {77.6, {9, 96, 24}}, + {77.63157894736842, {7, 58, 18}}, + {77.6470588235294, {4, 32, 16}}, + {77.67857142857143, {7, 86, 27}}, + {77.6923076923077, {9, 100, 25}}, + {77.71428571428572, {6, 67, 24}}, + {77.77777777777777, {8, 27, 7}}, + {77.77777777777779, {2, 13, 11}}, + {77.83251231527095, {6, 78, 28}}, + {77.85714285714286, {9, 108, 27}}, + {77.88461538461539, {7, 80, 25}}, + {77.89473684210526, {4, 36, 18}}, + {77.92207792207793, {6, 29, 10}}, + {77.93103448275862, {9, 112, 28}}, + {77.94117647058823, {7, 52, 16}}, + {78.0, {9, 38, 9}}, + {78.02197802197803, {6, 70, 25}}, + {78.06451612903226, {9, 120, 30}}, + {78.0952380952381, {6, 40, 14}}, + {78.125, {7, 24, 7}}, + {78.13620071684588, {8, 108, 30}}, + {78.16091954022988, {8, 101, 28}}, + {78.1609195402299, {2, 33, 28}}, + {78.18181818181819, {9, 42, 10}}, + {78.18930041152262, {8, 94, 26}}, + {78.19548872180451, {6, 51, 18}}, + {78.2051282051282, {5, 60, 25}}, + {78.22222222222221, {8, 87, 24}}, + {78.2258064516129, {7, 96, 30}}, + {78.26086956521739, {0, 8, 22}}, + {78.2608695652174, {2, 26, 22}}, + {78.3068783068783, {8, 73, 20}}, + {78.33333333333333, {9, 46, 11}}, + {78.33333333333334, {5, 46, 19}}, + {78.3410138248848, {6, 84, 30}}, + {78.3625730994152, {8, 66, 18}}, + {78.4, {4, 48, 24}}, + {78.4090909090909, {7, 68, 21}}, + {78.4313725490196, {8, 59, 16}}, + {78.43137254901961, {2, 19, 16}}, + {78.44827586206897, {7, 90, 28}}, + {78.46153846153847, {9, 50, 12}}, + {78.47222222222221, {8, 112, 31}}, + {78.49462365591398, {5, 72, 30}}, + {78.51851851851852, {8, 52, 14}}, + {78.57142857142857, {6, 21, 7}}, + {78.57142857142858, {6, 54, 19}}, + {78.62068965517241, {4, 56, 28}}, + {78.63247863247862, {8, 45, 12}}, + {78.66666666666667, {9, 58, 14}}, + {78.70370370370371, {8, 84, 23}}, + {78.70967741935483, {4, 60, 30}}, + {78.75, {9, 62, 15}}, + {78.78787878787878, {8, 38, 10}}, + {78.7878787878788, {2, 12, 10}}, + {78.81773399014779, {6, 79, 28}}, + {78.82352941176471, {9, 66, 16}}, + {78.84615384615384, {7, 40, 12}}, + {78.85304659498208, {8, 109, 30}}, + {78.85714285714286, {6, 68, 24}}, + {78.88888888888889, {9, 70, 17}}, + {78.8888888888889, {5, 70, 29}}, + {78.90625, {7, 100, 31}}, + {78.91156462585035, {6, 57, 20}}, + {78.9272030651341, {8, 102, 28}}, + {78.94736842105263, {1, 14, 18}}, + {78.99159663865547, {6, 46, 16}}, + {79.0, {9, 78, 19}}, + {79.01234567901234, {8, 31, 8}}, + {79.01234567901236, {2, 31, 26}}, + {79.03225806451613, {3, 48, 30}}, + {79.04761904761905, {9, 82, 20}}, + {79.0909090909091, {9, 86, 21}}, + {79.1111111111111, {8, 88, 24}}, + {79.12087912087912, {6, 35, 12}}, + {79.1304347826087, {9, 90, 22}}, + {79.16666666666666, {8, 56, 15}}, + {79.16666666666667, {5, 18, 7}}, + {79.2, {9, 98, 24}}, + {79.22077922077922, {6, 60, 21}}, + {79.22705314009661, {8, 81, 22}}, + {79.23076923076923, {9, 102, 25}}, + {79.25925925925925, {9, 106, 26}}, + {79.25925925925927, {8, 106, 29}}, + {79.26267281105991, {6, 85, 30}}, + {79.28571428571429, {9, 110, 27}}, + {79.3103448275862, {1, 22, 28}}, + {79.33333333333333, {9, 118, 29}}, + {79.34782608695652, {7, 72, 22}}, + {79.35483870967742, {9, 122, 30}}, + {79.36507936507935, {8, 74, 20}}, + {79.36507936507937, {6, 24, 8}}, + {79.36507936507938, {6, 74, 26}}, + {79.375, {9, 126, 31}}, + {79.41176470588235, {3, 26, 16}}, + {79.46428571428571, {7, 88, 27}}, + {79.46428571428572, {6, 88, 31}}, + {79.48717948717947, {8, 92, 25}}, + {79.4871794871795, {5, 30, 12}}, + {79.50310559006212, {6, 63, 22}}, + {79.53216374269006, {8, 67, 18}}, + {79.54545454545455, {7, 34, 10}}, + {79.56989247311827, {8, 110, 30}}, + {79.56989247311829, {2, 36, 30}}, + {79.59183673469389, {6, 38, 13}}, + {79.62962962962963, {8, 42, 11}}, + {79.6875, {7, 50, 15}}, + {79.6934865900383, {8, 103, 28}}, + {79.69924812030077, {6, 52, 18}}, + {79.71014492753623, {5, 54, 22}}, + {79.73856209150325, {8, 60, 16}}, + {79.76190476190476, {7, 66, 20}}, + {79.76190476190477, {6, 66, 23}}, + {79.79797979797979, {8, 78, 21}}, + {79.80295566502463, {6, 80, 28}}, + {79.8076923076923, {7, 82, 25}}, + {79.83539094650206, {8, 96, 26}}, + {79.83870967741936, {7, 98, 30}}, + {79.86111111111111, {8, 114, 31}}, + {80.0, {4, 15, 7}}, + {80.00000000000001, {2, 29, 24}}, + {80.15873015873015, {8, 100, 27}}, + {80.17241379310344, {7, 92, 28}}, + {80.18433179723503, {6, 86, 30}}, + {80.19323671497584, {8, 82, 22}}, + {80.20833333333333, {7, 76, 23}}, + {80.20833333333334, {5, 76, 31}}, + {80.21978021978022, {6, 72, 25}}, + {80.24691358024691, {8, 64, 17}}, + {80.24691358024693, {5, 64, 26}}, + {80.26315789473684, {7, 60, 18}}, + {80.27210884353742, {6, 58, 20}}, + {80.28673835125447, {8, 111, 30}}, + {80.30303030303031, {5, 52, 21}}, + {80.34188034188034, {8, 46, 12}}, + {80.35714285714286, {7, 44, 13}}, + {80.3921568627451, {5, 40, 16}}, + {80.42328042328043, {8, 75, 20}}, + {80.43478260869566, {3, 36, 22}}, + {80.45977011494251, {8, 104, 28}}, + {80.45977011494253, {2, 34, 28}}, + {80.46875, {7, 102, 31}}, + {80.51948051948052, {6, 30, 10}}, + {80.55555555555556, {8, 28, 7}}, + {80.61224489795919, {6, 78, 27}}, + {80.625, {9, 128, 31}}, + {80.64516129032258, {1, 24, 30}}, + {80.65843621399178, {8, 97, 26}}, + {80.66666666666667, {9, 120, 29}}, + {80.67226890756304, {6, 47, 16}}, + {80.68181818181819, {7, 70, 21}}, + {80.6896551724138, {9, 116, 28}}, + {80.7017543859649, {8, 68, 18}}, + {80.70175438596492, {2, 22, 18}}, + {80.71428571428571, {9, 112, 27}}, + {80.74074074074073, {8, 108, 29}}, + {80.74074074074075, {9, 108, 26}}, + {80.74534161490683, {6, 64, 22}}, + {80.76923076923077, {3, 20, 12}}, + {80.78817733990148, {6, 81, 28}}, + {80.8, {9, 100, 24}}, + {80.80808080808082, {8, 39, 10}}, + {80.83333333333333, {9, 96, 23}}, + {80.8695652173913, {9, 92, 22}}, + {80.88235294117646, {7, 54, 16}}, + {80.88888888888889, {8, 90, 24}}, + {80.9090909090909, {9, 88, 21}}, + {80.95238095238095, {6, 33, 11}}, + {80.95238095238096, {2, 16, 13}}, + {81.0, {9, 80, 19}}, + {81.00358422939067, {8, 112, 30}}, + {81.03448275862068, {3, 46, 28}}, + {81.04575163398692, {8, 61, 16}}, + {81.05263157894737, {9, 76, 18}}, + {81.10599078341014, {6, 87, 30}}, + {81.11111111111111, {9, 72, 17}}, + {81.14285714285715, {6, 70, 24}}, + {81.15942028985506, {8, 83, 22}}, + {81.15942028985508, {2, 27, 22}}, + {81.17647058823529, {9, 68, 16}}, + {81.19658119658119, {8, 94, 25}}, + {81.203007518797, {6, 53, 18}}, + {81.22605363984675, {8, 105, 28}}, + {81.25, {3, 12, 7}}, + {81.29032258064517, {4, 62, 30}}, + {81.31868131868131, {6, 36, 12}}, + {81.33333333333333, {9, 60, 14}}, + {81.33333333333334, {5, 60, 24}}, + {81.37931034482759, {4, 58, 28}}, + {81.42857142857143, {9, 56, 13}}, + {81.45161290322581, {7, 100, 30}}, + {81.48148148148147, {8, 32, 8}}, + {81.48148148148148, {2, 10, 8}}, + {81.52173913043478, {7, 74, 22}}, + {81.53846153846153, {9, 52, 12}}, + {81.57894736842105, {3, 30, 18}}, + {81.6, {4, 50, 24}}, + {81.60919540229887, {5, 70, 28}}, + {81.63265306122449, {6, 39, 13}}, + {81.6326530612245, {6, 59, 20}}, + {81.66666666666667, {9, 48, 11}}, + {81.72043010752687, {8, 113, 30}}, + {81.72043010752688, {2, 37, 30}}, + {81.73076923076923, {7, 84, 25}}, + {81.73913043478261, {4, 46, 22}}, + {81.74603174603173, {8, 102, 27}}, + {81.77339901477833, {6, 82, 28}}, + {81.77777777777777, {8, 91, 24}}, + {81.81818181818181, {1, 8, 10}}, + {81.81818181818183, {5, 26, 10}}, + {81.87134502923976, {8, 69, 18}}, + {81.875, {9, 130, 31}}, + {81.89655172413794, {7, 94, 28}}, + {81.9047619047619, {4, 42, 20}}, + {81.90476190476191, {6, 42, 14}}, + {81.93548387096774, {9, 126, 30}}, + {81.94444444444444, {8, 58, 15}}, + {81.98757763975155, {6, 65, 22}}, + {81.99233716475096, {8, 106, 28}}, + {82.0, {9, 40, 9}}, + {82.02764976958527, {6, 88, 30}}, + {82.03125, {7, 104, 31}}, + {82.05128205128204, {8, 47, 12}}, + {82.05128205128206, {2, 15, 12}}, + {82.06896551724138, {9, 118, 28}}, + {82.10526315789474, {4, 38, 18}}, + {82.1256038647343, {8, 84, 22}}, + {82.14285714285714, {3, 22, 13}}, + {82.14285714285715, {6, 22, 7}}, + {82.22222222222221, {8, 36, 9}}, + {82.22222222222223, {9, 36, 8}}, + {82.25806451612904, {3, 50, 30}}, + {82.28571428571429, {6, 71, 24}}, + {82.29166666666667, {7, 78, 23}}, + {82.30452674897118, {8, 99, 26}}, + {82.3076923076923, {9, 106, 25}}, + {82.3529411764706, {0, 6, 16}}, + {82.4, {9, 102, 24}}, + {82.4074074074074, {8, 88, 23}}, + {82.41758241758242, {6, 74, 25}}, + {82.43727598566309, {8, 114, 30}}, + {82.45614035087719, {5, 46, 18}}, + {82.5, {9, 32, 7}}, + {82.53968253968253, {8, 51, 13}}, + {82.53968253968254, {6, 25, 8}}, + {82.58064516129032, {4, 63, 30}}, + {82.6086956521739, {1, 18, 22}}, + {82.60869565217392, {5, 56, 22}}, + {82.63888888888889, {8, 118, 31}}, + {82.65306122448979, {6, 80, 27}}, + {82.66666666666666, {8, 92, 24}}, + {82.66666666666667, {4, 30, 14}}, + {82.66666666666669, {2, 30, 24}}, + {82.6923076923077, {7, 42, 12}}, + {82.70676691729324, {6, 54, 18}}, + {82.71604938271605, {8, 66, 17}}, + {82.72727272727273, {9, 90, 21}}, + {82.75862068965517, {0, 11, 28}}, + {82.7956989247312, {5, 76, 30}}, + {82.8125, {7, 52, 15}}, + {82.82828282828282, {8, 40, 10}}, + {82.85714285714286, {6, 28, 9}}, + {82.89473684210526, {7, 62, 18}}, + {82.90598290598291, {8, 96, 25}}, + {82.94930875576037, {6, 89, 30}}, + {82.95454545454545, {7, 72, 21}}, + {82.96296296296296, {8, 55, 14}}, + {82.99319727891157, {6, 60, 20}}, + {83.0, {9, 82, 19}}, + {83.03571428571429, {7, 92, 27}}, + {83.04093567251462, {8, 70, 18}}, + {83.06451612903226, {7, 102, 30}}, + {83.07692307692308, {4, 26, 12}}, + {83.09178743961353, {8, 85, 22}}, + {83.11688311688312, {6, 31, 10}}, + {83.125, {9, 132, 31}}, + {83.1275720164609, {8, 100, 26}}, + {83.15412186379929, {8, 115, 30}}, + {83.15789473684211, {9, 78, 18}}, + {83.2, {4, 51, 24}}, + {83.2258064516129, {9, 128, 30}}, + {83.22981366459628, {6, 66, 22}}, + {83.33333333333333, {8, 29, 7}}, + {83.33333333333334, {2, 9, 7}}, + {83.42857142857143, {6, 72, 24}}, + {83.44827586206897, {9, 120, 28}}, + {83.47826086956522, {4, 47, 22}}, + {83.51648351648352, {6, 37, 12}}, + {83.52490421455938, {8, 108, 28}}, + {83.52941176470588, {9, 70, 16}}, + {83.55555555555554, {8, 93, 24}}, + {83.57142857142857, {9, 116, 27}}, + {83.59375, {7, 106, 31}}, + {83.5978835978836, {8, 78, 20}}, + {83.59788359788361, {6, 78, 26}}, + {83.62068965517241, {7, 96, 28}}, + {83.63636363636364, {4, 22, 10}}, + {83.65384615384616, {7, 86, 25}}, + {83.66013071895425, {8, 63, 16}}, + {83.6734693877551, {6, 40, 13}}, + {83.69565217391305, {7, 76, 22}}, + {83.7037037037037, {8, 112, 29}}, + {83.70370370370371, {9, 112, 26}}, + {83.74384236453203, {6, 84, 28}}, + {83.75, {9, 66, 15}}, + {83.76068376068376, {8, 48, 12}}, + {83.80952380952381, {6, 43, 14}}, + {83.82352941176471, {7, 56, 16}}, + {83.83838383838383, {8, 82, 21}}, + {83.84615384615384, {9, 108, 25}}, + {83.87096774193549, {0, 12, 30}}, + {83.9080459770115, {5, 72, 28}}, + {83.92857142857143, {7, 46, 13}}, + {83.9506172839506, {8, 101, 26}}, + {83.95061728395062, {8, 33, 8}}, + {83.95061728395063, {2, 33, 26}}, + {84.0, {4, 20, 9}}, + {84.02777777777777, {8, 120, 31}}, + {84.03361344537815, {6, 49, 16}}, + {84.05797101449275, {8, 86, 22}}, + {84.05797101449276, {2, 28, 22}}, + {84.0909090909091, {7, 36, 10}}, + {84.12698412698413, {8, 52, 13}}, + {84.12698412698414, {6, 52, 17}}, + {84.13793103448276, {4, 60, 28}}, + {84.16666666666667, {9, 100, 23}}, + {84.21052631578948, {0, 7, 18}}, + {84.25925925925925, {8, 90, 23}}, + {84.28571428571429, {9, 58, 13}}, + {84.2911877394636, {8, 109, 28}}, + {84.31372549019609, {5, 42, 16}}, + {84.34782608695652, {9, 96, 22}}, + {84.35374149659864, {6, 61, 20}}, + {84.375, {7, 26, 7}}, + {84.41558441558442, {6, 64, 21}}, + {84.44444444444443, {8, 56, 14}}, + {84.44444444444444, {4, 18, 8}}, + {84.472049689441, {6, 67, 22}}, + {84.48275862068965, {3, 48, 28}}, + {84.51612903225806, {9, 130, 30}}, + {84.52380952380952, {7, 70, 20}}, + {84.52380952380953, {6, 70, 23}}, + {84.54545454545455, {9, 92, 21}}, + {84.57142857142857, {6, 73, 24}}, + {84.58781362007169, {8, 117, 30}}, + {84.61538461538461, {1, 10, 12}}, + {84.65608465608466, {8, 79, 20}}, + {84.66666666666667, {9, 126, 29}}, + {84.6774193548387, {7, 104, 30}}, + {84.6938775510204, {6, 82, 27}}, + {84.70588235294117, {4, 35, 16}}, + {84.72222222222221, {8, 60, 15}}, + {84.72222222222223, {7, 60, 17}}, + {84.72906403940887, {6, 85, 28}}, + {84.76190476190476, {9, 88, 20}}, + {84.76190476190477, {6, 88, 29}}, + {84.77366255144032, {8, 102, 26}}, + {84.78260869565217, {3, 38, 22}}, + {84.7926267281106, {6, 91, 30}}, + {84.8, {4, 52, 24}}, + {84.82142857142857, {7, 94, 27}}, + {84.82758620689656, {9, 122, 28}}, + {84.84848484848484, {8, 41, 10}}, + {84.84848484848486, {2, 13, 10}}, + {84.92063492063492, {8, 106, 27}}, + {84.94623655913979, {5, 78, 30}}, + {84.9673202614379, {8, 64, 16}}, + {85.0, {4, 16, 7}}, + {85.00000000000001, {5, 50, 19}}, + {85.02415458937197, {8, 87, 22}}, + {85.0574712643678, {8, 110, 28}}, + {85.05747126436782, {2, 36, 28}}, + {85.15625, {7, 108, 31}}, + {85.16129032258064, {4, 65, 30}}, + {85.18518518518518, {8, 45, 11}}, + {85.18518518518519, {5, 22, 8}}, + {85.21739130434783, {4, 48, 22}}, + {85.22727272727273, {7, 74, 21}}, + {85.26315789473684, {9, 80, 18}}, + {85.29411764705883, {3, 28, 16}}, + {85.30465949820788, {8, 118, 30}}, + {85.33333333333331, {8, 95, 24}}, + {85.33333333333333, {4, 31, 14}}, + {85.33333333333334, {2, 31, 24}}, + {85.34482758620689, {7, 98, 28}}, + {85.38011695906432, {8, 72, 18}}, + {85.38461538461539, {9, 110, 25}}, + {85.41666666666666, {8, 122, 31}}, + {85.41666666666667, {7, 40, 11}}, + {85.45454545454545, {9, 46, 10}}, + {85.47008547008546, {8, 49, 12}}, + {85.48387096774194, {3, 52, 30}}, + {85.5072463768116, {5, 58, 22}}, + {85.51724137931035, {4, 61, 28}}, + {85.52631578947368, {7, 64, 18}}, + {85.55555555555556, {9, 76, 17}}, + {85.55555555555557, {5, 76, 29}}, + {85.57692307692308, {7, 88, 25}}, + {85.59670781893003, {8, 103, 26}}, + {85.6, {9, 106, 24}}, + {85.625, {9, 136, 31}}, + {85.71428571428571, {0, 2, 6}}, + {85.71428571428572, {6, 23, 7}}, + {85.80645161290323, {9, 132, 30}}, + {85.82375478927203, {8, 111, 28}}, + {85.83333333333333, {9, 102, 23}}, + {85.85858585858585, {8, 84, 21}}, + {85.8695652173913, {7, 78, 22}}, + {85.88235294117646, {9, 72, 16}}, + {85.8974358974359, {5, 66, 25}}, + {85.92592592592592, {8, 57, 14}}, + {85.9375, {7, 54, 15}}, + {85.96491228070177, {5, 48, 18}}, + {85.9903381642512, {8, 88, 22}}, + {86.0, {9, 42, 9}}, + {86.02150537634408, {8, 119, 30}}, + {86.0215053763441, {2, 39, 30}}, + {86.08695652173913, {9, 98, 22}}, + {86.1111111111111, {8, 92, 23}}, + {86.11111111111111, {8, 30, 7}}, + {86.11111111111113, {5, 30, 11}}, + {86.15384615384616, {4, 27, 12}}, + {86.20689655172414, {1, 24, 28}}, + {86.22222222222223, {8, 96, 24}}, + {86.25, {9, 68, 15}}, + {86.27450980392156, {8, 65, 16}}, + {86.27450980392157, {2, 21, 16}}, + {86.29032258064517, {7, 106, 30}}, + {86.3157894736842, {4, 40, 18}}, + {86.32478632478632, {8, 100, 25}}, + {86.36363636363636, {3, 18, 10}}, + {86.36363636363637, {5, 56, 21}}, + {86.4, {4, 53, 24}}, + {86.41975308641975, {8, 34, 8}}, + {86.41975308641976, {2, 34, 26}}, + {86.42857142857143, {9, 120, 27}}, + {86.45161290322581, {4, 66, 30}}, + {86.45833333333333, {7, 82, 23}}, + {86.45833333333334, {5, 82, 31}}, + {86.5079365079365, {8, 108, 27}}, + {86.53846153846153, {7, 44, 12}}, + {86.54970760233918, {8, 73, 18}}, + {86.59003831417624, {8, 112, 28}}, + {86.60714285714286, {7, 96, 27}}, + {86.63594470046083, {6, 93, 30}}, + {86.66666666666666, {8, 38, 9}}, + {86.66666666666667, {9, 38, 8}}, + {86.66666666666669, {5, 64, 24}}, + {86.69950738916256, {6, 87, 28}}, + {86.71875, {7, 110, 31}}, + {86.73469387755104, {6, 84, 27}}, + {86.73835125448028, {8, 120, 30}}, + {86.76470588235294, {7, 58, 16}}, + {86.77248677248677, {8, 81, 20}}, + {86.77248677248679, {6, 81, 26}}, + {86.80555555555556, {8, 124, 31}}, + {86.81318681318682, {6, 78, 25}}, + {86.84210526315789, {3, 32, 18}}, + {86.85714285714286, {6, 75, 24}}, + {86.86868686868686, {8, 42, 10}}, + {86.875, {9, 138, 31}}, + {86.89655172413794, {4, 62, 28}}, + {86.9047619047619, {7, 72, 20}}, + {86.90476190476191, {6, 72, 23}}, + {86.92307692307692, {9, 112, 25}}, + {86.95652173913044, {0, 9, 22}}, + {86.95652173913045, {2, 29, 22}}, + {87.0, {9, 86, 19}}, + {87.01298701298703, {6, 66, 21}}, + {87.03703703703702, {8, 46, 11}}, + {87.03703703703704, {5, 46, 17}}, + {87.05882352941177, {4, 36, 16}}, + {87.06896551724138, {7, 100, 28}}, + {87.0748299319728, {6, 63, 20}}, + {87.09677419354838, {1, 26, 30}}, + {87.11111111111111, {8, 97, 24}}, + {87.14285714285714, {9, 60, 13}}, + {87.17948717948717, {8, 50, 12}}, + {87.1794871794872, {2, 16, 12}}, + {87.2, {9, 108, 24}}, + {87.21804511278197, {6, 57, 18}}, + {87.24279835390946, {8, 105, 26}}, + {87.27272727272727, {4, 23, 10}}, + {87.3015873015873, {8, 54, 13}}, + {87.33333333333333, {9, 130, 29}}, + {87.35632183908045, {8, 113, 28}}, + {87.35632183908046, {2, 37, 28}}, + {87.36842105263158, {9, 82, 18}}, + {87.39495798319328, {6, 51, 16}}, + {87.4074074074074, {8, 58, 14}}, + {87.45519713261648, {8, 121, 30}}, + {87.5, {1, 6, 7}}, + {87.55760368663594, {6, 94, 30}}, + {87.58169934640523, {8, 66, 16}}, + {87.58620689655173, {9, 126, 28}}, + {87.61904761904762, {4, 45, 20}}, + {87.61904761904763, {6, 45, 14}}, + {87.65432098765433, {8, 70, 17}}, + {87.68472906403942, {6, 88, 28}}, + {87.6923076923077, {9, 56, 12}}, + {87.71929824561403, {8, 74, 18}}, + {87.71929824561404, {2, 24, 18}}, + {87.74193548387096, {4, 67, 30}}, + {87.75510204081634, {6, 42, 13}}, + {87.77777777777777, {9, 78, 17}}, + {87.77777777777779, {5, 78, 29}}, + {87.82608695652173, {9, 100, 22}}, + {87.83068783068782, {8, 82, 20}}, + {87.83068783068784, {6, 82, 26}}, + {87.85714285714286, {9, 122, 27}}, + {87.87878787878788, {8, 86, 21}}, + {87.87878787878789, {5, 28, 10}}, + {87.90322580645162, {7, 108, 30}}, + {87.91208791208791, {6, 39, 12}}, + {87.92270531400966, {8, 90, 22}}, + {87.93103448275862, {3, 50, 28}}, + {87.96296296296295, {8, 94, 23}}, + {87.96296296296296, {7, 94, 26}}, + {88.0, {4, 21, 9}}, + {88.03418803418802, {8, 102, 25}}, + {88.04347826086956, {7, 80, 22}}, + {88.06584362139918, {8, 106, 26}}, + {88.09523809523809, {6, 36, 11}}, + {88.0952380952381, {5, 36, 13}}, + {88.12260536398468, {8, 114, 28}}, + {88.125, {9, 140, 31}}, + {88.14814814814814, {8, 118, 29}}, + {88.14814814814815, {9, 118, 26}}, + {88.15789473684211, {7, 66, 18}}, + {88.17204301075267, {8, 122, 30}}, + {88.17204301075269, {2, 40, 30}}, + {88.18181818181819, {9, 96, 21}}, + {88.19444444444444, {8, 126, 31}}, + {88.19875776397517, {6, 70, 22}}, + {88.23529411764706, {1, 14, 16}}, + {88.27586206896552, {4, 63, 28}}, + {88.28125, {7, 112, 31}}, + {88.31168831168831, {6, 33, 10}}, + {88.33333333333333, {9, 52, 11}}, + {88.33333333333334, {5, 52, 19}}, + {88.38709677419355, {9, 136, 30}}, + {88.39285714285714, {7, 98, 27}}, + {88.39285714285715, {6, 98, 31}}, + {88.40579710144928, {5, 60, 22}}, + {88.42105263157895, {4, 41, 18}}, + {88.43537414965988, {6, 64, 20}}, + {88.46153846153847, {3, 22, 12}}, + {88.47926267281107, {6, 95, 30}}, + {88.50574712643679, {5, 76, 28}}, + {88.54166666666667, {7, 84, 23}}, + {88.57142857142857, {9, 30, 6}}, + {88.57142857142858, {6, 30, 9}}, + {88.63636363636364, {7, 38, 10}}, + {88.66666666666667, {9, 132, 29}}, + {88.66995073891626, {6, 89, 28}}, + {88.69565217391305, {4, 50, 22}}, + {88.70967741935483, {3, 54, 30}}, + {88.7218045112782, {6, 58, 18}}, + {88.75, {9, 70, 15}}, + {88.77551020408164, {6, 86, 27}}, + {88.79310344827586, {7, 102, 28}}, + {88.8, {9, 110, 24}}, + {88.88888888888887, {8, 47, 11}}, + {88.88888888888889, {8, 27, 6}}, + {88.8888888888889, {2, 15, 11}}, + {88.96551724137932, {9, 128, 28}}, + {89.0, {9, 88, 19}}, + {89.01098901098901, {6, 80, 25}}, + {89.03225806451613, {4, 68, 30}}, + {89.0625, {7, 56, 15}}, + {89.07563025210085, {6, 52, 16}}, + {89.0909090909091, {9, 48, 10}}, + {89.1304347826087, {3, 40, 22}}, + {89.14285714285715, {6, 77, 24}}, + {89.16666666666667, {9, 106, 23}}, + {89.23076923076923, {4, 28, 12}}, + {89.247311827957, {5, 82, 30}}, + {89.28571428571429, {7, 24, 6}}, + {89.33333333333333, {9, 66, 14}}, + {89.33333333333334, {5, 66, 24}}, + {89.375, {9, 142, 31}}, + {89.39393939393939, {5, 58, 21}}, + {89.40092165898618, {6, 96, 30}}, + {89.41176470588235, {4, 37, 16}}, + {89.42307692307692, {7, 92, 25}}, + {89.44099378881988, {6, 71, 22}}, + {89.47368421052632, {1, 16, 18}}, + {89.47368421052633, {5, 50, 18}}, + {89.51612903225806, {7, 110, 30}}, + {89.52380952380952, {4, 46, 20}}, + {89.52380952380953, {6, 46, 14}}, + {89.56521739130434, {9, 102, 22}}, + {89.58333333333333, {7, 42, 11}}, + {89.58333333333334, {5, 42, 15}}, + {89.6, {4, 55, 24}}, + {89.6057347670251, {8, 124, 30}}, + {89.61038961038962, {6, 68, 21}}, + {89.62962962962962, {8, 120, 29}}, + {89.62962962962963, {9, 120, 26}}, + {89.65517241379311, {0, 12, 28}}, + {89.6774193548387, {9, 138, 30}}, + {89.68253968253967, {8, 112, 27}}, + {89.70588235294117, {7, 60, 16}}, + {89.7119341563786, {8, 108, 26}}, + {89.74358974358974, {8, 104, 25}}, + {89.74358974358975, {5, 34, 12}}, + {89.77272727272727, {7, 78, 21}}, + {89.77777777777777, {8, 100, 24}}, + {89.79591836734694, {6, 21, 6}}, + {89.81481481481481, {7, 96, 26}}, + {89.81481481481482, {8, 96, 23}}, + {89.84375, {7, 114, 31}}, + {89.85507246376811, {8, 92, 22}}, + {89.85507246376812, {2, 30, 22}}, + {89.8989898989899, {8, 88, 21}}, + {89.94708994708995, {8, 84, 20}}, + {89.94708994708996, {6, 84, 26}}, + {90.0, {4, 17, 7}}, + {90.00000000000001, {5, 26, 9}}, + {90.05847953216374, {8, 76, 18}}, + {90.10989010989012, {6, 40, 12}}, + {90.12345679012346, {8, 72, 17}}, + {90.17857142857143, {7, 100, 27}}, + {90.19607843137254, {8, 68, 16}}, + {90.19607843137256, {2, 22, 16}}, + {90.21739130434783, {7, 82, 22}}, + {90.22556390977445, {6, 59, 18}}, + {90.27777777777777, {8, 64, 15}}, + {90.27777777777779, {5, 64, 23}}, + {90.28571428571429, {6, 78, 24}}, + {90.3225806451613, {0, 13, 30}}, + {90.34482758620689, {9, 130, 28}}, + {90.37037037037037, {8, 60, 14}}, + {90.38461538461539, {7, 46, 12}}, + {90.4, {9, 112, 24}}, + {90.42145593869732, {8, 117, 28}}, + {90.43478260869566, {4, 51, 22}}, + {90.47619047619047, {8, 56, 13}}, + {90.47619047619048, {5, 18, 6}}, + {90.51724137931035, {7, 104, 28}}, + {90.52631578947368, {4, 42, 18}}, + {90.53497942386831, {8, 109, 26}}, + {90.58823529411765, {9, 76, 16}}, + {90.5982905982906, {8, 52, 12}}, + {90.625, {7, 28, 7}}, + {90.64039408866996, {6, 91, 28}}, + {90.66666666666666, {8, 101, 24}}, + {90.66666666666667, {4, 33, 14}}, + {90.66666666666669, {2, 33, 24}}, + {90.6832298136646, {6, 72, 22}}, + {90.71428571428571, {9, 126, 27}}, + {90.74074074074075, {8, 48, 11}}, + {90.75630252100841, {6, 53, 16}}, + {90.76923076923077, {9, 58, 12}}, + {90.78947368421052, {7, 68, 18}}, + {90.80459770114943, {5, 78, 28}}, + {90.81632653061226, {6, 88, 27}}, + {90.82125603864733, {8, 93, 22}}, + {90.83333333333333, {9, 108, 23}}, + {90.9090909090909, {0, 4, 10}}, + {90.90909090909092, {2, 14, 10}}, + {90.96774193548387, {9, 140, 30}}, + {90.97222222222221, {8, 130, 31}}, + {91.0, {9, 90, 19}}, + {91.005291005291, {8, 85, 20}}, + {91.00529100529101, {6, 85, 26}}, + {91.02564102564104, {5, 70, 25}}, + {91.03448275862068, {4, 65, 28}}, + {91.0394265232975, {8, 126, 30}}, + {91.07142857142857, {7, 50, 13}}, + {91.1111111111111, {8, 122, 29}}, + {91.11111111111111, {9, 40, 8}}, + {91.12903225806451, {7, 112, 30}}, + {91.15646258503402, {6, 66, 20}}, + {91.17647058823529, {3, 30, 16}}, + {91.18773946360153, {8, 118, 28}}, + {91.2, {4, 56, 24}}, + {91.20879120879121, {6, 82, 25}}, + {91.22807017543859, {8, 77, 18}}, + {91.2280701754386, {2, 25, 18}}, + {91.24423963133641, {6, 98, 30}}, + {91.25, {9, 72, 15}}, + {91.26984126984128, {8, 114, 27}}, + {91.30434782608695, {1, 20, 22}}, + {91.33333333333333, {9, 136, 29}}, + {91.34615384615384, {7, 94, 25}}, + {91.35802469135803, {8, 36, 8}}, + {91.35802469135804, {2, 36, 26}}, + {91.37931034482759, {3, 52, 28}}, + {91.3978494623656, {5, 84, 30}}, + {91.40625, {7, 116, 31}}, + {91.42857142857143, {4, 15, 6}}, + {91.45299145299145, {8, 106, 25}}, + {91.5032679738562, {8, 69, 16}}, + {91.53846153846153, {9, 118, 25}}, + {91.55555555555554, {8, 102, 24}}, + {91.57894736842105, {9, 86, 18}}, + {91.61290322580645, {4, 70, 30}}, + {91.6256157635468, {6, 92, 28}}, + {91.66666666666666, {8, 32, 7}}, + {91.66666666666667, {2, 10, 7}}, + {91.72413793103448, {9, 132, 28}}, + {91.72932330827068, {6, 60, 18}}, + {91.75627240143369, {8, 127, 30}}, + {91.76470588235294, {4, 38, 16}}, + {91.78743961352656, {8, 94, 22}}, + {91.81818181818181, {9, 100, 21}}, + {91.83673469387756, {6, 44, 13}}, + {91.85185185185185, {4, 61, 26}}, + {91.85185185185186, {8, 61, 14}}, + {91.875, {9, 146, 31}}, + {91.91919191919192, {8, 90, 21}}, + {91.92546583850931, {6, 73, 22}}, + {91.93548387096774, {3, 56, 30}}, + {91.95402298850574, {8, 119, 28}}, + {91.95402298850576, {2, 39, 28}}, + {91.96428571428571, {7, 102, 27}}, + {91.96428571428572, {6, 102, 31}}, + {92.0, {4, 22, 9}}, + {92.04545454545455, {7, 80, 21}}, + {92.06349206349206, {8, 28, 6}}, + {92.06349206349208, {6, 28, 8}}, + {92.10526315789474, {3, 34, 18}}, + {92.14285714285714, {9, 128, 27}}, + {92.15686274509804, {5, 46, 16}}, + {92.16589861751153, {6, 99, 30}}, + {92.17391304347827, {4, 52, 22}}, + {92.18106995884773, {8, 111, 26}}, + {92.1875, {7, 58, 15}}, + {92.20779220779221, {6, 70, 21}}, + {92.22222222222221, {8, 82, 19}}, + {92.22222222222223, {9, 82, 17}}, + {92.24137931034483, {7, 106, 28}}, + {92.25806451612904, {9, 142, 30}}, + {92.3076923076923, {0, 5, 12}}, + {92.36111111111111, {8, 132, 31}}, + {92.38095238095238, {9, 96, 20}}, + {92.3913043478261, {7, 84, 22}}, + {92.39766081871345, {8, 78, 18}}, + {92.41379310344827, {4, 66, 28}}, + {92.42424242424244, {5, 60, 21}}, + {92.43697478991598, {6, 54, 16}}, + {92.44444444444443, {8, 103, 24}}, + {92.47311827956989, {8, 128, 30}}, + {92.4731182795699, {2, 42, 30}}, + {92.5, {9, 36, 7}}, + {92.51700680272108, {6, 67, 20}}, + {92.57142857142857, {6, 80, 24}}, + {92.59259259259258, {8, 74, 17}}, + {92.5925925925926, {5, 24, 8}}, + {92.61083743842364, {6, 93, 28}}, + {92.63157894736842, {4, 43, 18}}, + {92.6470588235294, {7, 62, 16}}, + {92.66666666666667, {9, 138, 29}}, + {92.70833333333333, {7, 88, 23}}, + {92.70833333333334, {5, 88, 31}}, + {92.72030651340995, {8, 120, 28}}, + {92.72727272727273, {9, 50, 10}}, + {92.74193548387096, {7, 114, 30}}, + {92.75362318840578, {8, 95, 22}}, + {92.7536231884058, {2, 31, 22}}, + {92.8, {4, 57, 24}}, + {92.81045751633987, {8, 70, 16}}, + {92.85714285714286, {3, 12, 6}}, + {92.85714285714288, {6, 38, 11}}, + {92.90322580645162, {4, 71, 30}}, + {92.92929292929293, {8, 45, 10}}, + {92.94117647058823, {9, 78, 16}}, + {92.96875, {7, 118, 31}}, + {92.98245614035088, {5, 52, 18}}, + {93.0, {9, 92, 19}}, + {93.00411522633743, {8, 112, 26}}, + {93.04347826086956, {9, 106, 22}}, + {93.05555555555556, {8, 66, 15}}, + {93.07692307692308, {9, 120, 25}}, + {93.08755760368663, {6, 100, 30}}, + {93.10344827586206, {1, 26, 28}}, + {93.12169312169311, {8, 87, 20}}, + {93.125, {9, 148, 31}}, + {93.16239316239316, {8, 108, 25}}, + {93.16770186335405, {6, 74, 22}}, + {93.18181818181819, {7, 40, 10}}, + {93.18996415770609, {8, 129, 30}}, + {93.23308270676692, {6, 61, 18}}, + {93.26923076923077, {7, 96, 25}}, + {93.33333333333331, {8, 104, 24}}, + {93.33333333333333, {4, 20, 8}}, + {93.33333333333334, {2, 13, 9}}, + {93.40659340659342, {6, 84, 25}}, + {93.42105263157895, {7, 70, 18}}, + {93.47826086956522, {3, 42, 22}}, + {93.48659003831416, {8, 121, 28}}, + {93.50649350649351, {6, 35, 10}}, + {93.51851851851852, {8, 100, 23}}, + {93.54838709677419, {1, 28, 30}}, + {93.5672514619883, {8, 79, 18}}, + {93.57142857142857, {9, 130, 27}}, + {93.58974358974359, {5, 72, 25}}, + {93.59605911330048, {6, 94, 28}}, + {93.6, {9, 116, 24}}, + {93.63636363636364, {9, 102, 21}}, + {93.65079365079364, {8, 58, 13}}, + {93.65079365079366, {6, 58, 17}}, + {93.6842105263158, {9, 88, 18}}, + {93.71428571428572, {6, 81, 24}}, + {93.71980676328504, {8, 96, 22}}, + {93.75, {3, 14, 7}}, + {93.79310344827586, {4, 67, 28}}, + {93.82716049382715, {8, 113, 26}}, + {93.82716049382717, {8, 37, 8}}, + {93.84615384615384, {9, 60, 12}}, + {93.87755102040816, {6, 68, 20}}, + {93.87755102040818, {6, 22, 6}}, + {93.90681003584228, {8, 130, 30}}, + {93.91304347826087, {4, 53, 22}}, + {93.93939393939394, {8, 92, 21}}, + {93.93939393939395, {5, 30, 10}}, + {93.96551724137932, {7, 108, 28}}, + {94.0, {9, 46, 9}}, + {94.00921658986175, {6, 101, 30}}, + {94.01709401709401, {8, 54, 12}}, + {94.04761904761905, {7, 78, 20}}, + {94.07407407407408, {9, 126, 26}}, + {94.11764705882354, {0, 7, 16}}, + {94.16666666666667, {9, 112, 23}}, + {94.17989417989418, {8, 88, 20}}, + {94.17989417989419, {6, 88, 26}}, + {94.19354838709677, {4, 72, 30}}, + {94.20289855072465, {5, 64, 22}}, + {94.22222222222223, {8, 105, 24}}, + {94.23076923076923, {7, 48, 12}}, + {94.25287356321839, {8, 122, 28}}, + {94.2528735632184, {2, 40, 28}}, + {94.28571428571429, {9, 32, 6}}, + {94.31818181818181, {7, 82, 21}}, + {94.35483870967742, {7, 116, 30}}, + {94.4, {4, 58, 24}}, + {94.40993788819877, {6, 75, 22}}, + {94.44444444444444, {8, 33, 7}}, + {94.44444444444446, {2, 16, 11}}, + {94.48275862068965, {9, 136, 28}}, + {94.50549450549451, {6, 42, 12}}, + {94.54545454545455, {4, 25, 10}}, + {94.56521739130434, {7, 86, 22}}, + {94.58128078817735, {6, 95, 28}}, + {94.61538461538461, {9, 122, 25}}, + {94.62365591397848, {8, 131, 30}}, + {94.6236559139785, {2, 43, 30}}, + {94.64285714285714, {7, 52, 13}}, + {94.64285714285715, {6, 52, 15}}, + {94.65020576131688, {8, 114, 26}}, + {94.66666666666667, {9, 70, 14}}, + {94.66666666666669, {5, 70, 24}}, + {94.68599033816426, {8, 97, 22}}, + {94.73684210526316, {0, 8, 18}}, + {94.78260869565217, {9, 108, 22}}, + {94.79166666666667, {7, 90, 23}}, + {94.8051948051948, {6, 72, 21}}, + {94.81481481481481, {8, 63, 14}}, + {94.82758620689656, {3, 54, 28}}, + {94.83870967741936, {9, 146, 30}}, + {94.85714285714286, {6, 82, 24}}, + {94.87179487179486, {8, 110, 25}}, + {94.87179487179489, {5, 36, 12}}, + {94.89795918367348, {6, 92, 27}}, + {94.93087557603687, {6, 102, 30}}, + {94.94949494949493, {8, 46, 10}}, + {95.0, {4, 18, 7}}, + {95.00000000000001, {5, 56, 19}}, + {95.01915708812261, {8, 123, 28}}, + {95.06172839506172, {8, 76, 17}}, + {95.06172839506173, {5, 76, 26}}, + {95.11111111111111, {8, 106, 24}}, + {95.16129032258064, {3, 58, 30}}, + {95.17241379310344, {4, 68, 28}}, + {95.1923076923077, {7, 98, 25}}, + {95.2, {9, 118, 24}}, + {95.23809523809523, {8, 29, 6}}, + {95.23809523809524, {6, 29, 8}}, + {95.23809523809526, {2, 9, 6}}, + {95.29411764705883, {9, 80, 16}}, + {95.3125, {7, 60, 15}}, + {95.33333333333333, {9, 142, 29}}, + {95.3405017921147, {8, 132, 30}}, + {95.37037037037037, {8, 102, 23}}, + {95.38461538461539, {4, 30, 12}}, + {95.40229885057472, {5, 82, 28}}, + {95.42483660130719, {8, 72, 16}}, + {95.45454545454545, {3, 20, 10}}, + {95.47325102880659, {8, 115, 26}}, + {95.48387096774194, {4, 73, 30}}, + {95.53571428571429, {7, 106, 27}}, + {95.55555555555556, {9, 42, 8}}, + {95.55555555555557, {5, 42, 14}}, + {95.56650246305419, {6, 96, 28}}, + {95.58823529411765, {7, 64, 16}}, + {95.6043956043956, {6, 86, 25}}, + {95.65217391304348, {0, 10, 22}}, + {95.6896551724138, {7, 110, 28}}, + {95.6989247311828, {5, 88, 30}}, + {95.71428571428571, {9, 66, 13}}, + {95.71428571428572, {6, 66, 19}}, + {95.72649572649571, {8, 55, 12}}, + {95.78544061302682, {8, 124, 28}}, + {95.78947368421052, {9, 90, 18}}, + {95.7983193277311, {6, 56, 16}}, + {95.83333333333333, {3, 22, 11}}, + {95.83333333333334, {5, 22, 7}}, + {95.85253456221199, {6, 103, 30}}, + {95.86206896551724, {9, 138, 28}}, + {95.90643274853801, {8, 81, 18}}, + {95.91836734693878, {6, 46, 13}}, + {95.95959595959594, {8, 94, 21}}, + {95.96774193548387, {7, 118, 30}}, + {96.0, {4, 23, 9}}, + {96.03174603174602, {8, 120, 27}}, + {96.05263157894737, {7, 72, 18}}, + {96.05734767025089, {8, 133, 30}}, + {96.07843137254903, {5, 48, 16}}, + {96.1038961038961, {6, 36, 10}}, + {96.12903225806451, {9, 148, 30}}, + {96.15384615384616, {3, 24, 12}}, + {96.19047619047619, {9, 100, 20}}, + {96.24060150375941, {6, 63, 18}}, + {96.25, {9, 76, 15}}, + {96.29629629629629, {8, 38, 8}}, + {96.2962962962963, {2, 12, 8}}, + {96.36363636363636, {9, 52, 10}}, + {96.42857142857143, {7, 26, 6}}, + {96.47058823529412, {4, 40, 16}}, + {96.49122807017545, {5, 54, 18}}, + {96.52173913043478, {9, 110, 22}}, + {96.55172413793103, {0, 13, 28}}, + {96.58119658119656, {8, 112, 25}}, + {96.5909090909091, {7, 84, 21}}, + {96.59863945578232, {6, 70, 20}}, + {96.61835748792271, {8, 99, 22}}, + {96.66666666666666, {8, 86, 19}}, + {96.66666666666667, {5, 28, 9}}, + {96.7032967032967, {6, 43, 12}}, + {96.73202614379085, {8, 73, 16}}, + {96.73913043478261, {7, 88, 22}}, + {96.7741935483871, {0, 14, 30}}, + {96.8, {9, 120, 24}}, + {96.82539682539682, {8, 60, 13}}, + {96.82539682539684, {5, 60, 20}}, + {96.84210526315789, {4, 45, 18}}, + {96.875, {7, 30, 7}}, + {96.88888888888889, {8, 108, 24}}, + {96.89440993788821, {6, 77, 22}}, + {96.92307692307692, {9, 62, 12}}, + {96.93877551020408, {6, 94, 27}}, + {96.96969696969695, {8, 47, 10}}, + {96.96969696969698, {2, 15, 10}}, + {97.0, {9, 96, 19}}, + {97.03703703703702, {8, 130, 29}}, + {97.03703703703704, {9, 130, 26}}, + {97.05882352941177, {3, 32, 16}}, + {97.07602339181285, {8, 82, 18}}, + {97.10144927536233, {5, 66, 22}}, + {97.11538461538461, {7, 100, 25}}, + {97.11934156378601, {8, 117, 26}}, + {97.14285714285714, {4, 16, 6}}, + {97.14285714285715, {6, 84, 24}}, + {97.22222222222221, {8, 34, 7}}, + {97.22222222222223, {7, 34, 8}}, + {97.24137931034483, {9, 140, 28}}, + {97.27272727272727, {9, 106, 21}}, + {97.31800766283524, {8, 126, 28}}, + {97.32142857142857, {7, 108, 27}}, + {97.33333333333333, {9, 72, 14}}, + {97.33333333333334, {5, 72, 24}}, + {97.35449735449735, {8, 91, 20}}, + {97.35449735449737, {6, 91, 26}}, + {97.36842105263158, {3, 36, 18}}, + {97.3913043478261, {4, 55, 22}}, + {97.40259740259741, {6, 74, 21}}, + {97.41379310344827, {7, 112, 28}}, + {97.43589743589743, {8, 56, 12}}, + {97.43589743589745, {2, 18, 12}}, + {97.47899159663866, {6, 57, 16}}, + {97.5, {9, 38, 7}}, + {97.53086419753086, {8, 78, 17}}, + {97.53086419753087, {5, 78, 26}}, + {97.53694581280789, {6, 98, 28}}, + {97.58454106280193, {8, 100, 22}}, + {97.6, {4, 60, 24}}, + {97.6190476190476, {8, 122, 27}}, + {97.61904761904762, {5, 40, 13}}, + {97.61904761904763, {6, 40, 11}}, + {97.6470588235294, {9, 82, 16}}, + {97.6923076923077, {9, 126, 25}}, + {97.70114942528735, {5, 84, 28}}, + {97.72727272727273, {7, 42, 10}}, + {97.74436090225565, {6, 64, 18}}, + {97.77777777777777, {4, 21, 8}}, + {97.77777777777779, {2, 21, 14}}, + {97.80219780219781, {6, 88, 25}}, + {97.82608695652173, {3, 44, 22}}, + {97.85714285714286, {9, 136, 27}}, + {97.89473684210526, {9, 92, 18}}, + {97.91666666666667, {7, 46, 11}}, + {97.93103448275862, {4, 70, 28}}, + {97.94238683127571, {8, 118, 26}}, + {97.9591836734694, {6, 23, 6}}, + {97.97979797979798, {8, 96, 21}}, + {98.0, {9, 48, 9}}, + {98.0392156862745, {8, 74, 16}}, + {98.03921568627452, {2, 24, 16}}, + {98.07692307692308, {7, 50, 12}}, + {98.08429118773947, {8, 127, 28}}, + {98.0952380952381, {9, 102, 20}}, + {98.13664596273293, {6, 78, 22}}, + {98.14814814814815, {8, 52, 11}}, + {98.18181818181819, {4, 26, 10}}, + {98.21428571428571, {7, 54, 13}}, + {98.21428571428572, {6, 54, 15}}, + {98.24561403508771, {8, 83, 18}}, + {98.24561403508773, {2, 27, 18}}, + {98.26086956521739, {9, 112, 22}}, + {98.27586206896552, {3, 56, 28}}, + {98.28571428571429, {6, 85, 24}}, + {98.2905982905983, {8, 114, 25}}, + {98.33333333333333, {9, 58, 11}}, + {98.33333333333334, {5, 58, 19}}, + {98.4, {9, 122, 24}}, + {98.4126984126984, {8, 92, 20}}, + {98.41269841269842, {8, 30, 6}}, + {98.41269841269843, {2, 30, 20}}, + {98.4375, {7, 62, 15}}, + {98.46153846153847, {4, 31, 12}}, + {98.4848484848485, {5, 64, 21}}, + {98.51851851851852, {9, 132, 26}}, + {98.52216748768474, {6, 99, 28}}, + {98.52941176470588, {7, 66, 16}}, + {98.55072463768116, {8, 101, 22}}, + {98.55072463768117, {2, 33, 22}}, + {98.57142857142857, {9, 68, 13}}, + {98.57142857142858, {6, 68, 19}}, + {98.61111111111111, {8, 70, 15}}, + {98.61111111111113, {5, 70, 23}}, + {98.62068965517241, {9, 142, 28}}, + {98.66666666666666, {8, 110, 24}}, + {98.66666666666667, {4, 36, 14}}, + {98.66666666666669, {2, 36, 24}}, + {98.6842105263158, {7, 74, 18}}, + {98.70129870129871, {6, 37, 10}}, + {98.71794871794873, {5, 76, 25}}, + {98.75, {9, 78, 15}}, + {98.76543209876543, {8, 39, 8}}, + {98.76543209876544, {2, 39, 26}}, + {98.80952380952381, {7, 82, 20}}, + {98.80952380952382, {5, 82, 27}}, + {98.82352941176471, {4, 41, 16}}, + {98.85057471264368, {8, 128, 28}}, + {98.85057471264369, {2, 42, 28}}, + {98.86363636363636, {7, 86, 21}}, + {98.88888888888889, {9, 88, 17}}, + {98.8888888888889, {5, 88, 29}}, + {98.9010989010989, {6, 44, 12}}, + {98.91304347826087, {7, 90, 22}}, + {98.94736842105263, {4, 46, 18}}, + {98.95833333333333, {7, 94, 23}}, + {98.9795918367347, {6, 96, 27}}, + {98.98989898989899, {8, 48, 10}}, + {99.0, {9, 98, 19}}, + {99.03846153846153, {7, 102, 25}}, + {99.04761904761905, {6, 51, 14}}, + {99.07407407407408, {8, 106, 23}}, + {99.0909090909091, {9, 108, 21}}, + {99.10714285714286, {7, 110, 27}}, + {99.1304347826087, {4, 56, 22}}, + {99.13793103448276, {7, 114, 28}}, + {99.14529914529915, {8, 57, 12}}, + {99.15966386554622, {6, 58, 16}}, + {99.16666666666667, {9, 118, 23}}, + {99.2, {4, 61, 24}}, + {99.2063492063492, {8, 124, 27}}, + {99.23076923076923, {9, 128, 25}}, + {99.24812030075188, {6, 65, 18}}, + {99.25925925925925, {4, 66, 26}}, + {99.25925925925927, {8, 66, 14}}, + {99.28571428571429, {9, 138, 27}}, + {99.3103448275862, {4, 71, 28}}, + {99.31972789115646, {6, 72, 20}}, + {99.33333333333333, {9, 148, 29}}, + {99.34640522875817, {8, 75, 16}}, + {99.37888198757764, {6, 79, 22}}, + {99.41520467836257, {8, 84, 18}}, + {99.42857142857143, {6, 86, 24}}, + {99.47089947089947, {8, 93, 20}}, + {99.50738916256158, {6, 100, 28}}, + {99.51690821256038, {8, 102, 22}}, + {99.55555555555554, {8, 111, 24}}, + {99.58847736625513, {8, 120, 26}}, + {99.61685823754789, {8, 129, 28}}, + {100.0, {0, 2, 5}}, + {100.00000000000001, {5, 26, 8}}, + {100.3831417624521, {8, 130, 28}}, + {100.41152263374485, {8, 121, 26}}, + {100.44444444444443, {8, 112, 24}}, + {100.4830917874396, {8, 103, 22}}, + {100.49261083743842, {6, 101, 28}}, + {100.52910052910052, {8, 94, 20}}, + {100.52910052910053, {6, 94, 26}}, + {100.57142857142857, {6, 87, 24}}, + {100.58479532163743, {8, 85, 18}}, + {100.62111801242236, {6, 80, 22}}, + {100.65359477124183, {8, 76, 16}}, + {100.68027210884354, {6, 73, 20}}, + {100.6896551724138, {4, 72, 28}}, + {100.71428571428571, {9, 140, 27}}, + {100.74074074074073, {8, 67, 14}}, + {100.74074074074075, {4, 67, 26}}, + {100.75187969924814, {6, 66, 18}}, + {100.76923076923077, {9, 130, 25}}, + {100.7936507936508, {8, 126, 27}}, + {100.8, {4, 62, 24}}, + {100.83333333333333, {9, 120, 23}}, + {100.84033613445379, {6, 59, 16}}, + {100.85470085470085, {8, 58, 12}}, + {100.86206896551724, {7, 116, 28}}, + {100.8695652173913, {4, 57, 22}}, + {100.89285714285714, {7, 112, 27}}, + {100.9090909090909, {9, 110, 21}}, + {100.92592592592592, {8, 108, 23}}, + {100.95238095238095, {4, 52, 20}}, + {100.95238095238096, {6, 52, 14}}, + {100.96153846153847, {7, 104, 25}}, + {101.0, {9, 100, 19}}, + {101.01010101010101, {8, 49, 10}}, + {101.02040816326532, {6, 98, 27}}, + {101.04166666666667, {7, 96, 23}}, + {101.05263157894737, {4, 47, 18}}, + {101.08695652173913, {7, 92, 22}}, + {101.09890109890111, {6, 45, 12}}, + {101.11111111111111, {9, 90, 17}}, + {101.13636363636364, {7, 88, 21}}, + {101.14942528735631, {8, 131, 28}}, + {101.14942528735632, {2, 43, 28}}, + {101.17647058823529, {4, 42, 16}}, + {101.19047619047619, {7, 84, 20}}, + {101.1904761904762, {6, 84, 23}}, + {101.23456790123456, {8, 122, 26}}, + {101.23456790123457, {8, 40, 8}}, + {101.25, {9, 80, 15}}, + {101.28205128205128, {5, 78, 25}}, + {101.29870129870132, {6, 38, 10}}, + {101.3157894736842, {7, 76, 18}}, + {101.33333333333331, {8, 113, 24}}, + {101.33333333333333, {4, 37, 14}}, + {101.33333333333334, {2, 37, 24}}, + {101.37931034482759, {9, 146, 28}}, + {101.38888888888889, {8, 72, 15}}, + {101.3888888888889, {5, 72, 23}}, + {101.42857142857143, {9, 70, 13}}, + {101.44927536231883, {8, 104, 22}}, + {101.44927536231884, {2, 34, 22}}, + {101.47058823529412, {7, 68, 16}}, + {101.47783251231527, {6, 102, 28}}, + {101.48148148148148, {9, 136, 26}}, + {101.51515151515152, {5, 66, 21}}, + {101.53846153846153, {4, 32, 12}}, + {101.5625, {7, 64, 15}}, + {101.58730158730157, {8, 95, 20}}, + {101.58730158730158, {8, 31, 6}}, + {101.5873015873016, {6, 31, 8}}, + {101.6, {9, 126, 24}}, + {101.66666666666667, {9, 60, 11}}, + {101.7094017094017, {8, 118, 25}}, + {101.71428571428572, {6, 88, 24}}, + {101.72413793103448, {3, 58, 28}}, + {101.73913043478261, {9, 116, 22}}, + {101.75438596491227, {8, 86, 18}}, + {101.75438596491229, {2, 28, 18}}, + {101.78571428571429, {7, 56, 13}}, + {101.81818181818181, {4, 27, 10}}, + {101.85185185185185, {8, 54, 11}}, + {101.85185185185186, {5, 54, 17}}, + {101.86335403726709, {6, 81, 22}}, + {101.9047619047619, {9, 106, 20}}, + {101.91570881226053, {8, 132, 28}}, + {101.92307692307692, {7, 52, 12}}, + {101.96078431372548, {8, 77, 16}}, + {101.9607843137255, {2, 25, 16}}, + {102.0, {9, 50, 9}}, + {102.02020202020202, {8, 100, 21}}, + {102.04081632653062, {6, 24, 6}}, + {102.04081632653063, {6, 74, 20}}, + {102.05761316872429, {8, 123, 26}}, + {102.06896551724138, {4, 73, 28}}, + {102.08333333333333, {7, 48, 11}}, + {102.08333333333334, {5, 48, 15}}, + {102.10526315789474, {9, 96, 18}}, + {102.14285714285714, {9, 142, 27}}, + {102.17391304347827, {3, 46, 22}}, + {102.1978021978022, {6, 92, 25}}, + {102.22222222222221, {8, 45, 9}}, + {102.22222222222223, {4, 22, 8}}, + {102.25563909774436, {6, 67, 18}}, + {102.27272727272727, {7, 44, 10}}, + {102.29885057471266, {5, 88, 28}}, + {102.3076923076923, {9, 132, 25}}, + {102.3529411764706, {9, 86, 16}}, + {102.38095238095238, {3, 42, 20}}, + {102.3809523809524, {6, 42, 11}}, + {102.4, {4, 63, 24}}, + {102.41545893719807, {8, 105, 22}}, + {102.46305418719213, {6, 103, 28}}, + {102.46913580246913, {8, 82, 17}}, + {102.46913580246915, {5, 82, 26}}, + {102.5, {9, 40, 7}}, + {102.52100840336135, {6, 60, 16}}, + {102.56410256410255, {8, 59, 12}}, + {102.56410256410257, {2, 19, 12}}, + {102.58620689655173, {7, 118, 28}}, + {102.5974025974026, {6, 78, 21}}, + {102.6086956521739, {4, 58, 22}}, + {102.63157894736842, {3, 38, 18}}, + {102.64550264550265, {8, 96, 20}}, + {102.66666666666667, {9, 76, 14}}, + {102.66666666666669, {5, 76, 24}}, + {102.67857142857143, {7, 114, 27}}, + {102.68199233716476, {8, 133, 28}}, + {102.72727272727273, {9, 112, 21}}, + {102.75862068965517, {9, 148, 28}}, + {102.77777777777777, {8, 36, 7}}, + {102.77777777777779, {5, 36, 11}}, + {102.85714285714286, {4, 17, 6}}, + {102.88065843621399, {8, 124, 26}}, + {102.88461538461539, {7, 106, 25}}, + {102.8985507246377, {5, 70, 22}}, + {102.92397660818713, {8, 87, 18}}, + {102.94117647058823, {3, 34, 16}}, + {102.96296296296296, {9, 138, 26}}, + {103.0, {9, 102, 19}}, + {103.03030303030302, {8, 50, 10}}, + {103.03030303030305, {2, 16, 10}}, + {103.06122448979592, {6, 100, 27}}, + {103.07692307692308, {9, 66, 12}}, + {103.1055900621118, {6, 82, 22}}, + {103.11111111111111, {8, 115, 24}}, + {103.125, {7, 32, 7}}, + {103.15789473684211, {4, 48, 18}}, + {103.17460317460316, {8, 64, 13}}, + {103.17460317460319, {6, 64, 17}}, + {103.2, {9, 128, 24}}, + {103.26086956521739, {7, 94, 22}}, + {103.26797385620914, {8, 78, 16}}, + {103.2967032967033, {6, 46, 12}}, + {103.33333333333333, {9, 30, 5}}, + {103.33333333333334, {5, 30, 9}}, + {103.38164251207729, {8, 106, 22}}, + {103.4013605442177, {6, 75, 20}}, + {103.4090909090909, {7, 90, 21}}, + {103.4188034188034, {8, 120, 25}}, + {103.44827586206897, {0, 14, 28}}, + {103.47826086956522, {9, 118, 22}}, + {103.50877192982456, {5, 58, 18}}, + {103.52941176470588, {4, 43, 16}}, + {103.57142857142857, {7, 28, 6}}, + {103.57142857142858, {6, 28, 7}}, + {103.63636363636364, {9, 56, 10}}, + {103.7037037037037, {8, 27, 5}}, + {103.70370370370371, {2, 13, 8}}, + {103.75, {9, 82, 15}}, + {103.7593984962406, {6, 68, 18}}, + {103.80952380952381, {9, 108, 20}}, + {103.84615384615384, {3, 26, 12}}, + {103.8961038961039, {6, 39, 10}}, + {103.92156862745098, {5, 52, 16}}, + {103.94736842105263, {7, 78, 18}}, + {103.96825396825396, {8, 130, 27}}, + {104.0, {4, 25, 9}}, + {104.04040404040403, {8, 102, 21}}, + {104.08163265306122, {6, 50, 13}}, + {104.09356725146198, {8, 88, 18}}, + {104.16666666666666, {8, 74, 15}}, + {104.16666666666667, {7, 24, 5}}, + {104.20168067226892, {6, 61, 16}}, + {104.21052631578948, {9, 98, 18}}, + {104.27350427350426, {8, 60, 12}}, + {104.28571428571429, {9, 72, 13}}, + {104.34782608695652, {0, 11, 22}}, + {104.3956043956044, {6, 94, 25}}, + {104.41176470588235, {7, 70, 16}}, + {104.44444444444443, {8, 46, 9}}, + {104.44444444444444, {9, 46, 8}}, + {104.46428571428571, {7, 116, 27}}, + {104.52674897119341, {8, 126, 26}}, + {104.54545454545455, {3, 22, 10}}, + {104.57516339869281, {8, 79, 16}}, + {104.61538461538461, {4, 33, 12}}, + {104.62962962962962, {8, 112, 23}}, + {104.62962962962963, {7, 112, 26}}, + {104.6875, {7, 66, 15}}, + {104.70588235294117, {9, 88, 16}}, + {104.76190476190474, {8, 32, 6}}, + {104.76190476190476, {6, 21, 5}}, + {104.76190476190477, {2, 10, 6}}, + {104.8, {9, 130, 24}}, + {104.8076923076923, {7, 108, 25}}, + {104.88888888888889, {8, 117, 24}}, + {104.93827160493828, {8, 84, 17}}, + {105.0, {4, 20, 7}}, + {105.05050505050504, {8, 51, 10}}, + {105.10204081632654, {6, 102, 27}}, + {105.12820512820511, {8, 122, 25}}, + {105.12820512820514, {5, 40, 12}}, + {105.14285714285715, {6, 91, 24}}, + {105.18518518518519, {8, 70, 14}}, + {105.1948051948052, {6, 80, 21}}, + {105.20833333333333, {7, 100, 23}}, + {105.21739130434783, {9, 120, 22}}, + {105.26315789473684, {0, 9, 18}}, + {105.26315789473685, {2, 29, 18}}, + {105.31400966183574, {8, 108, 22}}, + {105.33333333333333, {9, 78, 14}}, + {105.33333333333334, {5, 78, 24}}, + {105.34979423868312, {8, 127, 26}}, + {105.35714285714286, {7, 58, 13}}, + {105.38461538461539, {9, 136, 25}}, + {105.43478260869566, {7, 96, 22}}, + {105.45454545454545, {4, 28, 10}}, + {105.4945054945055, {6, 47, 12}}, + {105.55555555555554, {8, 56, 11}}, + {105.55555555555556, {5, 18, 5}}, + {105.55555555555557, {5, 56, 17}}, + {105.59006211180126, {6, 84, 22}}, + {105.6, {4, 65, 24}}, + {105.68181818181819, {7, 92, 21}}, + {105.71428571428571, {9, 36, 6}}, + {105.76923076923077, {7, 54, 12}}, + {105.77777777777777, {8, 118, 24}}, + {105.79710144927537, {5, 72, 22}}, + {105.82010582010582, {8, 99, 20}}, + {105.83333333333333, {9, 126, 23}}, + {105.88235294117646, {0, 8, 16}}, + {105.88235294117648, {2, 26, 16}}, + {105.92592592592592, {9, 142, 26}}, + {105.95238095238095, {7, 88, 20}}, + {105.95238095238096, {6, 88, 23}}, + {105.98290598290599, {8, 61, 12}}, + {106.0, {9, 52, 9}}, + {106.06060606060605, {8, 104, 21}}, + {106.06060606060606, {5, 34, 10}}, + {106.08695652173913, {4, 60, 22}}, + {106.12244897959184, {6, 25, 6}}, + {106.12244897959185, {6, 77, 20}}, + {106.15384615384616, {9, 68, 12}}, + {106.17283950617283, {8, 42, 8}}, + {106.17283950617285, {2, 42, 26}}, + {106.25, {3, 16, 7}}, + {106.25000000000001, {5, 50, 15}}, + {106.28019323671496, {8, 109, 22}}, + {106.28571428571429, {6, 92, 24}}, + {106.3157894736842, {9, 100, 18}}, + {106.34920634920636, {8, 66, 13}}, + {106.36363636363636, {9, 116, 21}}, + {106.4, {9, 132, 24}}, + {106.41025641025642, {5, 82, 25}}, + {106.42857142857143, {9, 148, 27}}, + {106.4327485380117, {8, 90, 18}}, + {106.48148148148148, {8, 114, 23}}, + {106.4935064935065, {6, 40, 10}}, + {106.52173913043478, {3, 48, 22}}, + {106.57894736842105, {7, 80, 18}}, + {106.5934065934066, {6, 96, 25}}, + {106.66666666666666, {8, 47, 9}}, + {106.66666666666667, {4, 15, 5}}, + {106.66666666666669, {2, 39, 24}}, + {106.73076923076923, {7, 110, 25}}, + {106.76691729323309, {6, 70, 18}}, + {106.81818181818181, {7, 46, 10}}, + {106.83229813664597, {6, 85, 22}}, + {106.83760683760684, {8, 124, 25}}, + {106.87830687830687, {8, 100, 20}}, + {106.87830687830689, {6, 100, 26}}, + {106.92307692307692, {9, 138, 25}}, + {106.94444444444444, {8, 76, 15}}, + {106.94444444444446, {5, 76, 23}}, + {106.95652173913044, {9, 122, 22}}, + {106.99588477366254, {8, 129, 26}}, + {107.0, {9, 106, 19}}, + {107.01754385964914, {5, 60, 18}}, + {107.05882352941177, {9, 90, 16}}, + {107.07070707070707, {8, 52, 10}}, + {107.14285714285714, {3, 14, 6}}, + {107.14285714285715, {6, 29, 7}}, + {107.18954248366013, {8, 81, 16}}, + {107.2, {4, 66, 24}}, + {107.2463768115942, {8, 110, 22}}, + {107.24637681159422, {2, 36, 22}}, + {107.27272727272727, {9, 58, 10}}, + {107.29166666666667, {7, 102, 23}}, + {107.3529411764706, {7, 72, 16}}, + {107.36842105263158, {4, 50, 18}}, + {107.4074074074074, {8, 28, 5}}, + {107.40740740740742, {5, 28, 8}}, + {107.42857142857143, {6, 93, 24}}, + {107.48299319727892, {6, 78, 20}}, + {107.5, {9, 42, 7}}, + {107.55555555555554, {8, 120, 24}}, + {107.56302521008404, {6, 63, 16}}, + {107.57575757575759, {5, 70, 21}}, + {107.60233918128654, {8, 91, 18}}, + {107.6086956521739, {7, 98, 22}}, + {107.61904761904762, {9, 112, 20}}, + {107.6923076923077, {0, 6, 12}}, + {107.77777777777777, {9, 96, 17}}, + {107.77777777777779, {8, 96, 19}}, + {107.7922077922078, {6, 82, 21}}, + {107.8125, {7, 68, 15}}, + {107.81893004115226, {8, 130, 26}}, + {107.82608695652173, {4, 61, 22}}, + {107.84313725490198, {5, 54, 16}}, + {107.89473684210526, {3, 40, 18}}, + {107.93650793650792, {8, 101, 20}}, + {107.93650793650794, {8, 33, 6}}, + {107.93650793650795, {2, 33, 20}}, + {107.95454545454545, {7, 94, 21}}, + {108.0, {4, 26, 9}}, + {108.07453416149069, {6, 86, 22}}, + {108.08080808080808, {8, 106, 21}}, + {108.14814814814814, {8, 72, 14}}, + {108.14814814814815, {4, 72, 26}}, + {108.16326530612245, {6, 52, 13}}, + {108.18181818181819, {9, 118, 21}}, + {108.21256038647343, {8, 111, 22}}, + {108.23529411764706, {4, 45, 16}}, + {108.27067669172934, {6, 71, 18}}, + {108.33333333333333, {3, 12, 5}}, + {108.33333333333334, {2, 12, 7}}, + {108.42105263157895, {9, 102, 18}}, + {108.44444444444443, {8, 121, 24}}, + {108.46153846153847, {9, 140, 25}}, + {108.49673202614379, {8, 82, 16}}, + {108.54700854700855, {8, 126, 25}}, + {108.57142857142857, {4, 18, 6}}, + {108.57142857142858, {6, 37, 9}}, + {108.64197530864196, {8, 131, 26}}, + {108.64197530864197, {8, 43, 8}}, + {108.65384615384616, {7, 112, 25}}, + {108.69565217391305, {1, 24, 22}}, + {108.75, {9, 86, 15}}, + {108.7719298245614, {8, 92, 18}}, + {108.77192982456143, {2, 30, 18}}, + {108.7912087912088, {6, 98, 25}}, + {108.8, {4, 67, 24}}, + {108.82352941176471, {3, 36, 16}}, + {108.843537414966, {6, 79, 20}}, + {108.88888888888889, {9, 48, 8}}, + {108.8888888888889, {5, 48, 14}}, + {108.92857142857143, {7, 60, 13}}, + {108.97435897435898, {5, 84, 25}}, + {108.99470899470899, {8, 102, 20}}, + {108.994708994709, {6, 102, 26}}, + {109.0, {9, 108, 19}}, + {109.0909090909091, {0, 5, 10}}, + {109.16666666666667, {9, 130, 23}}, + {109.17874396135265, {8, 112, 22}}, + {109.21052631578948, {7, 82, 18}}, + {109.23076923076923, {9, 70, 12}}, + {109.2436974789916, {6, 64, 16}}, + {109.25925925925925, {8, 58, 11}}, + {109.25925925925927, {5, 58, 17}}, + {109.3167701863354, {6, 87, 22}}, + {109.33333333333331, {8, 122, 24}}, + {109.33333333333333, {4, 40, 14}}, + {109.33333333333334, {2, 40, 24}}, + {109.375, {7, 34, 7}}, + {109.4017094017094, {8, 63, 12}}, + {109.41176470588235, {9, 92, 16}}, + {109.46502057613169, {8, 132, 26}}, + {109.47368421052632, {4, 51, 18}}, + {109.52380952380952, {8, 68, 13}}, + {109.52380952380953, {6, 22, 5}}, + {109.56521739130434, {4, 62, 22}}, + {109.6, {9, 136, 24}}, + {109.61538461538461, {7, 56, 12}}, + {109.62962962962962, {8, 73, 14}}, + {109.62962962962963, {4, 73, 26}}, + {109.71428571428572, {6, 95, 24}}, + {109.72222222222221, {8, 78, 15}}, + {109.72222222222223, {7, 78, 17}}, + {109.77443609022556, {6, 72, 18}}, + {109.78260869565217, {7, 100, 22}}, + {109.80392156862744, {8, 83, 16}}, + {109.80392156862746, {2, 27, 16}}, + {109.87654320987653, {8, 88, 17}}, + {109.87654320987656, {5, 88, 26}}, + {109.8901098901099, {6, 49, 12}}, + {109.94152046783624, {8, 93, 18}}, + {110.0, {9, 32, 5}}, + {110.05291005291004, {8, 103, 20}}, + {110.05291005291006, {6, 103, 26}}, + {110.1010101010101, {8, 108, 21}}, + {110.14492753623188, {8, 113, 22}}, + {110.14492753623189, {2, 37, 22}}, + {110.18518518518518, {8, 118, 23}}, + {110.18518518518519, {7, 118, 26}}, + {110.20408163265306, {6, 26, 6}}, + {110.22222222222223, {8, 123, 24}}, + {110.22727272727273, {7, 96, 21}}, + {110.25641025641025, {8, 128, 25}}, + {110.25641025641026, {5, 42, 12}}, + {110.2880658436214, {8, 133, 26}}, + {110.29411764705883, {7, 74, 16}}, + {110.37037037037037, {9, 148, 26}}, + {110.38961038961041, {6, 84, 21}}, + {110.4, {4, 68, 24}}, + {110.41666666666667, {7, 52, 11}}, + {110.43478260869566, {9, 126, 22}}, + {110.47619047619048, {4, 57, 20}}, + {110.4761904761905, {6, 57, 14}}, + {110.52631578947368, {1, 20, 18}}, + {110.55900621118013, {6, 88, 22}}, + {110.57692307692308, {7, 114, 25}}, + {110.58823529411765, {4, 46, 16}}, + {110.60606060606061, {5, 72, 21}}, + {110.66666666666667, {9, 82, 14}}, + {110.66666666666669, {5, 82, 24}}, + {110.71428571428571, {7, 30, 6}}, + {110.71428571428572, {6, 30, 7}}, + {110.76923076923077, {4, 35, 12}}, + {110.83333333333333, {9, 132, 23}}, + {110.85714285714286, {6, 96, 24}}, + {110.8695652173913, {3, 50, 22}}, + {110.9090909090909, {9, 60, 10}}, + {110.92436974789916, {6, 65, 16}}, + {110.9375, {7, 70, 15}}, + {110.98901098901099, {6, 100, 25}}, + {111.0, {9, 110, 19}}, + {111.1111111111111, {8, 29, 5}}, + {111.11111111111111, {8, 39, 7}}, + {111.11111111111113, {2, 9, 5}}, + {111.2, {9, 138, 24}}, + {111.25, {9, 88, 15}}, + {111.2781954887218, {6, 73, 18}}, + {111.30434782608695, {4, 63, 22}}, + {111.36363636363636, {7, 48, 10}}, + {111.42857142857143, {9, 38, 6}}, + {111.42857142857144, {6, 38, 9}}, + {111.45833333333333, {7, 106, 23}}, + {111.53846153846153, {3, 28, 12}}, + {111.56462585034015, {6, 81, 20}}, + {111.57894736842105, {4, 52, 18}}, + {111.59420289855073, {5, 76, 22}}, + {111.66666666666667, {9, 66, 11}}, + {111.6883116883117, {6, 42, 10}}, + {111.76470588235294, {1, 18, 16}}, + {111.76470588235296, {5, 56, 16}}, + {111.80124223602485, {6, 89, 22}}, + {111.81818181818181, {9, 122, 21}}, + {111.84210526315789, {7, 84, 18}}, + {111.9047619047619, {3, 46, 20}}, + {111.90476190476191, {6, 46, 11}}, + {111.95652173913044, {7, 102, 22}}, + {111.96581196581195, {8, 130, 25}}, + {112.0, {4, 27, 9}}, + {112.03703703703702, {8, 120, 23}}, + {112.07729468599034, {8, 115, 22}}, + {112.08791208791209, {6, 50, 12}}, + {112.12121212121211, {8, 110, 21}}, + {112.12121212121214, {5, 36, 10}}, + {112.16931216931218, {8, 105, 20}}, + {112.17391304347827, {9, 128, 22}}, + {112.22222222222221, {8, 100, 19}}, + {112.22222222222223, {9, 100, 17}}, + {112.24489795918369, {6, 54, 13}}, + {112.28070175438594, {8, 95, 18}}, + {112.28070175438597, {2, 31, 18}}, + {112.3076923076923, {9, 72, 12}}, + {112.34567901234567, {8, 90, 17}}, + {112.38095238095238, {6, 58, 14}}, + {112.41830065359477, {8, 85, 16}}, + {112.5, {7, 26, 5}}, + {112.50000000000001, {5, 26, 7}}, + {112.5925925925926, {8, 75, 14}}, + {112.60504201680673, {6, 66, 16}}, + {112.63157894736842, {9, 106, 18}}, + {112.6984126984127, {8, 70, 13}}, + {112.69841269841271, {6, 70, 17}}, + {112.72727272727273, {4, 30, 10}}, + {112.78195488721806, {6, 74, 18}}, + {112.8, {9, 140, 24}}, + {112.8205128205128, {8, 65, 12}}, + {112.82051282051283, {2, 21, 12}}, + {112.85714285714286, {9, 78, 13}}, + {112.88888888888889, {8, 126, 24}}, + {112.92517006802721, {6, 82, 20}}, + {112.94117647058823, {4, 47, 16}}, + {112.96296296296295, {8, 60, 11}}, + {112.96296296296298, {5, 60, 17}}, + {112.98701298701299, {6, 86, 21}}, + {113.0, {9, 112, 19}}, + {113.04347826086956, {0, 12, 22}}, + {113.07692307692308, {9, 146, 25}}, + {113.09523809523809, {6, 94, 23}}, + {113.0952380952381, {7, 94, 20}}, + {113.13131313131312, {8, 55, 10}}, + {113.14285714285715, {6, 98, 24}}, + {113.15789473684211, {3, 42, 18}}, + {113.1868131868132, {6, 102, 25}}, + {113.22751322751323, {8, 106, 20}}, + {113.23529411764706, {7, 76, 16}}, + {113.33333333333333, {4, 16, 5}}, + {113.33333333333334, {2, 16, 9}}, + {113.45029239766082, {8, 96, 18}}, + {113.46153846153847, {7, 58, 12}}, + {113.54166666666667, {7, 108, 23}}, + {113.58024691358024, {8, 45, 8}}, + {113.6, {4, 70, 24}}, + {113.63636363636364, {3, 24, 10}}, + {113.67521367521368, {8, 132, 25}}, + {113.6842105263158, {4, 53, 18}}, + {113.72549019607843, {8, 86, 16}}, + {113.72549019607844, {2, 28, 16}}, + {113.75, {9, 90, 15}}, + {113.77777777777777, {8, 127, 24}}, + {113.84615384615384, {4, 36, 12}}, + {113.88888888888887, {8, 122, 23}}, + {113.88888888888889, {8, 40, 7}}, + {113.8888888888889, {5, 40, 11}}, + {113.91304347826087, {9, 130, 22}}, + {114.0, {9, 56, 9}}, + {114.00966183574879, {8, 117, 22}}, + {114.03508771929826, {5, 64, 18}}, + {114.0625, {7, 72, 15}}, + {114.07407407407408, {8, 76, 14}}, + {114.10256410256412, {5, 88, 25}}, + {114.11764705882354, {9, 96, 16}}, + {114.1304347826087, {7, 104, 22}}, + {114.14141414141413, {8, 112, 21}}, + {114.16666666666667, {9, 136, 23}}, + {114.28571428571428, {6, 43, 10}}, + {114.28571428571429, {6, 23, 5}}, + {114.2857142857143, {6, 91, 22}}, + {114.4, {9, 142, 24}}, + {114.42307692307692, {7, 118, 25}}, + {114.44444444444443, {8, 102, 19}}, + {114.44444444444444, {9, 102, 17}}, + {114.47368421052632, {7, 86, 18}}, + {114.4927536231884, {5, 78, 22}}, + {114.52991452991454, {8, 66, 12}}, + {114.54545454545455, {9, 62, 10}}, + {114.58333333333333, {7, 54, 11}}, + {114.58333333333334, {5, 54, 15}}, + {114.61538461538461, {9, 148, 25}}, + {114.61988304093568, {8, 97, 18}}, + {114.66666666666666, {8, 128, 24}}, + {114.66666666666667, {4, 42, 14}}, + {114.66666666666669, {2, 42, 24}}, + {114.70588235294117, {3, 38, 16}}, + {114.73684210526316, {9, 108, 18}}, + {114.77272727272727, {7, 100, 21}}, + {114.78260869565217, {4, 65, 22}}, + {114.81481481481481, {8, 92, 17}}, + {114.81481481481482, {8, 30, 5}}, + {114.81481481481484, {5, 30, 8}}, + {114.97584541062801, {8, 118, 22}}, + {115.0, {4, 22, 7}}, + {115.03267973856208, {8, 87, 16}}, + {115.15151515151514, {8, 56, 10}}, + {115.15151515151516, {2, 18, 10}}, + {115.2, {4, 71, 24}}, + {115.21739130434783, {3, 52, 22}}, + {115.23809523809524, {9, 120, 20}}, + {115.27777777777777, {8, 82, 15}}, + {115.27777777777779, {5, 82, 23}}, + {115.29411764705883, {4, 48, 16}}, + {115.34391534391534, {8, 108, 20}}, + {115.38461538461539, {1, 14, 12}}, + {115.42857142857143, {6, 100, 24}}, + {115.45454545454545, {9, 126, 21}}, + {115.47619047619048, {7, 96, 20}}, + {115.52795031055902, {6, 92, 22}}, + {115.55555555555554, {8, 51, 9}}, + {115.55555555555556, {4, 25, 8}}, + {115.55555555555557, {2, 25, 14}}, + {115.5844155844156, {6, 88, 21}}, + {115.625, {7, 36, 7}}, + {115.64625850340137, {6, 84, 20}}, + {115.65217391304348, {9, 132, 22}}, + {115.68627450980392, {5, 58, 16}}, + {115.71428571428571, {9, 80, 13}}, + {115.74074074074075, {8, 124, 23}}, + {115.78947368421052, {0, 10, 18}}, + {115.83333333333333, {9, 138, 23}}, + {115.87301587301587, {8, 72, 13}}, + {115.9090909090909, {7, 50, 10}}, + {115.94202898550724, {8, 119, 22}}, + {115.94202898550726, {2, 39, 22}}, + {115.96638655462186, {6, 68, 16}}, + {116.0, {4, 28, 9}}, + {116.04938271604937, {8, 46, 8}}, + {116.07142857142857, {7, 64, 13}}, + {116.07142857142858, {6, 64, 15}}, + {116.16161616161617, {8, 114, 21}}, + {116.17647058823529, {7, 78, 16}}, + {116.19047619047619, {6, 60, 14}}, + {116.23931623931624, {8, 67, 12}}, + {116.25, {9, 92, 15}}, + {116.30434782608695, {7, 106, 22}}, + {116.32653061224491, {6, 56, 13}}, + {116.33986928104574, {8, 88, 16}}, + {116.36363636363636, {4, 31, 10}}, + {116.40211640211639, {8, 109, 20}}, + {116.44444444444443, {8, 130, 24}}, + {116.47058823529412, {9, 98, 16}}, + {116.4835164835165, {6, 52, 12}}, + {116.52173913043478, {4, 66, 22}}, + {116.57142857142857, {6, 101, 24}}, + {116.66666666666666, {8, 41, 7}}, + {116.66666666666667, {1, 6, 5}}, + {116.66666666666669, {5, 76, 21}}, + {116.77018633540374, {6, 93, 22}}, + {116.8, {4, 72, 24}}, + {116.84210526315789, {9, 110, 18}}, + {116.88311688311688, {6, 44, 10}}, + {116.90821256038646, {8, 120, 22}}, + {116.92307692307692, {4, 37, 12}}, + {116.95906432748538, {8, 99, 18}}, + {117.0, {9, 116, 19}}, + {117.00680272108845, {6, 85, 20}}, + {117.03703703703702, {8, 78, 14}}, + {117.04545454545455, {7, 102, 21}}, + {117.10526315789474, {7, 88, 18}}, + {117.14285714285714, {9, 40, 6}}, + {117.14285714285715, {6, 40, 9}}, + {117.17171717171718, {8, 57, 10}}, + {117.1875, {7, 74, 15}}, + {117.27272727272727, {9, 128, 21}}, + {117.28395061728394, {8, 94, 17}}, + {117.29323308270678, {6, 77, 18}}, + {117.3076923076923, {7, 60, 12}}, + {117.33333333333331, {8, 131, 24}}, + {117.33333333333333, {4, 43, 14}}, + {117.33333333333334, {2, 43, 24}}, + {117.3913043478261, {1, 26, 22}}, + {117.46031746031746, {8, 36, 6}}, + {117.46031746031747, {2, 36, 20}}, + {117.5, {9, 46, 7}}, + {117.54385964912281, {5, 66, 18}}, + {117.5925925925926, {8, 126, 23}}, + {117.6, {9, 146, 24}}, + {117.6470588235294, {0, 9, 16}}, + {117.64705882352942, {2, 29, 16}}, + {117.70833333333333, {7, 112, 23}}, + {117.71428571428572, {6, 102, 24}}, + {117.77777777777777, {9, 52, 8}}, + {117.77777777777779, {8, 52, 9}}, + {117.85714285714286, {7, 32, 6}}, + {117.85714285714288, {6, 98, 23}}, + {117.87439613526568, {8, 121, 22}}, + {117.89473684210526, {4, 55, 18}}, + {117.94871794871794, {8, 68, 12}}, + {117.94871794871796, {2, 22, 12}}, + {118.0, {9, 58, 9}}, + {118.01242236024845, {6, 94, 22}}, + {118.05555555555556, {8, 84, 15}}, + {118.0952380952381, {6, 61, 14}}, + {118.12865497076022, {8, 100, 18}}, + {118.18181818181819, {1, 12, 10}}, + {118.22222222222223, {8, 132, 24}}, + {118.26086956521739, {4, 67, 22}}, + {118.33333333333333, {9, 70, 11}}, + {118.33333333333334, {5, 70, 19}}, + {118.36734693877551, {6, 86, 20}}, + {118.36734693877553, {6, 28, 6}}, + {118.4, {4, 73, 24}}, + {118.42105263157895, {3, 44, 18}}, + {118.46153846153847, {9, 76, 12}}, + {118.47826086956522, {7, 108, 22}}, + {118.5185185185185, {8, 47, 8}}, + {118.51851851851852, {8, 31, 5}}, + {118.51851851851853, {2, 15, 8}}, + {118.57142857142857, {9, 82, 13}}, + {118.57142857142858, {6, 82, 19}}, + {118.66666666666667, {9, 88, 14}}, + {118.66666666666669, {5, 88, 24}}, + {118.68131868131869, {6, 53, 12}}, + {118.75, {3, 18, 7}}, + {118.75000000000001, {5, 56, 15}}, + {118.79699248120302, {6, 78, 18}}, + {118.82352941176471, {9, 100, 16}}, + {118.84057971014491, {8, 122, 22}}, + {118.84057971014494, {2, 40, 22}}, + {118.85714285714286, {6, 103, 24}}, + {118.88888888888889, {9, 106, 17}}, + {118.94736842105263, {9, 112, 18}}, + {118.95424836601308, {8, 90, 16}}, + {119.0, {9, 118, 19}}, + {119.04761904761904, {8, 74, 13}}, + {119.04761904761905, {6, 24, 5}}, + {119.04761904761907, {6, 74, 17}}, + {119.0909090909091, {9, 130, 21}}, + {119.11111111111111, {8, 133, 24}}, + {119.11764705882354, {7, 80, 16}}, + {119.1304347826087, {9, 136, 22}}, + {119.16666666666667, {9, 142, 23}}, + {119.19191919191918, {8, 58, 10}}, + {119.2, {9, 148, 24}}, + {119.23076923076923, {3, 30, 12}}, + {119.25465838509318, {6, 95, 22}}, + {119.29824561403508, {8, 101, 18}}, + {119.29824561403511, {2, 33, 18}}, + {119.31818181818181, {7, 104, 21}}, + {119.32773109243698, {6, 70, 16}}, + {119.44444444444444, {8, 42, 7}}, + {119.44444444444446, {5, 42, 11}}, + {119.48051948051949, {6, 45, 10}}, + {119.56521739130434, {3, 54, 22}}, + {119.57671957671957, {8, 112, 20}}, + {119.60784313725492, {5, 60, 16}}, + {119.64285714285714, {7, 66, 13}}, + {119.64285714285715, {6, 66, 15}}, + {119.65811965811965, {8, 69, 12}}, + {119.6969696969697, {5, 78, 21}}, + {119.72789115646258, {6, 87, 20}}, + {119.73684210526316, {7, 90, 18}}, + {119.75308641975309, {8, 96, 17}}, + {119.79166666666667, {7, 114, 23}}, + {119.80676328502416, {8, 123, 22}}, + {120.0, {0, 2, 4}}, + {120.00000000000001, {2, 26, 14}}, + {120.2020202020202, {8, 118, 21}}, + {120.23809523809524, {7, 100, 20}}, + {120.26143790849673, {8, 91, 16}}, + {120.28985507246378, {5, 82, 22}}, + {120.30075187969925, {6, 79, 18}}, + {120.3125, {7, 76, 15}}, + {120.37037037037037, {8, 64, 11}}, + {120.37037037037038, {5, 64, 17}}, + {120.40816326530613, {6, 58, 13}}, + {120.45454545454545, {7, 52, 10}}, + {120.46783625730993, {8, 102, 18}}, + {120.4968944099379, {6, 96, 22}}, + {120.51282051282053, {5, 46, 12}}, + {120.58823529411765, {3, 40, 16}}, + {120.63492063492062, {8, 113, 20}}, + {120.63492063492063, {8, 37, 6}}, + {120.63492063492065, {6, 37, 8}}, + {120.65217391304348, {7, 110, 22}}, + {120.77294685990339, {8, 124, 22}}, + {120.7792207792208, {6, 92, 21}}, + {120.83333333333333, {7, 28, 5}}, + {120.83333333333334, {5, 28, 7}}, + {120.8695652173913, {9, 138, 22}}, + {120.87912087912089, {6, 54, 12}}, + {120.9090909090909, {9, 132, 21}}, + {120.95238095238095, {9, 126, 20}}, + {120.98765432098766, {8, 48, 8}}, + {121.0, {9, 120, 19}}, + {121.00840336134455, {6, 71, 16}}, + {121.05263157894737, {1, 22, 18}}, + {121.08843537414967, {6, 88, 20}}, + {121.11111111111111, {9, 108, 17}}, + {121.15384615384616, {7, 62, 12}}, + {121.17647058823529, {9, 102, 16}}, + {121.2121212121212, {8, 59, 10}}, + {121.21212121212123, {2, 19, 10}}, + {121.25, {9, 96, 15}}, + {121.29629629629629, {8, 130, 23}}, + {121.33333333333333, {9, 90, 14}}, + {121.36752136752138, {8, 70, 12}}, + {121.42857142857143, {3, 16, 6}}, + {121.42857142857144, {5, 50, 13}}, + {121.48148148148148, {8, 81, 14}}, + {121.53846153846153, {9, 78, 12}}, + {121.56862745098039, {8, 92, 16}}, + {121.56862745098042, {2, 30, 16}}, + {121.5909090909091, {7, 106, 21}}, + {121.63742690058479, {8, 103, 18}}, + {121.66666666666667, {9, 72, 11}}, + {121.6931216931217, {8, 114, 20}}, + {121.73913043478261, {0, 13, 22}}, + {121.80451127819549, {6, 80, 18}}, + {121.81818181818181, {9, 66, 10}}, + {121.875, {7, 38, 7}}, + {121.9047619047619, {4, 63, 20}}, + {121.90476190476191, {6, 63, 14}}, + {122.0, {9, 60, 9}}, + {122.05882352941177, {7, 82, 16}}, + {122.07792207792208, {6, 46, 10}}, + {122.10526315789474, {4, 57, 18}}, + {122.22222222222221, {8, 32, 5}}, + {122.22222222222223, {2, 10, 5}}, + {122.22222222222224, {5, 76, 20}}, + {122.3529411764706, {4, 51, 16}}, + {122.36842105263158, {7, 92, 18}}, + {122.44897959183675, {6, 29, 6}}, + {122.5, {9, 48, 7}}, + {122.6086956521739, {9, 140, 22}}, + {122.61904761904762, {7, 102, 20}}, + {122.61904761904763, {6, 102, 23}}, + {122.66666666666667, {4, 45, 14}}, + {122.6890756302521, {6, 72, 16}}, + {122.70531400966183, {8, 126, 22}}, + {122.72727272727273, {3, 26, 10}}, + {122.75132275132276, {8, 115, 20}}, + {122.80701754385963, {8, 104, 18}}, + {122.80701754385966, {2, 34, 18}}, + {122.82608695652173, {7, 112, 22}}, + {122.85714285714286, {9, 42, 6}}, + {122.87581699346404, {8, 93, 16}}, + {122.91666666666667, {7, 58, 11}}, + {122.96296296296296, {8, 82, 14}}, + {122.98136645962734, {6, 98, 22}}, + {123.0, {9, 122, 19}}, + {123.07692307692308, {0, 7, 12}}, + {123.14814814814815, {8, 132, 23}}, + {123.15789473684211, {9, 116, 18}}, + {123.18840579710145, {5, 84, 22}}, + {123.21428571428571, {7, 68, 13}}, + {123.21428571428572, {6, 68, 15}}, + {123.23232323232322, {8, 60, 10}}, + {123.30827067669175, {6, 81, 18}}, + {123.33333333333333, {9, 36, 5}}, + {123.33333333333334, {5, 36, 9}}, + {123.37662337662337, {6, 94, 21}}, + {123.4375, {7, 78, 15}}, + {123.45679012345678, {8, 49, 8}}, + {123.47826086956522, {4, 70, 22}}, + {123.52941176470588, {1, 20, 16}}, + {123.6111111111111, {8, 88, 15}}, + {123.61111111111111, {7, 88, 17}}, + {123.61111111111113, {5, 88, 23}}, + {123.63636363636364, {4, 33, 10}}, + {123.67149758454106, {8, 127, 22}}, + {123.6842105263158, {3, 46, 18}}, + {123.75, {9, 98, 15}}, + {123.80952380952381, {6, 25, 5}}, + {123.80952380952382, {2, 12, 6}}, + {123.86363636363636, {7, 108, 21}}, + {123.91304347826087, {3, 56, 22}}, + {123.95833333333333, {7, 118, 23}}, + {123.9766081871345, {8, 105, 18}}, + {124.0, {9, 30, 4}}, + {124.07407407407408, {8, 66, 11}}, + {124.16666666666667, {9, 148, 23}}, + {124.1830065359477, {8, 94, 16}}, + {124.21052631578948, {4, 58, 18}}, + {124.22360248447205, {6, 99, 22}}, + {124.24242424242424, {8, 122, 21}}, + {124.24242424242425, {5, 40, 10}}, + {124.28571428571429, {9, 86, 13}}, + {124.34782608695652, {9, 142, 22}}, + {124.36974789915966, {6, 73, 16}}, + {124.44444444444443, {8, 27, 4}}, + {124.44444444444444, {4, 27, 8}}, + {124.48979591836735, {6, 60, 13}}, + {124.54545454545455, {9, 136, 21}}, + {124.56140350877195, {5, 70, 18}}, + {124.61538461538461, {9, 80, 12}}, + {124.63768115942028, {8, 128, 22}}, + {124.6376811594203, {2, 42, 22}}, + {124.67532467532469, {6, 47, 10}}, + {124.69135802469135, {8, 100, 17}}, + {124.70588235294117, {4, 52, 16}}, + {124.76190476190476, {9, 130, 20}}, + {124.78632478632478, {8, 72, 12}}, + {124.81203007518798, {6, 82, 18}}, + {124.86772486772486, {8, 117, 20}}, + {125.0, {7, 24, 4}}, + {125.00000000000001, {2, 14, 7}}, + {125.14619883040936, {8, 106, 18}}, + {125.1700680272109, {6, 91, 20}}, + {125.21739130434783, {4, 71, 22}}, + {125.25252525252526, {8, 61, 10}}, + {125.26315789473684, {9, 118, 18}}, + {125.27472527472528, {6, 56, 12}}, + {125.33333333333333, {4, 46, 14}}, + {125.39682539682539, {8, 78, 13}}, + {125.3968253968254, {6, 78, 17}}, + {125.45454545454545, {9, 68, 10}}, + {125.46583850931677, {6, 100, 22}}, + {125.49019607843135, {8, 95, 16}}, + {125.49019607843138, {2, 31, 16}}, + {125.55555555555554, {8, 112, 19}}, + {125.55555555555556, {9, 112, 17}}, + {125.6038647342995, {8, 129, 22}}, + {125.64102564102565, {5, 48, 12}}, + {125.71428571428571, {6, 21, 4}}, + {125.71428571428572, {6, 65, 14}}, + {125.75757575757576, {5, 82, 21}}, + {125.88235294117646, {9, 106, 16}}, + {125.92592592592592, {8, 33, 5}}, + {125.92592592592594, {2, 16, 8}}, + {125.97402597402598, {6, 96, 21}}, + {126.0, {9, 62, 9}}, + {126.05042016806725, {6, 74, 16}}, + {126.08695652173913, {1, 28, 22}}, + {126.13636363636364, {7, 110, 21}}, + {126.15384615384616, {4, 40, 12}}, + {126.19047619047619, {5, 52, 13}}, + {126.1904761904762, {6, 52, 11}}, + {126.25, {9, 100, 15}}, + {126.26262626262627, {8, 124, 21}}, + {126.3157894736842, {0, 11, 18}}, + {126.36363636363636, {9, 138, 21}}, + {126.38888888888889, {8, 90, 15}}, + {126.47058823529412, {3, 42, 16}}, + {126.49572649572649, {8, 73, 12}}, + {126.53061224489797, {6, 30, 6}}, + {126.5625, {7, 80, 15}}, + {126.57004830917873, {8, 130, 22}}, + {126.66666666666666, {8, 56, 9}}, + {126.66666666666667, {5, 18, 4}}, + {126.66666666666669, {5, 56, 14}}, + {126.70807453416148, {6, 101, 22}}, + {126.78571428571429, {7, 70, 13}}, + {126.79738562091504, {8, 96, 16}}, + {126.92307692307692, {3, 32, 12}}, + {126.95652173913044, {4, 72, 22}}, + {126.98412698412697, {8, 119, 20}}, + {126.98412698412699, {8, 39, 6}}, + {126.984126984127, {2, 39, 20}}, + {127.0, {9, 126, 19}}, + {127.05882352941177, {4, 53, 16}}, + {127.08333333333333, {7, 60, 11}}, + {127.08333333333334, {5, 60, 15}}, + {127.14285714285714, {9, 88, 13}}, + {127.14285714285715, {6, 88, 19}}, + {127.16049382716048, {8, 102, 17}}, + {127.17391304347827, {7, 116, 22}}, + {127.27272727272727, {0, 6, 10}}, + {127.36842105263158, {9, 120, 18}}, + {127.38095238095238, {7, 106, 20}}, + {127.4074074074074, {8, 85, 14}}, + {127.45098039215688, {5, 64, 16}}, + {127.47252747252749, {6, 57, 12}}, + {127.48538011695906, {8, 108, 18}}, + {127.5, {9, 50, 7}}, + {127.53623188405795, {8, 131, 22}}, + {127.53623188405798, {2, 43, 22}}, + {127.61904761904762, {4, 66, 20}}, + {127.61904761904763, {6, 66, 14}}, + {127.63157894736842, {7, 96, 18}}, + {127.6923076923077, {9, 82, 12}}, + {127.73109243697479, {6, 75, 16}}, + {127.77777777777777, {8, 45, 7}}, + {127.77777777777779, {5, 22, 5}}, + {127.81954887218046, {6, 84, 18}}, + {127.82608695652173, {9, 146, 22}}, + {127.89115646258503, {6, 93, 20}}, + {127.94117647058823, {7, 86, 16}}, + {127.95031055900623, {6, 102, 22}}, + {128.0, {4, 15, 4}}, + {128.04232804232802, {8, 120, 20}}, + {128.0701754385965, {5, 72, 18}}, + {128.1045751633987, {8, 97, 16}}, + {128.125, {7, 40, 7}}, + {128.1818181818182, {9, 140, 21}}, + {128.2051282051282, {8, 74, 12}}, + {128.23529411764707, {9, 108, 16}}, + {128.2608695652174, {3, 58, 22}}, + {128.2828282828283, {8, 126, 21}}, + {128.33333333333334, {9, 76, 11}}, + {128.39506172839504, {8, 51, 8}}, + {128.4090909090909, {7, 112, 21}}, + {128.42105263157896, {4, 60, 18}}, + {128.5024154589372, {8, 132, 22}}, + {128.57142857142856, {6, 80, 17}}, + {128.57142857142858, {6, 26, 5}}, + {128.6549707602339, {8, 109, 18}}, + {128.69565217391303, {4, 73, 22}}, + {128.75, {9, 102, 15}}, + {128.78787878787878, {5, 84, 21}}, + {128.84615384615384, {7, 66, 12}}, + {128.88888888888889, {8, 28, 4}}, + {128.94736842105263, {3, 48, 18}}, + {128.9855072463768, {5, 88, 22}}, + {129.0, {9, 128, 19}}, + {129.0909090909091, {9, 70, 10}}, + {129.1005291005291, {8, 121, 20}}, + {129.16666666666666, {7, 30, 5}}, + {129.16666666666669, {5, 30, 7}}, + {129.19254658385094, {6, 103, 22}}, + {129.23076923076923, {4, 41, 12}}, + {129.2517006802721, {6, 94, 20}}, + {129.2929292929293, {8, 63, 10}}, + {129.3233082706767, {6, 85, 18}}, + {129.33333333333334, {9, 96, 14}}, + {129.34782608695653, {7, 118, 22}}, + {129.41176470588235, {0, 10, 16}}, + {129.46859903381642, {8, 133, 22}}, + {129.47368421052633, {9, 122, 18}}, + {129.52380952380952, {6, 67, 14}}, + {129.54545454545453, {7, 56, 10}}, + {129.56521739130434, {9, 148, 22}}, + {129.62962962962962, {8, 34, 5}}, + {129.62962962962965, {5, 34, 8}}, + {129.67032967032966, {6, 58, 12}}, + {129.6875, {7, 82, 15}}, + {129.76190476190476, {7, 108, 20}}, + {129.82456140350877, {8, 110, 18}}, + {129.8245614035088, {2, 36, 18}}, + {129.8701298701299, {6, 49, 10}}, + {129.9145299145299, {8, 75, 12}}, + {130.0, {3, 12, 4}}, + {130.15873015873015, {8, 40, 6}}, + {130.15873015873018, {6, 40, 8}}, + {130.26315789473685, {7, 98, 18}}, + {130.30303030303028, {8, 128, 21}}, + {130.3030303030303, {5, 42, 10}}, + {130.35714285714286, {7, 72, 13}}, + {130.37037037037035, {8, 87, 14}}, + {130.43478260869566, {0, 14, 22}}, + {130.47619047619048, {9, 136, 20}}, + {130.52631578947367, {4, 61, 18}}, + {130.55555555555554, {8, 46, 7}}, + {130.55555555555557, {5, 46, 11}}, + {130.58823529411765, {9, 110, 16}}, + {130.6122448979592, {6, 31, 6}}, + {130.66666666666666, {4, 48, 14}}, + {130.6818181818182, {7, 114, 21}}, + {130.718954248366, {8, 99, 16}}, + {130.76923076923077, {1, 16, 12}}, + {130.82706766917295, {6, 86, 18}}, + {130.8641975308642, {8, 52, 8}}, + {130.88235294117646, {7, 88, 16}}, + {130.9090909090909, {4, 35, 10}}, + {130.95238095238096, {6, 54, 11}}, + {130.99415204678363, {8, 111, 18}}, + {131.0, {9, 130, 19}}, + {131.09243697478993, {6, 77, 16}}, + {131.11111111111111, {9, 58, 8}}, + {131.16883116883116, {6, 100, 21}}, + {131.21693121693121, {8, 123, 20}}, + {131.25, {3, 20, 7}}, + {131.3131313131313, {8, 64, 10}}, + {131.37254901960785, {5, 66, 16}}, + {131.42857142857142, {4, 22, 6}}, + {131.42857142857144, {6, 22, 4}}, + {131.4814814814815, {8, 70, 11}}, + {131.57894736842104, {1, 24, 18}}, + {131.6239316239316, {8, 76, 12}}, + {131.66666666666666, {9, 78, 11}}, + {131.66666666666669, {5, 78, 19}}, + {131.74603174603175, {8, 82, 13}}, + {131.76470588235293, {4, 55, 16}}, + {131.8181818181818, {3, 28, 10}}, + {131.85185185185185, {8, 88, 14}}, + {131.86813186813188, {6, 59, 12}}, + {131.94444444444443, {8, 94, 15}}, + {131.94444444444446, {7, 94, 17}}, + {131.97278911564626, {6, 96, 20}}, + {132.0, {9, 32, 4}}, + {132.02614379084966, {8, 100, 16}}, + {132.09876543209876, {8, 106, 17}}, + {132.14285714285714, {7, 36, 6}}, + {132.16374269005846, {8, 112, 18}}, + {132.22222222222223, {9, 118, 17}}, + {132.27513227513228, {8, 124, 20}}, + {132.30769230769232, {4, 42, 12}}, + {132.3232323232323, {8, 130, 21}}, + {132.33082706766916, {6, 87, 18}}, + {132.35294117647058, {3, 44, 16}}, + {132.38095238095238, {9, 138, 20}}, + {132.46753246753246, {6, 50, 10}}, + {132.5, {9, 52, 7}}, + {132.6315789473684, {4, 62, 18}}, + {132.65306122448982, {6, 64, 13}}, + {132.69230769230768, {7, 68, 12}}, + {132.72727272727272, {9, 72, 10}}, + {132.7731092436975, {6, 78, 16}}, + {132.8125, {7, 84, 15}}, + {132.85714285714286, {9, 92, 13}}, + {132.89473684210526, {7, 100, 18}}, + {132.94117647058823, {9, 112, 16}}, + {132.95454545454547, {7, 116, 21}}, + {133.0, {9, 132, 19}}, + {133.33333333333331, {8, 29, 4}}, + {133.33333333333334, {2, 9, 4}}, + {133.63636363636363, {9, 146, 21}}, + {133.68421052631578, {9, 126, 18}}, + {133.75, {9, 106, 15}}, + {133.76623376623377, {6, 102, 21}}, + {133.8235294117647, {7, 90, 16}}, + {133.83458646616543, {6, 88, 18}}, + {133.84615384615384, {9, 86, 12}}, + {133.92857142857142, {7, 74, 13}}, + {133.92857142857144, {6, 74, 15}}, + {134.0, {9, 66, 9}}, + {134.06593406593407, {6, 60, 12}}, + {134.0909090909091, {7, 58, 10}}, + {134.11764705882354, {4, 56, 16}}, + {134.21052631578948, {3, 50, 18}}, + {134.28571428571428, {9, 46, 6}}, + {134.34343434343435, {8, 132, 21}}, + {134.375, {7, 42, 7}}, + {134.39153439153438, {8, 126, 20}}, + {134.44444444444443, {8, 120, 19}}, + {134.44444444444446, {9, 120, 17}}, + {134.45378151260505, {6, 79, 16}}, + {134.5029239766082, {8, 114, 18}}, + {134.52380952380952, {7, 112, 20}}, + {134.54545454545453, {4, 36, 10}}, + {134.5679012345679, {8, 108, 17}}, + {134.6153846153846, {3, 34, 12}}, + {134.64052287581697, {8, 102, 16}}, + {134.66666666666666, {9, 100, 14}}, + {134.69387755102042, {6, 32, 6}}, + {134.72222222222223, {8, 96, 15}}, + {134.73684210526315, {4, 63, 18}}, + {134.8148148148148, {8, 90, 14}}, + {134.84848484848487, {5, 88, 21}}, + {134.9206349206349, {8, 84, 13}}, + {134.92063492063494, {6, 84, 17}}, + {135.0, {7, 26, 4}}, + {135.04273504273505, {8, 78, 12}}, + {135.06493506493507, {6, 51, 10}}, + {135.08771929824562, {5, 76, 18}}, + {135.1851851851852, {8, 72, 11}}, + {135.22727272727272, {7, 118, 21}}, + {135.23809523809524, {6, 70, 14}}, + {135.2941176470588, {1, 22, 16}}, + {135.33834586466165, {6, 89, 18}}, + {135.35353535353536, {8, 66, 10}}, + {135.3846153846154, {4, 43, 12}}, + {135.41666666666666, {7, 64, 11}}, + {135.41666666666669, {5, 64, 15}}, + {135.44973544973544, {8, 127, 20}}, + {135.45454545454547, {9, 148, 21}}, + {135.52631578947367, {7, 102, 18}}, + {135.55555555555554, {9, 60, 8}}, + {135.55555555555557, {5, 60, 14}}, + {135.67251461988303, {8, 115, 18}}, + {135.71428571428572, {3, 18, 6}}, + {135.78947368421052, {9, 128, 18}}, + {135.80246913580245, {8, 54, 8}}, + {135.8974358974359, {5, 52, 12}}, + {135.9375, {7, 86, 15}}, + {135.94771241830063, {8, 103, 16}}, + {136.0, {4, 16, 4}}, + {136.0544217687075, {6, 99, 20}}, + {136.11111111111111, {8, 48, 7}}, + {136.1344537815126, {6, 80, 16}}, + {136.1904761904762, {9, 142, 20}}, + {136.25, {9, 108, 15}}, + {136.26373626373626, {6, 61, 12}}, + {136.29629629629628, {8, 91, 14}}, + {136.36363636363637, {1, 14, 10}}, + {136.47058823529412, {4, 57, 16}}, + {136.5079365079365, {8, 42, 6}}, + {136.50793650793653, {2, 42, 20}}, + {136.53846153846155, {7, 70, 12}}, + {136.66666666666666, {9, 40, 5}}, + {136.66666666666669, {5, 40, 9}}, + {136.73469387755102, {6, 66, 13}}, + {136.75213675213675, {8, 79, 12}}, + {136.76470588235293, {7, 92, 16}}, + {136.8421052631579, {0, 12, 18}}, + {136.9047619047619, {7, 114, 20}}, + {136.92307692307693, {9, 88, 12}}, + {137.0, {9, 136, 19}}, + {137.03703703703704, {8, 36, 5}}, + {137.03703703703707, {5, 36, 8}}, + {137.14285714285714, {4, 23, 6}}, + {137.14285714285717, {6, 23, 4}}, + {137.2549019607843, {8, 104, 16}}, + {137.33333333333334, {9, 102, 14}}, + {137.37373737373738, {8, 67, 10}}, + {137.41496598639455, {6, 100, 20}}, + {137.5, {7, 32, 5}}, + {137.56613756613757, {8, 129, 20}}, + {137.64705882352942, {9, 116, 16}}, + {137.66233766233768, {6, 52, 10}}, + {137.77777777777777, {8, 30, 4}}, + {137.7777777777778, {2, 30, 14}}, + {137.8151260504202, {6, 81, 16}}, + {137.89473684210526, {9, 130, 18}}, + {138.0, {9, 68, 9}}, + {138.01169590643275, {8, 117, 18}}, + {138.0952380952381, {6, 28, 5}}, + {138.1578947368421, {7, 104, 18}}, + {138.1818181818182, {4, 37, 10}}, + {138.23529411764707, {3, 46, 16}}, + {138.2716049382716, {8, 55, 8}}, + {138.33333333333334, {9, 82, 11}}, + {138.34586466165416, {6, 91, 18}}, + {138.46153846153845, {0, 8, 12}}, + {138.46153846153848, {2, 26, 12}}, + {138.562091503268, {8, 105, 16}}, + {138.57142857142858, {9, 96, 13}}, + {138.5964912280702, {5, 78, 18}}, + {138.6243386243386, {8, 130, 20}}, + {138.63636363636363, {7, 60, 10}}, + {138.66666666666666, {4, 51, 14}}, + {138.75, {9, 110, 15}}, + {138.77551020408163, {6, 33, 6}}, + {138.8235294117647, {4, 58, 16}}, + {138.88888888888889, {5, 24, 5}}, + {138.94736842105263, {4, 65, 18}}, + {139.0, {9, 138, 19}}, + {139.04761904761904, {4, 72, 20}}, + {139.04761904761907, {6, 72, 14}}, + {139.0625, {7, 88, 15}}, + {139.1812865497076, {8, 118, 18}}, + {139.21568627450984, {5, 70, 16}}, + {139.25925925925924, {8, 93, 14}}, + {139.28571428571428, {7, 38, 6}}, + {139.2857142857143, {6, 38, 7}}, + {139.39393939393938, {8, 68, 10}}, + {139.3939393939394, {2, 22, 10}}, + {139.47368421052633, {3, 52, 18}}, + {139.49579831932775, {6, 82, 16}}, + {139.50617283950615, {8, 112, 17}}, + {139.58333333333334, {7, 66, 11}}, + {139.68253968253967, {8, 43, 6}}, + {139.6825396825397, {2, 43, 20}}, + {139.7058823529412, {7, 94, 16}}, + {139.84962406015038, {6, 92, 18}}, + {139.86928104575165, {8, 106, 16}}, + {140.0, {1, 6, 4}}, + {140.13605442176873, {6, 102, 20}}, + {140.17094017094016, {8, 81, 12}}, + {140.25974025974025, {6, 53, 10}}, + {140.27777777777777, {8, 100, 15}}, + {140.35087719298244, {8, 119, 18}}, + {140.35087719298247, {2, 39, 18}}, + {140.3846153846154, {7, 72, 12}}, + {140.47619047619048, {6, 58, 11}}, + {140.625, {7, 44, 7}}, + {140.65934065934067, {6, 63, 12}}, + {140.74074074074073, {8, 37, 5}}, + {140.74074074074076, {2, 18, 8}}, + {140.78947368421052, {7, 106, 18}}, + {140.81632653061226, {6, 68, 13}}, + {140.9090909090909, {3, 30, 10}}, + {140.95238095238093, {6, 73, 14}}, + {140.95238095238096, {4, 73, 20}}, + {141.0, {9, 140, 19}}, + {141.02564102564105, {5, 54, 12}}, + {141.05263157894737, {4, 66, 18}}, + {141.07142857142858, {7, 78, 13}}, + {141.11111111111111, {9, 126, 17}}, + {141.1764705882353, {0, 11, 16}}, + {141.25, {9, 112, 15}}, + {141.26984126984127, {8, 88, 13}}, + {141.2698412698413, {6, 88, 17}}, + {141.33333333333334, {4, 52, 14}}, + {141.35338345864662, {6, 93, 18}}, + {141.4141414141414, {8, 69, 10}}, + {141.42857142857142, {9, 98, 13}}, + {141.42857142857144, {6, 98, 19}}, + {141.49659863945578, {6, 103, 20}}, + {141.5204678362573, {8, 120, 18}}, + {141.53846153846155, {4, 45, 12}}, + {141.66666666666666, {3, 16, 5}}, + {141.66666666666669, {2, 16, 7}}, + {141.7989417989418, {8, 133, 20}}, + {141.8181818181818, {4, 38, 10}}, + {141.88034188034186, {8, 82, 12}}, + {141.9047619047619, {9, 148, 20}}, + {141.97530864197532, {8, 114, 17}}, + {142.0, {9, 70, 9}}, + {142.10526315789474, {1, 26, 18}}, + {142.1875, {7, 90, 15}}, + {142.2222222222222, {8, 95, 14}}, + {142.22222222222223, {8, 31, 4}}, + {142.30769230769232, {3, 36, 12}}, + {142.35294117647058, {9, 120, 16}}, + {142.42424242424244, {5, 46, 10}}, + {142.48366013071896, {8, 108, 16}}, + {142.5, {9, 56, 7}}, + {142.59259259259258, {8, 76, 11}}, + {142.5925925925926, {5, 76, 17}}, + {142.64705882352942, {7, 96, 16}}, + {142.66666666666666, {9, 106, 14}}, + {142.69005847953215, {8, 121, 18}}, + {142.85714285714286, {6, 24, 4}}, + {142.8571428571429, {6, 84, 16}}, + {143.0, {9, 142, 19}}, + {143.05555555555554, {8, 102, 15}}, + {143.07692307692307, {9, 92, 12}}, + {143.1372549019608, {5, 72, 16}}, + {143.1578947368421, {4, 67, 18}}, + {143.1818181818182, {7, 62, 10}}, + {143.20987654320987, {8, 57, 8}}, + {143.33333333333331, {8, 128, 19}}, + {143.33333333333334, {9, 42, 5}}, + {143.42105263157896, {7, 108, 18}}, + {143.43434343434345, {8, 70, 10}}, + {143.52941176470588, {4, 60, 16}}, + {143.5897435897436, {8, 83, 12}}, + {143.63636363636363, {9, 78, 10}}, + {143.70370370370372, {8, 96, 14}}, + {143.75, {3, 22, 7}}, + {143.79084967320262, {8, 109, 16}}, + {143.859649122807, {8, 122, 18}}, + {144.0, {4, 17, 4}}, + {144.11764705882354, {3, 48, 16}}, + {144.21052631578948, {9, 136, 18}}, + {144.23076923076923, {7, 74, 12}}, + {144.28571428571428, {9, 100, 13}}, + {144.3609022556391, {6, 95, 18}}, + {144.44444444444443, {8, 38, 5}}, + {144.44444444444446, {2, 12, 5}}, + {144.53781512605042, {6, 85, 16}}, + {144.6153846153846, {4, 46, 12}}, + {144.64285714285714, {7, 80, 13}}, + {144.7058823529412, {9, 122, 16}}, + {144.73684210526315, {3, 54, 18}}, + {144.76190476190476, {6, 75, 14}}, + {144.89795918367346, {6, 70, 13}}, + {145.0, {7, 28, 4}}, + {145.02923976608187, {8, 123, 18}}, + {145.05494505494505, {6, 65, 12}}, + {145.09803921568627, {8, 110, 16}}, + {145.0980392156863, {2, 36, 16}}, + {145.1851851851852, {8, 97, 14}}, + {145.23809523809524, {6, 60, 11}}, + {145.26315789473685, {4, 68, 18}}, + {145.2991452991453, {8, 84, 12}}, + {145.3125, {7, 92, 15}}, + {145.33333333333334, {9, 108, 14}}, + {145.45454545454547, {0, 7, 10}}, + {145.55555555555554, {9, 130, 17}}, + {145.58823529411765, {7, 98, 16}}, + {145.61403508771932, {5, 82, 18}}, + {145.679012345679, {8, 58, 8}}, + {145.71428571428572, {9, 50, 6}}, + {145.83333333333331, {8, 104, 15}}, + {145.83333333333334, {7, 34, 5}}, + {145.86466165413535, {6, 96, 18}}, + {145.88235294117646, {4, 61, 16}}, + {146.0, {9, 72, 9}}, + {146.03174603174602, {8, 45, 6}}, + {146.03174603174605, {6, 45, 8}}, + {146.05263157894737, {7, 110, 18}}, + {146.15384615384616, {1, 18, 12}}, + {146.19883040935673, {8, 124, 18}}, + {146.21848739495798, {6, 86, 16}}, + {146.25, {9, 116, 15}}, + {146.29629629629628, {8, 78, 11}}, + {146.2962962962963, {5, 78, 17}}, + {146.31578947368422, {9, 138, 18}}, + {146.40522875816993, {8, 111, 16}}, + {146.42857142857142, {7, 40, 6}}, + {146.42857142857144, {6, 40, 7}}, + {146.66666666666666, {8, 32, 4}}, + {146.66666666666669, {2, 10, 4}}, + {146.875, {7, 46, 7}}, + {146.91358024691357, {8, 118, 17}}, + {146.9387755102041, {6, 35, 6}}, + {147.0, {9, 146, 19}}, + {147.008547008547, {8, 85, 12}}, + {147.05882352941177, {1, 24, 16}}, + {147.14285714285714, {9, 102, 13}}, + {147.14285714285717, {6, 102, 19}}, + {147.22222222222223, {8, 52, 7}}, + {147.25274725274727, {6, 66, 12}}, + {147.27272727272728, {9, 80, 10}}, + {147.3684210526316, {0, 13, 18}}, + {147.47474747474746, {8, 72, 10}}, + {147.5, {9, 58, 7}}, + {147.61904761904762, {6, 30, 5}}, + {147.61904761904765, {5, 30, 6}}, + {147.69230769230768, {4, 47, 12}}, + {147.71241830065358, {8, 112, 16}}, + {147.72727272727272, {7, 64, 10}}, + {147.77777777777777, {9, 132, 17}}, + {147.89915966386553, {6, 87, 16}}, + {147.91666666666666, {7, 70, 11}}, + {147.91666666666669, {5, 70, 15}}, + {148.0, {9, 36, 4}}, + {148.05194805194807, {6, 56, 10}}, + {148.07692307692307, {7, 76, 12}}, + {148.14814814814815, {8, 39, 5}}, + {148.21428571428572, {7, 82, 13}}, + {148.23529411764707, {4, 62, 16}}, + {148.33333333333334, {9, 88, 11}}, + {148.42105263157896, {9, 140, 18}}, + {148.4375, {7, 94, 15}}, + {148.4848484848485, {5, 48, 10}}, + {148.52941176470588, {7, 100, 16}}, + {148.53801169590642, {8, 126, 18}}, + {148.57142857142858, {6, 25, 4}}, + {148.61111111111111, {8, 106, 15}}, + {148.68421052631578, {7, 112, 18}}, + {148.7179487179487, {8, 86, 12}}, + {148.71794871794873, {2, 28, 12}}, + {148.75, {9, 118, 15}}, + {148.87218045112783, {6, 98, 18}}, + {148.88888888888889, {9, 66, 8}}, + {148.9795918367347, {6, 72, 13}}, + {149.0, {9, 148, 19}}, + {149.01960784313724, {8, 113, 16}}, + {149.01960784313727, {2, 37, 16}}, + {149.0909090909091, {4, 40, 10}}, + {149.12280701754386, {5, 84, 18}}, + {149.2063492063492, {8, 46, 6}}, + {149.20634920634922, {6, 46, 8}}, + {149.23076923076923, {9, 96, 12}}, + {149.33333333333334, {4, 55, 14}}, + {149.3827160493827, {8, 120, 17}}, + {149.41176470588235, {9, 126, 16}}, + {149.45054945054946, {6, 67, 12}}, + {149.47368421052633, {4, 70, 18}}, + {149.49494949494948, {8, 73, 10}}, + {149.57983193277312, {6, 88, 16}}, + {149.62962962962962, {8, 100, 14}}, + {149.70760233918128, {8, 127, 18}}, + {150.0, {0, 2, 3}}, + {150.00000000000003, {5, 26, 5}}, + {150.32679738562092, {8, 114, 16}}, + {150.37593984962407, {6, 99, 18}}, + {150.4273504273504, {8, 87, 12}}, + {150.47619047619048, {6, 78, 14}}, + {150.52631578947367, {9, 142, 18}}, + {150.58823529411765, {4, 63, 16}}, + {150.61728395061726, {8, 60, 8}}, + {150.64935064935068, {6, 57, 10}}, + {150.66666666666666, {9, 112, 14}}, + {150.76923076923077, {4, 48, 12}}, + {150.79365079365078, {8, 94, 13}}, + {150.87719298245614, {8, 128, 18}}, + {150.87719298245617, {2, 42, 18}}, + {150.9090909090909, {9, 82, 10}}, + {150.98039215686276, {5, 76, 16}}, + {151.0204081632653, {6, 36, 6}}, + {151.11111111111111, {8, 33, 4}}, + {151.11111111111114, {2, 33, 14}}, + {151.25, {9, 120, 15}}, + {151.26050420168067, {6, 89, 16}}, + {151.2820512820513, {5, 58, 12}}, + {151.31578947368422, {7, 114, 18}}, + {151.38888888888889, {8, 108, 15}}, + {151.42857142857142, {9, 52, 6}}, + {151.42857142857144, {6, 52, 9}}, + {151.47058823529412, {7, 102, 16}}, + {151.5151515151515, {8, 74, 10}}, + {151.51515151515153, {2, 24, 10}}, + {151.5625, {7, 96, 15}}, + {151.57894736842104, {4, 71, 18}}, + {151.63398692810458, {8, 115, 16}}, + {151.64835164835165, {6, 68, 12}}, + {151.66666666666666, {9, 90, 11}}, + {151.76470588235293, {9, 128, 16}}, + {151.78571428571428, {7, 84, 13}}, + {151.7857142857143, {6, 84, 15}}, + {151.85185185185185, {8, 40, 5}}, + {151.87969924812032, {6, 100, 18}}, + {151.92307692307693, {7, 78, 12}}, + {152.0, {4, 18, 4}}, + {152.046783625731, {8, 129, 18}}, + {152.08333333333334, {7, 72, 11}}, + {152.13675213675214, {8, 88, 12}}, + {152.22222222222223, {9, 136, 17}}, + {152.27272727272728, {7, 66, 10}}, + {152.30769230769232, {9, 98, 12}}, + {152.38095238095235, {8, 47, 6}}, + {152.38095238095238, {6, 31, 5}}, + {152.3809523809524, {6, 47, 8}}, + {152.5, {9, 60, 7}}, + {152.59259259259258, {8, 102, 14}}, + {152.6315789473684, {1, 28, 18}}, + {152.72727272727272, {4, 41, 10}}, + {152.77777777777777, {8, 54, 7}}, + {152.7777777777778, {5, 54, 11}}, + {152.85714285714286, {9, 106, 13}}, + {152.94117647058823, {0, 12, 16}}, + {153.06122448979593, {6, 74, 13}}, + {153.08641975308643, {8, 61, 8}}, + {153.125, {7, 48, 7}}, + {153.21637426900583, {8, 130, 18}}, + {153.24675324675326, {6, 58, 10}}, + {153.33333333333331, {8, 68, 9}}, + {153.33333333333334, {5, 22, 4}}, + {153.38345864661653, {6, 101, 18}}, + {153.53535353535355, {8, 75, 10}}, + {153.57142857142858, {7, 42, 6}}, + {153.68421052631578, {4, 72, 18}}, + {153.7037037037037, {8, 82, 11}}, + {153.70370370370372, {5, 82, 17}}, + {153.75, {9, 122, 15}}, + {153.84615384615384, {0, 9, 12}}, + {153.84615384615387, {2, 29, 12}}, + {153.94736842105263, {7, 116, 18}}, + {153.96825396825398, {8, 96, 13}}, + {154.0, {9, 76, 9}}, + {154.07407407407405, {8, 103, 14}}, + {154.11764705882354, {9, 130, 16}}, + {154.16666666666666, {7, 36, 5}}, + {154.16666666666669, {5, 36, 7}}, + {154.2483660130719, {8, 117, 16}}, + {154.28571428571428, {6, 26, 4}}, + {154.320987654321, {8, 124, 17}}, + {154.38596491228068, {8, 131, 18}}, + {154.3859649122807, {2, 43, 18}}, + {154.41176470588235, {7, 104, 16}}, + {154.44444444444446, {9, 138, 17}}, + {154.54545454545453, {1, 16, 10}}, + {154.54545454545456, {5, 50, 10}}, + {154.62184873949582, {6, 91, 16}}, + {154.66666666666666, {4, 57, 14}}, + {154.6875, {7, 98, 15}}, + {154.73684210526315, {9, 146, 18}}, + {154.7619047619048, {6, 64, 11}}, + {154.8872180451128, {6, 102, 18}}, + {154.90196078431373, {5, 78, 16}}, + {155.0, {9, 30, 3}}, + {155.10204081632654, {6, 37, 6}}, + {155.26315789473685, {3, 58, 18}}, + {155.2941176470588, {4, 65, 16}}, + {155.35714285714286, {7, 86, 13}}, + {155.3846153846154, {9, 100, 12}}, + {155.55555555555554, {8, 27, 3}}, + {155.55555555555557, {2, 13, 5}}, + {155.71428571428572, {9, 108, 13}}, + {155.76923076923077, {7, 80, 12}}, + {155.78947368421052, {4, 73, 18}}, + {155.84415584415586, {6, 59, 10}}, + {155.88235294117646, {3, 52, 16}}, + {156.0, {9, 38, 4}}, + {156.04395604395606, {6, 70, 12}}, + {156.140350877193, {5, 88, 18}}, + {156.1904761904762, {6, 81, 14}}, + {156.25, {7, 24, 3}}, + {156.30252100840337, {6, 92, 16}}, + {156.36363636363637, {4, 42, 10}}, + {156.39097744360902, {6, 103, 18}}, + {156.4102564102564, {5, 60, 12}}, + {156.47058823529412, {9, 132, 16}}, + {156.57894736842104, {7, 118, 18}}, + {156.66666666666666, {9, 46, 5}}, + {156.66666666666669, {5, 46, 9}}, + {156.7251461988304, {8, 133, 18}}, + {156.79012345679013, {8, 126, 17}}, + {156.8181818181818, {7, 68, 10}}, + {156.8421052631579, {9, 148, 18}}, + {156.8627450980392, {8, 119, 16}}, + {156.86274509803923, {2, 39, 16}}, + {156.92307692307693, {4, 50, 12}}, + {156.94444444444443, {8, 112, 15}}, + {156.94444444444446, {7, 112, 17}}, + {157.03703703703704, {8, 105, 14}}, + {157.14285714285714, {6, 21, 3}}, + {157.14285714285717, {6, 54, 9}}, + {157.26495726495725, {8, 91, 12}}, + {157.33333333333334, {4, 58, 14}}, + {157.35294117647058, {7, 106, 16}}, + {157.40740740740742, {8, 84, 11}}, + {157.5, {9, 62, 7}}, + {157.57575757575756, {8, 77, 10}}, + {157.5757575757576, {2, 25, 10}}, + {157.64705882352942, {4, 66, 16}}, + {157.69230769230768, {3, 40, 12}}, + {157.77777777777777, {9, 70, 8}}, + {157.7777777777778, {5, 70, 14}}, + {157.8125, {7, 100, 15}}, + {157.89473684210526, {0, 14, 18}}, + {157.98319327731093, {6, 93, 16}}, + {158.0, {9, 78, 9}}, + {158.02469135802468, {8, 63, 8}}, + {158.0952380952381, {6, 82, 14}}, + {158.16993464052285, {8, 120, 16}}, + {158.1818181818182, {9, 86, 10}}, + {158.24175824175825, {6, 71, 12}}, + {158.33333333333331, {8, 56, 7}}, + {158.33333333333334, {5, 18, 3}}, + {158.44155844155844, {6, 60, 10}}, + {158.46153846153845, {9, 102, 12}}, + {158.51851851851853, {8, 106, 14}}, + {158.57142857142858, {9, 110, 13}}, + {158.66666666666666, {9, 118, 14}}, + {158.73015873015873, {8, 49, 6}}, + {158.75, {9, 126, 15}}, + {158.8235294117647, {1, 26, 16}}, + {158.88888888888889, {9, 142, 17}}, + {158.92857142857142, {7, 88, 13}}, + {158.92857142857144, {6, 88, 15}}, + {158.97435897435895, {8, 92, 12}}, + {158.974358974359, {2, 30, 12}}, + {159.0909090909091, {3, 34, 10}}, + {159.18367346938777, {6, 38, 6}}, + {159.25925925925924, {8, 128, 17}}, + {159.25925925925927, {8, 42, 5}}, + {159.375, {7, 50, 7}}, + {159.4771241830065, {8, 121, 16}}, + {159.52380952380955, {6, 66, 11}}, + {159.59595959595958, {8, 78, 10}}, + {159.6153846153846, {7, 82, 12}}, + {159.6638655462185, {6, 94, 16}}, + {159.72222222222223, {8, 114, 15}}, + {160.0, {4, 15, 3}}, + {160.2941176470588, {7, 108, 16}}, + {160.3174603174603, {8, 100, 13}}, + {160.31746031746033, {6, 100, 17}}, + {160.41666666666666, {7, 76, 11}}, + {160.41666666666669, {5, 76, 15}}, + {160.43956043956044, {6, 72, 12}}, + {160.49382716049382, {8, 64, 8}}, + {160.60606060606062, {5, 52, 10}}, + {160.68376068376068, {8, 93, 12}}, + {160.71428571428572, {7, 44, 6}}, + {160.78431372549016, {8, 122, 16}}, + {160.7843137254902, {2, 40, 16}}, + {160.9375, {7, 102, 15}}, + {161.03896103896105, {6, 61, 10}}, + {161.11111111111111, {8, 28, 3}}, + {161.1764705882353, {9, 136, 16}}, + {161.22448979591837, {6, 78, 13}}, + {161.25, {9, 128, 15}}, + {161.33333333333334, {9, 120, 14}}, + {161.34453781512607, {6, 95, 16}}, + {161.36363636363637, {7, 70, 10}}, + {161.42857142857142, {9, 112, 13}}, + {161.48148148148147, {8, 108, 14}}, + {161.53846153846155, {1, 20, 12}}, + {161.61616161616163, {8, 79, 10}}, + {161.66666666666666, {9, 96, 11}}, + {161.72839506172838, {8, 130, 17}}, + {161.76470588235293, {3, 54, 16}}, + {161.8181818181818, {9, 88, 10}}, + {161.9047619047619, {6, 33, 5}}, + {161.90476190476193, {2, 16, 6}}, + {162.0, {9, 80, 9}}, + {162.09150326797385, {8, 123, 16}}, + {162.22222222222223, {9, 72, 8}}, + {162.35294117647058, {4, 68, 16}}, + {162.39316239316238, {8, 94, 12}}, + {162.5, {3, 12, 3}}, + {162.63736263736263, {6, 73, 12}}, + {162.66666666666666, {4, 60, 14}}, + {162.7450980392157, {5, 82, 16}}, + {162.85714285714286, {9, 56, 6}}, + {162.96296296296293, {8, 65, 8}}, + {162.96296296296296, {8, 43, 5}}, + {163.02521008403363, {6, 96, 16}}, + {163.07692307692307, {4, 52, 12}}, + {163.23529411764707, {7, 110, 16}}, + {163.26530612244898, {6, 39, 6}}, + {163.33333333333334, {9, 48, 5}}, + {163.39869281045753, {8, 124, 16}}, + {163.46153846153845, {7, 84, 12}}, + {163.49206349206347, {8, 102, 13}}, + {163.4920634920635, {6, 102, 17}}, + {163.52941176470588, {9, 138, 16}}, + {163.63636363636363, {0, 8, 10}}, + {163.63636363636365, {2, 26, 10}}, + {163.75, {9, 130, 15}}, + {163.80952380952382, {6, 85, 14}}, + {163.88888888888889, {8, 58, 7}}, + {164.0, {9, 40, 4}}, + {164.0625, {7, 104, 15}}, + {164.1025641025641, {8, 95, 12}}, + {164.10256410256412, {2, 31, 12}}, + {164.19753086419755, {8, 132, 17}}, + {164.28571428571428, {3, 22, 6}}, + {164.2857142857143, {6, 22, 3}}, + {164.44444444444443, {8, 36, 4}}, + {164.44444444444446, {4, 36, 8}}, + {164.58333333333334, {7, 78, 11}}, + {164.6153846153846, {9, 106, 12}}, + {164.7058823529412, {0, 13, 16}}, + {164.8148148148148, {8, 88, 11}}, + {164.81481481481484, {5, 88, 17}}, + {164.83516483516485, {6, 74, 12}}, + {165.0, {9, 32, 3}}, + {165.07936507936506, {8, 51, 6}}, + {165.0793650793651, {6, 51, 8}}, + {165.27777777777777, {8, 118, 15}}, + {165.30612244897958, {6, 80, 13}}, + {165.33333333333334, {4, 61, 14}}, + {165.3846153846154, {3, 42, 12}}, + {165.4320987654321, {8, 66, 8}}, + {165.45454545454547, {9, 90, 10}}, + {165.55555555555554, {9, 148, 17}}, + {165.625, {7, 52, 7}}, + {165.65656565656565, {8, 81, 10}}, + {165.71428571428572, {6, 28, 4}}, + {165.81196581196582, {8, 96, 12}}, + {165.88235294117646, {9, 140, 16}}, + {165.9090909090909, {7, 72, 10}}, + {165.92592592592592, {8, 111, 14}}, + {166.0, {9, 82, 9}}, + {166.01307189542484, {8, 126, 16}}, + {166.07142857142858, {7, 92, 13}}, + {166.15384615384616, {4, 53, 12}}, + {166.1764705882353, {7, 112, 16}}, + {166.23376623376623, {6, 63, 10}}, + {166.25, {9, 132, 15}}, + {166.38655462184875, {6, 98, 16}}, + {166.66666666666666, {8, 29, 3}}, + {166.66666666666669, {2, 9, 3}}, + {167.03296703296704, {6, 75, 12}}, + {167.05882352941177, {4, 70, 16}}, + {167.14285714285714, {9, 116, 13}}, + {167.1875, {7, 106, 15}}, + {167.27272727272728, {4, 45, 10}}, + {167.30769230769232, {7, 86, 12}}, + {167.3202614379085, {8, 127, 16}}, + {167.3469387755102, {6, 40, 6}}, + {167.4074074074074, {8, 112, 14}}, + {167.5, {9, 66, 7}}, + {167.52136752136752, {8, 97, 12}}, + {167.61904761904762, {6, 87, 14}}, + {167.64705882352942, {3, 56, 16}}, + {167.67676767676767, {8, 82, 10}}, + {167.69230769230768, {9, 108, 12}}, + {167.85714285714286, {7, 46, 6}}, + {167.90123456790124, {8, 67, 8}}, + {168.0, {4, 20, 4}}, + {168.05555555555554, {8, 120, 15}}, + {168.0672268907563, {6, 99, 16}}, + {168.1818181818182, {3, 36, 10}}, + {168.23529411764707, {9, 142, 16}}, + {168.25396825396825, {8, 52, 6}}, + {168.25396825396828, {6, 52, 8}}, + {168.33333333333334, {9, 100, 11}}, + {168.5185185185185, {8, 90, 11}}, + {168.57142857142858, {9, 58, 6}}, + {168.62745098039215, {8, 128, 16}}, + {168.62745098039218, {2, 42, 16}}, + {168.75, {7, 26, 3}}, + {168.83116883116884, {6, 64, 10}}, + {168.88888888888886, {8, 113, 14}}, + {168.88888888888889, {8, 37, 4}}, + {169.04761904761907, {6, 70, 11}}, + {169.0909090909091, {9, 92, 10}}, + {169.11764705882354, {7, 114, 16}}, + {169.23076923076923, {0, 10, 12}}, + {169.33333333333334, {9, 126, 14}}, + {169.3877551020408, {6, 82, 13}}, + {169.41176470588235, {4, 71, 16}}, + {169.44444444444443, {8, 60, 7}}, + {169.44444444444446, {7, 60, 8}}, + {169.52380952380955, {6, 88, 14}}, + {169.64285714285714, {7, 94, 13}}, + {169.6969696969697, {8, 83, 10}}, + {169.69696969696972, {2, 27, 10}}, + {169.74789915966386, {6, 100, 16}}, + {169.84126984126985, {8, 106, 13}}, + {169.9346405228758, {8, 129, 16}}, + {170.0, {4, 16, 3}}, + {170.00000000000003, {5, 50, 9}}, + {170.3125, {7, 108, 15}}, + {170.37037037037035, {8, 45, 5}}, + {170.37037037037038, {2, 22, 8}}, + {170.45454545454547, {7, 74, 10}}, + {170.58823529411765, {1, 28, 16}}, + {170.66666666666666, {4, 63, 14}}, + {170.76923076923077, {9, 110, 12}}, + {170.83333333333331, {8, 122, 15}}, + {170.83333333333334, {7, 40, 5}}, + {170.9090909090909, {4, 46, 10}}, + {170.94017094017093, {8, 99, 12}}, + {171.11111111111111, {9, 76, 8}}, + {171.11111111111114, {5, 76, 14}}, + {171.15384615384616, {7, 88, 12}}, + {171.24183006535947, {8, 130, 16}}, + {171.25, {9, 136, 15}}, + {171.42857142857142, {0, 5, 6}}, + {171.42857142857144, {6, 23, 3}}, + {171.66666666666666, {9, 102, 11}}, + {171.7171717171717, {8, 84, 10}}, + {171.76470588235293, {4, 72, 16}}, + {171.7948717948718, {5, 66, 12}}, + {171.85185185185185, {8, 115, 14}}, + {171.875, {7, 54, 7}}, + {172.0, {9, 42, 4}}, + {172.05882352941177, {7, 116, 16}}, + {172.2222222222222, {8, 92, 11}}, + {172.22222222222223, {8, 30, 3}}, + {172.22222222222226, {5, 30, 5}}, + {172.30769230769232, {4, 55, 12}}, + {172.5, {9, 68, 7}}, + {172.54901960784312, {8, 131, 16}}, + {172.54901960784315, {2, 43, 16}}, + {172.64957264957263, {8, 100, 12}}, + {172.72727272727272, {1, 18, 10}}, + {172.72727272727275, {5, 56, 10}}, + {172.8395061728395, {8, 69, 8}}, + {172.85714285714286, {9, 120, 13}}, + {172.91666666666666, {7, 82, 11}}, + {172.91666666666669, {5, 82, 15}}, + {172.94117647058823, {9, 146, 16}}, + {173.015873015873, {8, 108, 13}}, + {173.07692307692307, {3, 44, 12}}, + {173.109243697479, {6, 102, 16}}, + {173.21428571428572, {7, 96, 13}}, + {173.33333333333331, {8, 38, 4}}, + {173.33333333333334, {2, 12, 4}}, + {173.4375, {7, 110, 15}}, + {173.46938775510208, {6, 84, 13}}, + {173.52941176470588, {3, 58, 16}}, + {173.61111111111111, {8, 124, 15}}, + {173.62637362637363, {6, 78, 12}}, + {173.73737373737373, {8, 85, 10}}, + {173.75, {9, 138, 15}}, + {173.80952380952382, {6, 72, 11}}, + {173.84615384615384, {9, 112, 12}}, + {173.8562091503268, {8, 132, 16}}, + {174.0, {9, 86, 9}}, + {174.02597402597405, {6, 66, 10}}, + {174.07407407407405, {8, 46, 5}}, + {174.07407407407408, {5, 46, 8}}, + {174.11764705882354, {4, 73, 16}}, + {174.28571428571428, {9, 60, 6}}, + {174.35897435897434, {8, 101, 12}}, + {174.3589743589744, {2, 33, 12}}, + {174.50980392156865, {5, 88, 16}}, + {174.54545454545453, {4, 47, 10}}, + {174.6031746031746, {8, 54, 6}}, + {174.66666666666666, {9, 130, 14}}, + {174.78991596638656, {6, 103, 16}}, + {174.8148148148148, {8, 117, 14}}, + {175.0, {1, 6, 3}}, + {175.16339869281046, {8, 133, 16}}, + {175.23809523809527, {6, 91, 14}}, + {175.2941176470588, {9, 148, 16}}, + {175.30864197530866, {8, 70, 8}}, + {175.3846153846154, {4, 56, 12}}, + {175.51020408163268, {6, 42, 6}}, + {175.55555555555554, {9, 78, 8}}, + {175.55555555555557, {5, 78, 14}}, + {175.71428571428572, {9, 122, 13}}, + {175.75757575757575, {8, 86, 10}}, + {175.75757575757578, {2, 28, 10}}, + {175.82417582417582, {6, 79, 12}}, + {175.9259259259259, {8, 94, 11}}, + {176.0, {4, 21, 4}}, + {176.06837606837604, {8, 102, 12}}, + {176.19047619047618, {6, 36, 5}}, + {176.1904761904762, {5, 36, 6}}, + {176.25, {9, 140, 15}}, + {176.29629629629628, {8, 118, 14}}, + {176.36363636363637, {9, 96, 10}}, + {176.38888888888889, {8, 126, 15}}, + {176.47058823529412, {0, 14, 16}}, + {176.5625, {7, 112, 15}}, + {176.62337662337663, {6, 67, 10}}, + {176.66666666666666, {9, 52, 5}}, + {176.66666666666669, {5, 52, 9}}, + {176.78571428571428, {7, 98, 13}}, + {176.7857142857143, {6, 98, 15}}, + {176.92307692307693, {1, 22, 12}}, + {177.08333333333334, {7, 84, 11}}, + {177.14285714285714, {4, 30, 6}}, + {177.14285714285717, {6, 30, 4}}, + {177.27272727272728, {3, 38, 10}}, + {177.33333333333334, {9, 132, 14}}, + {177.5, {9, 70, 7}}, + {177.55102040816328, {6, 86, 13}}, + {177.77777777777774, {8, 47, 5}}, + {177.77777777777777, {8, 31, 3}}, + {177.7777777777778, {2, 15, 5}}, + {178.0, {9, 88, 9}}, + {178.02197802197801, {6, 80, 12}}, + {178.125, {7, 56, 7}}, + {178.1818181818182, {4, 48, 10}}, + {178.33333333333334, {9, 106, 11}}, + {178.46153846153845, {4, 57, 12}}, + {178.57142857142858, {6, 24, 3}}, + {178.66666666666666, {4, 66, 14}}, + {178.75, {9, 142, 15}}, + {178.78787878787878, {5, 58, 10}}, + {178.84615384615384, {7, 92, 12}}, + {179.04761904761907, {6, 93, 14}}, + {179.16666666666666, {7, 42, 5}}, + {179.16666666666669, {5, 42, 7}}, + {179.22077922077924, {6, 68, 10}}, + {179.25925925925924, {8, 120, 14}}, + {179.36507936507934, {8, 112, 13}}, + {179.48717948717947, {8, 104, 12}}, + {179.4871794871795, {2, 34, 12}}, + {179.54545454545453, {7, 78, 10}}, + {179.59183673469389, {6, 43, 6}}, + {179.62962962962965, {8, 96, 11}}, + {179.6875, {7, 114, 15}}, + {179.7979797979798, {8, 88, 10}}, + {180.0, {4, 17, 3}}, + {180.00000000000003, {5, 26, 4}}, + {180.21978021978023, {6, 81, 12}}, + {180.2469135802469, {8, 72, 8}}, + {180.35714285714286, {7, 100, 13}}, + {180.55555555555554, {8, 64, 7}}, + {180.55555555555557, {5, 64, 11}}, + {180.74074074074073, {8, 121, 14}}, + {180.76923076923077, {3, 46, 12}}, + {180.95238095238093, {8, 56, 6}}, + {180.95238095238096, {6, 37, 5}}, + {181.1965811965812, {8, 105, 12}}, + {181.25, {7, 28, 3}}, + {181.33333333333334, {4, 67, 14}}, + {181.42857142857142, {9, 126, 13}}, + {181.4814814814815, {8, 48, 5}}, + {181.53846153846155, {4, 58, 12}}, + {181.63265306122452, {6, 88, 13}}, + {181.66666666666666, {9, 108, 11}}, + {181.8181818181818, {0, 9, 10}}, + {181.81818181818184, {2, 29, 10}}, + {181.94444444444443, {8, 130, 15}}, + {182.0, {9, 90, 9}}, + {182.05128205128207, {5, 70, 12}}, + {182.14285714285714, {7, 50, 6}}, + {182.2222222222222, {8, 122, 14}}, + {182.22222222222223, {8, 40, 4}}, + {182.41758241758242, {6, 82, 12}}, + {182.5, {9, 72, 7}}, + {182.53968253968256, {8, 114, 13}}, + {182.66666666666666, {9, 136, 14}}, + {182.69230769230768, {7, 94, 12}}, + {182.71604938271605, {8, 73, 8}}, + {182.8125, {7, 116, 15}}, + {182.85714285714286, {6, 31, 4}}, + {182.9059829059829, {8, 106, 12}}, + {183.07692307692307, {9, 118, 12}}, + {183.33333333333331, {8, 32, 3}}, + {183.33333333333334, {2, 10, 3}}, + {183.63636363636363, {9, 100, 10}}, + {183.67346938775512, {6, 44, 6}}, + {183.70370370370372, {8, 123, 14}}, + {183.75, {9, 146, 15}}, + {183.83838383838383, {8, 90, 10}}, + {183.92857142857142, {7, 102, 13}}, + {183.92857142857144, {6, 102, 15}}, + {184.0, {4, 22, 4}}, + {184.0909090909091, {7, 80, 10}}, + {184.12698412698413, {8, 57, 6}}, + {184.12698412698415, {6, 57, 8}}, + {184.28571428571428, {9, 128, 13}}, + {184.375, {7, 58, 7}}, + {184.41558441558442, {6, 70, 10}}, + {184.44444444444443, {8, 82, 9}}, + {184.44444444444446, {9, 82, 8}}, + {184.6153846153846, {0, 11, 12}}, + {184.72222222222223, {8, 132, 15}}, + {184.76190476190476, {6, 96, 14}}, + {184.84848484848487, {5, 60, 10}}, + {185.0, {9, 36, 3}}, + {185.18518518518516, {8, 74, 8}}, + {185.1851851851852, {8, 49, 5}}, + {185.33333333333334, {9, 138, 14}}, + {185.41666666666666, {7, 88, 11}}, + {185.41666666666669, {5, 88, 15}}, + {185.45454545454547, {4, 50, 10}}, + {185.71428571428572, {6, 25, 3}}, + {185.71428571428575, {6, 38, 5}}, + {185.85858585858585, {8, 91, 10}}, + {185.9375, {7, 118, 15}}, + {186.0, {9, 92, 9}}, + {186.11111111111111, {8, 66, 7}}, + {186.15384615384616, {9, 120, 12}}, + {186.25, {9, 148, 15}}, + {186.32478632478632, {8, 108, 12}}, + {186.36363636363637, {3, 40, 10}}, + {186.53846153846155, {7, 96, 12}}, + {186.66666666666666, {8, 41, 4}}, + {186.66666666666669, {2, 13, 4}}, + {186.81318681318683, {6, 84, 12}}, + {187.01298701298703, {6, 71, 10}}, + {187.03703703703704, {8, 100, 11}}, + {187.14285714285714, {9, 130, 13}}, + {187.17948717948718, {5, 72, 12}}, + {187.27272727272728, {9, 102, 10}}, + {187.3015873015873, {8, 58, 6}}, + {187.30158730158732, {6, 58, 8}}, + {187.5, {3, 14, 3}}, + {187.65432098765433, {8, 75, 8}}, + {187.69230769230768, {4, 60, 12}}, + {187.75510204081635, {6, 45, 6}}, + {187.87878787878788, {8, 92, 10}}, + {187.8787878787879, {2, 30, 10}}, + {188.0, {9, 46, 4}}, + {188.03418803418802, {8, 109, 12}}, + {188.0952380952381, {6, 78, 11}}, + {188.14814814814815, {8, 126, 14}}, + {188.33333333333334, {9, 112, 11}}, + {188.46153846153845, {3, 48, 12}}, + {188.57142857142858, {6, 32, 4}}, + {188.63636363636363, {7, 82, 10}}, + {188.88888888888889, {8, 33, 3}}, + {188.8888888888889, {2, 16, 5}}, + {189.01098901098902, {6, 85, 12}}, + {189.0909090909091, {4, 51, 10}}, + {189.23076923076923, {9, 122, 12}}, + {189.28571428571428, {7, 52, 6}}, + {189.2857142857143, {6, 52, 7}}, + {189.33333333333334, {4, 70, 14}}, + {189.58333333333334, {7, 90, 11}}, + {189.6103896103896, {6, 72, 10}}, + {189.62962962962962, {8, 127, 14}}, + {189.74358974358972, {8, 110, 12}}, + {189.74358974358978, {2, 36, 12}}, + {189.79591836734696, {6, 92, 13}}, + {189.89898989898987, {8, 93, 10}}, + {190.0, {4, 18, 3}}, + {190.00000000000003, {5, 56, 9}}, + {190.12345679012344, {8, 76, 8}}, + {190.3846153846154, {7, 98, 12}}, + {190.47619047619045, {8, 59, 6}}, + {190.47619047619048, {6, 39, 5}}, + {190.4761904761905, {2, 19, 6}}, + {190.625, {7, 60, 7}}, + {190.66666666666666, {9, 142, 14}}, + {190.74074074074073, {8, 102, 11}}, + {190.76923076923077, {4, 61, 12}}, + {190.9090909090909, {1, 20, 10}}, + {191.07142857142858, {7, 106, 13}}, + {191.11111111111111, {8, 42, 4}}, + {191.11111111111114, {2, 42, 14}}, + {191.2087912087912, {6, 86, 12}}, + {191.42857142857142, {9, 66, 6}}, + {191.42857142857144, {6, 66, 9}}, + {191.45299145299143, {8, 111, 12}}, + {191.66666666666666, {3, 22, 5}}, + {191.66666666666669, {5, 22, 3}}, + {191.83673469387756, {6, 46, 6}}, + {191.9191919191919, {8, 94, 10}}, + {192.0, {4, 23, 4}}, + {192.06349206349205, {8, 120, 13}}, + {192.2077922077922, {6, 73, 10}}, + {192.30769230769232, {1, 24, 12}}, + {192.38095238095238, {6, 100, 14}}, + {192.5, {9, 76, 7}}, + {192.59259259259258, {8, 51, 5}}, + {192.5925925925926, {2, 25, 8}}, + {192.72727272727272, {4, 52, 10}}, + {192.85714285714286, {6, 26, 3}}, + {193.16239316239313, {8, 112, 12}}, + {193.1818181818182, {7, 84, 10}}, + {193.33333333333331, {8, 86, 9}}, + {193.33333333333334, {5, 28, 4}}, + {193.4065934065934, {6, 87, 12}}, + {193.65079365079364, {8, 60, 6}}, + {193.75, {7, 30, 3}}, + {193.84615384615384, {4, 62, 12}}, + {193.87755102040816, {6, 94, 13}}, + {193.9393939393939, {8, 95, 10}}, + {193.93939393939397, {2, 31, 10}}, + {194.0, {9, 96, 9}}, + {194.07407407407405, {8, 130, 14}}, + {194.23076923076923, {7, 100, 12}}, + {194.28571428571428, {6, 33, 4}}, + {194.44444444444443, {8, 34, 3}}, + {194.44444444444446, {5, 34, 5}}, + {194.54545454545453, {9, 106, 10}}, + {194.64285714285714, {7, 108, 13}}, + {194.66666666666666, {4, 72, 14}}, + {194.80519480519482, {6, 74, 10}}, + {194.87179487179486, {8, 113, 12}}, + {194.8717948717949, {2, 37, 12}}, + {195.0, {9, 38, 3}}, + {195.06172839506172, {8, 78, 8}}, + {195.2380952380952, {8, 122, 13}}, + {195.23809523809524, {5, 40, 6}}, + {195.23809523809527, {6, 40, 5}}, + {195.3846153846154, {9, 126, 12}}, + {195.45454545454547, {3, 42, 10}}, + {195.55555555555554, {8, 43, 4}}, + {195.55555555555557, {2, 43, 14}}, + {195.60439560439562, {6, 88, 12}}, + {195.71428571428572, {9, 136, 13}}, + {195.83333333333334, {7, 46, 5}}, + {195.9183673469388, {6, 47, 6}}, + {195.95959595959596, {8, 96, 10}}, + {196.0, {9, 48, 4}}, + {196.15384615384616, {3, 50, 12}}, + {196.1904761904762, {6, 102, 14}}, + {196.2962962962963, {8, 52, 5}}, + {196.36363636363637, {4, 53, 10}}, + {196.42857142857142, {7, 54, 6}}, + {196.42857142857144, {6, 54, 7}}, + {196.5811965811966, {8, 114, 12}}, + {196.66666666666666, {9, 58, 5}}, + {196.66666666666669, {5, 58, 9}}, + {196.82539682539684, {8, 61, 6}}, + {196.875, {7, 62, 7}}, + {196.92307692307693, {4, 63, 12}}, + {196.969696969697, {5, 64, 10}}, + {197.03703703703704, {8, 132, 14}}, + {197.14285714285714, {9, 68, 6}}, + {197.14285714285717, {6, 68, 9}}, + {197.22222222222223, {8, 70, 7}}, + {197.22222222222226, {5, 70, 11}}, + {197.33333333333334, {4, 73, 14}}, + {197.40259740259742, {6, 75, 10}}, + {197.43589743589746, {5, 76, 12}}, + {197.5, {9, 78, 7}}, + {197.53086419753086, {8, 79, 8}}, + {197.61904761904762, {6, 82, 11}}, + {197.61904761904765, {5, 82, 13}}, + {197.72727272727272, {7, 86, 10}}, + {197.77777777777777, {9, 88, 8}}, + {197.7777777777778, {5, 88, 14}}, + {197.8021978021978, {6, 89, 12}}, + {197.91666666666666, {7, 94, 11}}, + {197.9591836734694, {6, 96, 13}}, + {197.97979797979798, {8, 97, 10}}, + {198.0, {9, 98, 9}}, + {198.07692307692307, {7, 102, 12}}, + {198.0952380952381, {6, 103, 14}}, + {198.14814814814815, {8, 106, 11}}, + {198.1818181818182, {9, 108, 10}}, + {198.21428571428572, {7, 110, 13}}, + {198.2905982905983, {8, 115, 12}}, + {198.33333333333334, {9, 118, 11}}, + {198.4126984126984, {8, 124, 13}}, + {198.46153846153845, {9, 128, 12}}, + {198.51851851851853, {8, 133, 14}}, + {198.57142857142858, {9, 138, 13}}, + {198.66666666666666, {9, 148, 14}}, + {200.0, {0, 2, 2}}, + {200.00000000000003, {2, 14, 4}}, + {201.42857142857142, {9, 140, 13}}, + {201.53846153846155, {9, 130, 12}}, + {201.5873015873016, {8, 126, 13}}, + {201.66666666666666, {9, 120, 11}}, + {201.7094017094017, {8, 117, 12}}, + {201.78571428571428, {7, 112, 13}}, + {201.8181818181818, {9, 110, 10}}, + {201.85185185185185, {8, 108, 11}}, + {201.92307692307693, {7, 104, 12}}, + {202.0, {9, 100, 9}}, + {202.02020202020202, {8, 99, 10}}, + {202.04081632653063, {6, 98, 13}}, + {202.08333333333334, {7, 96, 11}}, + {202.19780219780222, {6, 91, 12}}, + {202.22222222222223, {9, 90, 8}}, + {202.27272727272728, {7, 88, 10}}, + {202.38095238095238, {5, 84, 13}}, + {202.3809523809524, {6, 84, 11}}, + {202.46913580246914, {8, 81, 8}}, + {202.5, {9, 80, 7}}, + {202.56410256410257, {5, 78, 12}}, + {202.59740259740263, {6, 77, 10}}, + {202.77777777777777, {8, 72, 7}}, + {202.7777777777778, {5, 72, 11}}, + {202.85714285714286, {9, 70, 6}}, + {203.03030303030303, {5, 66, 10}}, + {203.07692307692307, {4, 65, 12}}, + {203.125, {7, 64, 7}}, + {203.17460317460316, {8, 63, 6}}, + {203.1746031746032, {6, 63, 8}}, + {203.33333333333334, {9, 60, 5}}, + {203.4188034188034, {8, 118, 12}}, + {203.57142857142858, {7, 56, 6}}, + {203.63636363636363, {4, 55, 10}}, + {203.7037037037037, {8, 54, 5}}, + {203.70370370370372, {5, 54, 8}}, + {203.84615384615384, {3, 52, 12}}, + {204.0, {9, 50, 4}}, + {204.04040404040404, {8, 100, 10}}, + {204.08163265306123, {6, 49, 6}}, + {204.16666666666666, {7, 48, 5}}, + {204.16666666666669, {5, 48, 7}}, + {204.28571428571428, {9, 142, 13}}, + {204.3956043956044, {6, 92, 12}}, + {204.44444444444443, {8, 45, 4}}, + {204.44444444444446, {4, 45, 8}}, + {204.54545454545453, {3, 44, 10}}, + {204.6153846153846, {9, 132, 12}}, + {204.76190476190476, {8, 128, 13}}, + {204.7619047619048, {6, 42, 5}}, + {204.93827160493825, {8, 82, 8}}, + {205.0, {9, 40, 3}}, + {205.1282051282051, {8, 119, 12}}, + {205.12820512820514, {2, 39, 12}}, + {205.1948051948052, {6, 78, 10}}, + {205.35714285714286, {7, 114, 13}}, + {205.45454545454547, {9, 112, 10}}, + {205.55555555555554, {8, 36, 3}}, + {205.55555555555557, {5, 36, 5}}, + {205.71428571428572, {6, 35, 4}}, + {205.76923076923077, {7, 106, 12}}, + {206.0, {9, 102, 9}}, + {206.06060606060603, {8, 101, 10}}, + {206.0606060606061, {2, 33, 10}}, + {206.12244897959184, {6, 100, 13}}, + {206.15384615384616, {4, 66, 12}}, + {206.25, {7, 32, 3}}, + {206.34920634920633, {8, 64, 6}}, + {206.34920634920638, {6, 64, 8}}, + {206.5934065934066, {6, 93, 12}}, + {206.66666666666666, {9, 30, 2}}, + {206.66666666666669, {5, 30, 4}}, + {206.8181818181818, {7, 90, 10}}, + {206.8376068376068, {8, 120, 12}}, + {207.14285714285714, {3, 28, 6}}, + {207.14285714285717, {6, 28, 3}}, + {207.27272727272728, {4, 56, 10}}, + {207.4074074074074, {8, 27, 2}}, + {207.40740740740742, {2, 27, 8}}, + {207.5, {9, 82, 7}}, + {207.69230769230768, {1, 26, 12}}, + {207.7922077922078, {6, 79, 10}}, + {207.93650793650792, {8, 130, 13}}, + {208.0, {4, 25, 4}}, + {208.08080808080805, {8, 102, 10}}, + {208.16326530612244, {6, 50, 6}}, + {208.33333333333331, {8, 74, 7}}, + {208.33333333333334, {7, 24, 2}}, + {208.54700854700852, {8, 121, 12}}, + {208.57142857142858, {9, 72, 6}}, + {208.7912087912088, {6, 94, 12}}, + {208.88888888888886, {8, 46, 4}}, + {208.88888888888889, {4, 46, 8}}, + {208.92857142857142, {7, 116, 13}}, + {209.0909090909091, {1, 22, 10}}, + {209.23076923076923, {4, 67, 12}}, + {209.25925925925924, {8, 112, 11}}, + {209.375, {7, 66, 7}}, + {209.5238095238095, {8, 65, 6}}, + {209.52380952380952, {6, 21, 2}}, + {209.52380952380955, {2, 21, 6}}, + {209.6153846153846, {7, 108, 12}}, + {209.87654320987656, {8, 84, 8}}, + {210.0, {4, 20, 3}}, + {210.10101010101008, {8, 103, 10}}, + {210.20408163265307, {6, 102, 13}}, + {210.25641025641022, {8, 122, 12}}, + {210.25641025641028, {2, 40, 12}}, + {210.3896103896104, {6, 80, 10}}, + {210.41666666666666, {7, 100, 11}}, + {210.71428571428572, {7, 58, 6}}, + {210.76923076923077, {9, 136, 12}}, + {210.9090909090909, {4, 57, 10}}, + {210.989010989011, {6, 95, 12}}, + {211.1111111111111, {8, 56, 5}}, + {211.11111111111111, {5, 18, 2}}, + {211.11111111111114, {5, 56, 8}}, + {211.36363636363637, {7, 92, 10}}, + {211.42857142857142, {6, 36, 4}}, + {211.53846153846155, {3, 54, 12}}, + {211.66666666666666, {9, 126, 11}}, + {211.90476190476193, {6, 88, 11}}, + {211.96581196581198, {8, 123, 12}}, + {212.0, {9, 52, 4}}, + {212.1212121212121, {8, 104, 10}}, + {212.12121212121212, {2, 34, 10}}, + {212.24489795918367, {6, 51, 6}}, + {212.30769230769232, {4, 68, 12}}, + {212.34567901234567, {8, 85, 8}}, + {212.5, {3, 16, 3}}, + {212.50000000000003, {5, 50, 7}}, + {212.6984126984127, {8, 66, 6}}, + {212.72727272727272, {9, 116, 10}}, + {212.82051282051285, {5, 82, 12}}, + {212.85714285714286, {9, 148, 13}}, + {212.96296296296296, {8, 114, 11}}, + {212.987012987013, {6, 81, 10}}, + {213.1868131868132, {6, 96, 12}}, + {213.33333333333331, {8, 47, 4}}, + {213.33333333333334, {4, 15, 2}}, + {213.46153846153845, {7, 110, 12}}, + {213.63636363636363, {3, 46, 10}}, + {213.67521367521368, {8, 124, 12}}, + {213.84615384615384, {9, 138, 12}}, + {213.88888888888889, {8, 76, 7}}, + {213.8888888888889, {5, 76, 11}}, + {214.0, {9, 106, 9}}, + {214.14141414141415, {8, 105, 10}}, + {214.28571428571428, {1, 14, 6}}, + {214.2857142857143, {6, 29, 3}}, + {214.54545454545453, {4, 58, 10}}, + {214.58333333333334, {7, 102, 11}}, + {214.8148148148148, {8, 28, 2}}, + {214.81481481481484, {2, 28, 8}}, + {215.0, {9, 42, 3}}, + {215.15151515151518, {5, 70, 10}}, + {215.3846153846154, {0, 13, 12}}, + {215.55555555555554, {9, 96, 8}}, + {215.55555555555557, {8, 96, 9}}, + {215.5844155844156, {6, 82, 10}}, + {215.625, {7, 68, 7}}, + {215.87301587301587, {8, 67, 6}}, + {215.9090909090909, {7, 94, 10}}, + {216.0, {4, 26, 4}}, + {216.16161616161617, {8, 106, 10}}, + {216.3265306122449, {6, 52, 6}}, + {216.36363636363637, {9, 118, 10}}, + {216.66666666666666, {3, 12, 2}}, + {216.66666666666669, {2, 12, 3}}, + {216.92307692307693, {9, 140, 12}}, + {217.0940170940171, {8, 126, 12}}, + {217.14285714285714, {4, 37, 6}}, + {217.14285714285717, {6, 37, 4}}, + {217.28395061728395, {8, 87, 8}}, + {217.30769230769232, {7, 112, 12}}, + {217.5, {9, 86, 7}}, + {217.5824175824176, {6, 98, 12}}, + {217.77777777777777, {8, 48, 4}}, + {217.85714285714286, {7, 60, 6}}, + {217.94871794871796, {5, 84, 12}}, + {218.0, {9, 108, 9}}, + {218.1818181818182, {0, 11, 10}}, + {218.33333333333334, {9, 130, 11}}, + {218.46153846153845, {4, 70, 12}}, + {218.5185185185185, {8, 58, 5}}, + {218.51851851851853, {5, 58, 8}}, + {218.75, {7, 34, 3}}, + {218.8034188034188, {8, 127, 12}}, + {219.04761904761904, {8, 68, 6}}, + {219.04761904761907, {6, 22, 2}}, + {219.23076923076923, {3, 56, 12}}, + {219.44444444444443, {8, 78, 7}}, + {219.44444444444446, {7, 78, 8}}, + {219.75308641975306, {8, 88, 8}}, + {219.7802197802198, {6, 99, 12}}, + {220.0, {9, 32, 2}}, + {220.2020202020202, {8, 108, 10}}, + {220.37037037037035, {8, 118, 11}}, + {220.40816326530611, {6, 53, 6}}, + {220.45454545454547, {7, 96, 10}}, + {220.5128205128205, {8, 128, 12}}, + {220.51282051282053, {2, 42, 12}}, + {220.77922077922082, {6, 84, 10}}, + {220.83333333333334, {7, 52, 5}}, + {221.15384615384616, {7, 114, 12}}, + {221.21212121212122, {5, 72, 10}}, + {221.42857142857142, {3, 30, 6}}, + {221.42857142857144, {6, 30, 3}}, + {221.53846153846155, {4, 71, 12}}, + {221.66666666666666, {9, 132, 11}}, + {221.8181818181818, {4, 60, 10}}, + {221.875, {7, 70, 7}}, + {221.97802197802199, {6, 100, 12}}, + {222.0, {9, 110, 9}}, + {222.2222222222222, {8, 29, 2}}, + {222.22222222222223, {8, 39, 3}}, + {222.22222222222226, {2, 9, 2}}, + {222.5, {9, 88, 7}}, + {222.72727272727272, {3, 48, 10}}, + {222.85714285714286, {4, 38, 6}}, + {222.8571428571429, {6, 38, 4}}, + {222.91666666666666, {7, 106, 11}}, + {223.07692307692307, {1, 28, 12}}, + {223.33333333333334, {9, 66, 5}}, + {223.3766233766234, {6, 85, 10}}, + {223.63636363636363, {9, 122, 10}}, + {223.80952380952382, {6, 46, 5}}, + {223.9316239316239, {8, 130, 12}}, + {224.0, {4, 27, 4}}, + {224.07407407407405, {8, 120, 11}}, + {224.17582417582418, {6, 101, 12}}, + {224.24242424242422, {8, 110, 10}}, + {224.24242424242428, {2, 36, 10}}, + {224.44444444444443, {8, 100, 9}}, + {224.44444444444446, {9, 100, 8}}, + {224.48979591836738, {6, 54, 6}}, + {224.6153846153846, {4, 72, 12}}, + {224.69135802469134, {8, 90, 8}}, + {225.0, {7, 26, 2}}, + {225.00000000000003, {5, 26, 3}}, + {225.3968253968254, {8, 70, 6}}, + {225.39682539682542, {6, 70, 8}}, + {225.45454545454547, {4, 61, 10}}, + {225.6410256410256, {8, 131, 12}}, + {225.64102564102566, {2, 43, 12}}, + {225.71428571428572, {9, 78, 6}}, + {225.9259259259259, {8, 60, 5}}, + {225.92592592592595, {5, 60, 8}}, + {225.97402597402598, {6, 86, 10}}, + {226.0, {9, 112, 9}}, + {226.15384615384616, {9, 146, 12}}, + {226.19047619047618, {6, 94, 11}}, + {226.26262626262624, {8, 111, 10}}, + {226.3736263736264, {6, 102, 12}}, + {226.66666666666666, {4, 16, 2}}, + {226.66666666666669, {2, 16, 4}}, + {226.92307692307693, {3, 58, 12}}, + {227.08333333333334, {7, 108, 11}}, + {227.16049382716048, {8, 91, 8}}, + {227.27272727272728, {1, 24, 10}}, + {227.35042735042737, {8, 132, 12}}, + {227.5, {9, 90, 7}}, + {227.69230769230768, {4, 73, 12}}, + {227.77777777777774, {8, 122, 11}}, + {227.77777777777777, {8, 40, 3}}, + {227.7777777777778, {5, 40, 5}}, + {228.0, {9, 56, 4}}, + {228.125, {7, 72, 7}}, + {228.20512820512823, {5, 88, 12}}, + {228.28282828282826, {8, 112, 10}}, + {228.33333333333334, {9, 136, 11}}, + {228.57142857142856, {6, 87, 10}}, + {228.57142857142858, {6, 23, 2}}, + {228.84615384615384, {7, 118, 12}}, + {228.88888888888886, {8, 102, 9}}, + {228.88888888888889, {9, 102, 8}}, + {229.05982905982907, {8, 133, 12}}, + {229.0909090909091, {4, 62, 10}}, + {229.16666666666666, {7, 54, 5}}, + {229.16666666666669, {5, 54, 7}}, + {229.23076923076923, {9, 148, 12}}, + {229.54545454545453, {7, 100, 10}}, + {229.62962962962962, {8, 92, 8}}, + {229.62962962962965, {8, 30, 2}}, + {229.62962962962968, {2, 30, 8}}, + {230.0, {4, 22, 3}}, + {230.30303030303028, {8, 113, 10}}, + {230.3030303030303, {2, 37, 10}}, + {230.55555555555554, {8, 82, 7}}, + {230.55555555555557, {5, 82, 11}}, + {230.76923076923077, {0, 14, 12}}, + {230.9090909090909, {9, 126, 10}}, + {230.95238095238096, {6, 96, 11}}, + {231.1111111111111, {8, 51, 4}}, + {231.11111111111111, {4, 51, 8}}, + {231.1688311688312, {6, 88, 10}}, + {231.25, {7, 36, 3}}, + {231.42857142857142, {9, 80, 6}}, + {231.4814814814815, {8, 124, 11}}, + {231.66666666666666, {9, 138, 11}}, + {231.74603174603175, {8, 72, 6}}, + {231.8181818181818, {3, 50, 10}}, + {232.0, {4, 28, 4}}, + {232.09876543209873, {8, 93, 8}}, + {232.14285714285714, {7, 64, 6}}, + {232.14285714285717, {6, 64, 7}}, + {232.32323232323233, {8, 114, 10}}, + {232.5, {9, 92, 7}}, + {232.65306122448982, {6, 56, 6}}, + {232.72727272727272, {4, 63, 10}}, + {233.33333333333331, {8, 41, 3}}, + {233.33333333333334, {1, 6, 2}}, + {233.33333333333337, {5, 76, 10}}, + {233.76623376623377, {6, 89, 10}}, + {234.0, {9, 116, 9}}, + {234.0909090909091, {7, 102, 10}}, + {234.28571428571428, {4, 40, 6}}, + {234.2857142857143, {6, 40, 4}}, + {234.34343434343435, {8, 115, 10}}, + {234.375, {7, 74, 7}}, + {234.54545454545453, {9, 128, 10}}, + {234.56790123456787, {8, 94, 8}}, + {234.9206349206349, {8, 73, 6}}, + {235.0, {9, 46, 3}}, + {235.1851851851852, {8, 126, 11}}, + {235.41666666666666, {7, 112, 11}}, + {235.55555555555554, {4, 52, 8}}, + {235.55555555555557, {8, 52, 4}}, + {235.71428571428572, {6, 32, 3}}, + {235.71428571428575, {6, 98, 11}}, + {236.0, {9, 58, 4}}, + {236.11111111111111, {8, 84, 7}}, + {236.36363636363637, {0, 12, 10}}, + {236.66666666666666, {9, 70, 5}}, + {236.66666666666669, {5, 70, 9}}, + {236.73469387755105, {6, 57, 6}}, + {237.037037037037, {8, 95, 8}}, + {237.03703703703704, {8, 31, 2}}, + {237.03703703703707, {2, 31, 8}}, + {237.14285714285714, {9, 82, 6}}, + {237.14285714285717, {6, 82, 9}}, + {237.5, {3, 18, 3}}, + {237.50000000000003, {5, 56, 7}}, + {237.77777777777777, {9, 106, 8}}, + {238.0, {9, 118, 9}}, + {238.09523809523807, {8, 74, 6}}, + {238.0952380952381, {6, 24, 2}}, + {238.09523809523813, {6, 74, 8}}, + {238.1818181818182, {9, 130, 10}}, + {238.33333333333334, {9, 142, 11}}, + {238.38383838383837, {8, 117, 10}}, + {238.63636363636363, {7, 104, 10}}, + {238.88888888888889, {8, 42, 3}}, + {238.8888888888889, {5, 42, 5}}, + {238.96103896103898, {6, 91, 10}}, + {239.28571428571428, {7, 66, 6}}, + {239.2857142857143, {6, 66, 7}}, + {239.3939393939394, {5, 78, 10}}, + {239.50617283950618, {8, 96, 8}}, + {239.58333333333334, {7, 114, 11}}, + {240.0, {4, 17, 2}}, + {240.4040404040404, {8, 118, 10}}, + {240.47619047619048, {6, 100, 11}}, + {240.625, {7, 76, 7}}, + {240.74074074074073, {8, 64, 5}}, + {240.74074074074076, {5, 64, 8}}, + {240.81632653061226, {6, 58, 6}}, + {240.9090909090909, {3, 52, 10}}, + {241.26984126984127, {8, 75, 6}}, + {241.2698412698413, {6, 75, 8}}, + {241.5584415584416, {6, 92, 10}}, + {241.66666666666666, {7, 28, 2}}, + {241.66666666666669, {5, 28, 3}}, + {241.8181818181818, {9, 132, 10}}, + {241.97530864197532, {8, 97, 8}}, + {242.0, {9, 120, 9}}, + {242.22222222222223, {9, 108, 8}}, + {242.4242424242424, {8, 119, 10}}, + {242.42424242424246, {2, 39, 10}}, + {242.5, {9, 96, 7}}, + {242.59259259259258, {8, 130, 11}}, + {242.85714285714286, {6, 33, 3}}, + {242.8571428571429, {5, 50, 6}}, + {243.1818181818182, {7, 106, 10}}, + {243.33333333333334, {9, 72, 5}}, + {243.63636363636363, {4, 66, 10}}, + {243.75, {7, 38, 3}}, + {244.0, {9, 60, 4}}, + {244.15584415584416, {6, 93, 10}}, + {244.44444444444443, {8, 32, 2}}, + {244.44444444444446, {2, 10, 2}}, + {244.8979591836735, {6, 59, 6}}, + {245.0, {9, 48, 3}}, + {245.23809523809527, {6, 102, 11}}, + {245.45454545454547, {1, 26, 10}}, + {245.71428571428572, {6, 42, 4}}, + {245.83333333333334, {7, 58, 5}}, + {246.0, {9, 122, 9}}, + {246.2962962962963, {8, 132, 11}}, + {246.42857142857142, {7, 68, 6}}, + {246.42857142857144, {6, 68, 7}}, + {246.46464646464645, {8, 121, 10}}, + {246.66666666666666, {9, 36, 2}}, + {246.66666666666669, {5, 36, 4}}, + {246.75324675324674, {6, 94, 10}}, + {246.875, {7, 78, 7}}, + {246.91358024691357, {8, 99, 8}}, + {247.2222222222222, {8, 88, 7}}, + {247.22222222222223, {7, 88, 8}}, + {247.22222222222226, {5, 88, 11}}, + {247.27272727272728, {4, 67, 10}}, + {247.5, {9, 98, 7}}, + {247.61904761904762, {6, 25, 2}}, + {247.61904761904765, {2, 25, 6}}, + {247.72727272727272, {7, 108, 10}}, + {247.91666666666666, {7, 118, 11}}, + {248.0, {4, 30, 4}}, + {248.14814814814815, {8, 66, 5}}, + {248.33333333333334, {9, 148, 11}}, + {248.48484848484847, {8, 122, 10}}, + {248.4848484848485, {2, 40, 10}}, + {248.57142857142858, {9, 86, 6}}, + {248.88888888888886, {8, 55, 4}}, + {248.88888888888889, {4, 55, 8}}, + {248.9795918367347, {6, 60, 6}}, + {249.0909090909091, {9, 136, 10}}, + {249.35064935064938, {6, 95, 10}}, + {249.3827160493827, {8, 100, 8}}, + {250.0, {3, 14, 2}}, + {250.00000000000003, {2, 14, 3}}, + {250.50505050505052, {8, 123, 10}}, + {250.79365079365078, {8, 78, 6}}, + {250.7936507936508, {6, 78, 8}}, + {250.9090909090909, {4, 68, 10}}, + {251.1111111111111, {8, 112, 9}}, + {251.11111111111111, {9, 112, 8}}, + {251.42857142857142, {6, 43, 4}}, + {251.51515151515153, {5, 82, 10}}, + {251.85185185185185, {8, 33, 2}}, + {251.85185185185188, {2, 33, 8}}, + {251.94805194805195, {6, 96, 10}}, + {252.0, {9, 62, 4}}, + {252.27272727272728, {7, 110, 10}}, + {252.38095238095238, {5, 52, 6}}, + {252.3809523809524, {6, 52, 5}}, + {252.5, {9, 100, 7}}, + {252.52525252525254, {8, 124, 10}}, + {252.72727272727272, {9, 138, 10}}, + {252.77777777777777, {8, 90, 7}}, + {253.06122448979593, {6, 61, 6}}, + {253.125, {7, 80, 7}}, + {253.33333333333331, {8, 56, 4}}, + {253.33333333333334, {4, 18, 2}}, + {253.57142857142858, {7, 70, 6}}, + {253.96825396825398, {8, 79, 6}}, + {254.0, {9, 126, 9}}, + {254.16666666666666, {7, 60, 5}}, + {254.16666666666669, {5, 60, 7}}, + {254.28571428571428, {9, 88, 6}}, + {254.2857142857143, {6, 88, 9}}, + {254.32098765432096, {8, 102, 8}}, + {254.54545454545453, {0, 13, 10}}, + {255.0, {9, 50, 3}}, + {255.55555555555554, {8, 45, 3}}, + {255.55555555555557, {5, 22, 2}}, + {256.0, {4, 31, 4}}, + {256.25, {7, 40, 3}}, + {256.3636363636364, {9, 140, 10}}, + {256.5656565656566, {8, 126, 10}}, + {256.6666666666667, {9, 76, 5}}, + {256.79012345679007, {8, 103, 8}}, + {256.8181818181818, {7, 112, 10}}, + {257.1428571428571, {6, 80, 8}}, + {257.14285714285717, {6, 26, 2}}, + {257.5, {9, 102, 7}}, + {257.57575757575756, {5, 84, 10}}, + {257.77777777777777, {8, 57, 4}}, + {258.0, {9, 128, 9}}, + {258.1818181818182, {4, 70, 10}}, + {258.3333333333333, {7, 30, 2}}, + {258.33333333333337, {5, 30, 3}}, + {258.5858585858586, {8, 127, 10}}, + {259.09090909090907, {3, 56, 10}}, + {259.25925925925924, {8, 34, 2}}, + {259.2592592592593, {2, 34, 8}}, + {259.375, {7, 82, 7}}, + {259.7402597402598, {6, 99, 10}}, + {260.0, {9, 38, 2}}, + {260.3174603174603, {8, 81, 6}}, + {260.31746031746036, {6, 81, 8}}, + {260.60606060606057, {8, 128, 10}}, + {260.6060606060606, {2, 42, 10}}, + {260.7142857142857, {7, 72, 6}}, + {261.1111111111111, {8, 46, 3}}, + {261.11111111111114, {5, 46, 5}}, + {261.2244897959184, {6, 63, 6}}, + {261.3636363636364, {7, 114, 10}}, + {261.7283950617284, {8, 105, 8}}, + {261.8181818181818, {4, 71, 10}}, + {261.9047619047619, {6, 54, 5}}, + {262.0, {9, 130, 9}}, + {262.22222222222223, {8, 58, 4}}, + {262.3376623376623, {6, 100, 10}}, + {262.5, {3, 20, 3}}, + {262.6262626262626, {8, 129, 10}}, + {262.85714285714283, {4, 45, 6}}, + {262.8571428571429, {6, 45, 4}}, + {262.962962962963, {8, 70, 5}}, + {263.3333333333333, {9, 78, 5}}, + {263.33333333333337, {5, 78, 9}}, + {263.4920634920635, {8, 82, 6}}, + {263.6363636363636, {1, 28, 10}}, + {263.88888888888886, {8, 94, 7}}, + {263.8888888888889, {7, 94, 8}}, + {264.0, {4, 32, 4}}, + {264.1975308641975, {8, 106, 8}}, + {264.2857142857143, {6, 36, 3}}, + {264.44444444444446, {9, 118, 8}}, + {264.6464646464646, {8, 130, 10}}, + {264.93506493506493, {6, 101, 10}}, + {265.0, {9, 52, 3}}, + {265.30612244897964, {6, 64, 6}}, + {265.45454545454544, {4, 72, 10}}, + {265.625, {7, 84, 7}}, + {265.7142857142857, {9, 92, 6}}, + {265.90909090909093, {7, 116, 10}}, + {266.0, {9, 132, 9}}, + {266.66666666666663, {8, 47, 3}}, + {266.6666666666667, {0, 3, 2}}, + {267.27272727272725, {9, 146, 10}}, + {267.5, {9, 106, 7}}, + {267.53246753246754, {6, 102, 10}}, + {267.85714285714283, {7, 74, 6}}, + {267.8571428571429, {6, 74, 7}}, + {268.0, {9, 66, 4}}, + {268.1818181818182, {3, 58, 10}}, + {268.57142857142856, {6, 46, 4}}, + {268.6868686868687, {8, 132, 10}}, + {268.75, {7, 42, 3}}, + {268.88888888888886, {8, 120, 9}}, + {268.8888888888889, {9, 120, 8}}, + {269.09090909090907, {4, 73, 10}}, + {269.1358024691358, {8, 108, 8}}, + {269.38775510204084, {6, 65, 6}}, + {269.44444444444446, {8, 96, 7}}, + {269.69696969696975, {5, 88, 10}}, + {269.8412698412698, {8, 84, 6}}, + {269.8412698412699, {6, 84, 8}}, + {270.0, {4, 26, 3}}, + {270.12987012987014, {6, 103, 10}}, + {270.3703703703704, {8, 72, 5}}, + {270.45454545454544, {7, 118, 10}}, + {270.7070707070707, {8, 133, 10}}, + {270.8333333333333, {7, 64, 5}}, + {270.83333333333337, {5, 64, 7}}, + {270.90909090909093, {9, 148, 10}}, + {271.1111111111111, {8, 60, 4}}, + {271.42857142857144, {6, 37, 3}}, + {271.6049382716049, {8, 109, 8}}, + {271.875, {7, 86, 7}}, + {272.0, {4, 33, 4}}, + {272.22222222222223, {8, 48, 3}}, + {272.5, {9, 108, 7}}, + {272.72727272727275, {0, 14, 10}}, + {273.015873015873, {8, 85, 6}}, + {273.3333333333333, {9, 40, 2}}, + {273.33333333333337, {5, 40, 4}}, + {273.46938775510205, {6, 66, 6}}, + {274.0, {9, 136, 9}}, + {274.0740740740741, {8, 36, 2}}, + {274.07407407407413, {2, 36, 8}}, + {274.2857142857143, {4, 47, 6}}, + {274.28571428571433, {6, 47, 4}}, + {275.0, {7, 32, 2}}, + {275.55555555555554, {8, 61, 4}}, + {276.0, {9, 68, 4}}, + {276.1904761904762, {6, 28, 2}}, + {276.5432098765432, {8, 111, 8}}, + {276.6666666666667, {9, 82, 5}}, + {277.14285714285717, {9, 96, 6}}, + {277.5, {9, 110, 7}}, + {277.55102040816325, {6, 67, 6}}, + {277.77777777777777, {5, 24, 2}}, + {278.0, {9, 138, 9}}, + {278.125, {7, 88, 7}}, + {278.57142857142856, {3, 38, 6}}, + {278.5714285714286, {6, 38, 3}}, + {279.0123456790123, {8, 112, 8}}, + {279.1666666666667, {7, 66, 5}}, + {279.36507936507934, {8, 87, 6}}, + {280.0, {4, 20, 2}}, + {280.55555555555554, {8, 100, 7}}, + {280.95238095238096, {6, 58, 5}}, + {281.25, {7, 44, 3}}, + {281.48148148148147, {8, 37, 2}}, + {281.4814814814815, {2, 37, 8}}, + {281.6326530612245, {6, 68, 6}}, + {282.0, {9, 140, 9}}, + {282.14285714285717, {7, 78, 6}}, + {282.22222222222223, {9, 126, 8}}, + {282.5, {9, 112, 7}}, + {282.53968253968253, {8, 88, 6}}, + {282.5396825396826, {6, 88, 8}}, + {282.85714285714283, {9, 98, 6}}, + {282.8571428571429, {6, 98, 9}}, + {283.3333333333333, {3, 16, 2}}, + {283.33333333333337, {2, 16, 3}}, + {283.95061728395063, {8, 114, 8}}, + {284.0, {9, 70, 4}}, + {284.375, {7, 90, 7}}, + {284.44444444444446, {8, 63, 4}}, + {285.0, {9, 56, 3}}, + {285.18518518518516, {8, 76, 5}}, + {285.1851851851852, {5, 76, 8}}, + {285.7142857142857, {6, 29, 2}}, + {286.0, {9, 142, 9}}, + {286.1111111111111, {8, 102, 7}}, + {286.41975308641975, {8, 115, 8}}, + {286.66666666666663, {8, 128, 9}}, + {286.6666666666667, {9, 42, 2}}, + {287.5, {3, 22, 3}}, + {288.0, {4, 35, 4}}, + {288.57142857142856, {9, 100, 6}}, + {288.88888888888886, {8, 38, 2}}, + {288.8888888888889, {2, 12, 2}}, + {289.2857142857143, {7, 80, 6}}, + {289.7959183673469, {6, 70, 6}}, + {290.0, {4, 28, 3}}, + {290.4761904761905, {6, 60, 5}}, + {290.625, {7, 92, 7}}, + {291.1111111111111, {9, 130, 8}}, + {291.358024691358, {8, 117, 8}}, + {291.42857142857144, {6, 50, 4}}, + {291.66666666666663, {8, 104, 7}}, + {291.6666666666667, {7, 34, 2}}, + {292.0, {9, 72, 4}}, + {292.06349206349205, {8, 91, 6}}, + {292.0634920634921, {6, 91, 8}}, + {292.5, {9, 116, 7}}, + {292.59259259259255, {8, 78, 5}}, + {292.5925925925926, {5, 78, 8}}, + {292.85714285714283, {3, 40, 6}}, + {292.8571428571429, {6, 40, 3}}, + {293.3333333333333, {4, 21, 2}}, + {293.33333333333337, {2, 21, 4}}, + {293.75, {7, 46, 3}}, + {293.82716049382714, {8, 118, 8}}, + {293.8775510204082, {6, 71, 6}}, + {294.0, {9, 146, 9}}, + {294.2857142857143, {9, 102, 6}}, + {294.28571428571433, {6, 102, 9}}, + {294.44444444444446, {8, 52, 3}}, + {295.0, {9, 58, 3}}, + {295.23809523809524, {6, 30, 2}}, + {295.2380952380953, {2, 30, 6}}, + {295.55555555555554, {9, 132, 8}}, + {295.8333333333333, {7, 70, 5}}, + {295.83333333333337, {5, 70, 7}}, + {296.0, {4, 36, 4}}, + {296.2962962962963, {8, 39, 2}}, + {296.42857142857144, {7, 82, 6}}, + {296.6666666666667, {9, 88, 5}}, + {296.875, {7, 94, 7}}, + {297.14285714285717, {6, 51, 4}}, + {297.22222222222223, {8, 106, 7}}, + {297.5, {9, 118, 7}}, + {297.77777777777777, {8, 66, 4}}, + {297.9591836734694, {6, 72, 6}}, + {298.0, {9, 148, 9}}, + {298.4126984126984, {8, 93, 6}}, + {298.41269841269843, {6, 93, 8}}, + {298.7654320987654, {8, 120, 8}}, + {300.0, {0, 2, 1}}, + {300.00000000000006, {5, 26, 2}}, + {301.2345679012345, {8, 121, 8}}, + {301.58730158730157, {8, 94, 6}}, + {302.0408163265306, {6, 73, 6}}, + {302.22222222222223, {8, 67, 4}}, + {302.5, {9, 120, 7}}, + {302.77777777777777, {8, 108, 7}}, + {302.85714285714283, {4, 52, 6}}, + {302.8571428571429, {6, 52, 4}}, + {303.125, {7, 96, 7}}, + {303.3333333333333, {9, 90, 5}}, + {303.57142857142856, {7, 84, 6}}, + {303.5714285714286, {6, 84, 7}}, + {303.7037037037037, {8, 40, 2}}, + {304.0, {4, 37, 4}}, + {304.1666666666667, {7, 72, 5}}, + {304.44444444444446, {9, 136, 8}}, + {304.7619047619047, {8, 95, 6}}, + {304.76190476190476, {6, 31, 2}}, + {304.7619047619048, {6, 95, 8}}, + {305.0, {9, 60, 3}}, + {305.55555555555554, {8, 54, 3}}, + {305.5555555555556, {5, 54, 5}}, + {305.7142857142857, {9, 106, 6}}, + {306.12244897959187, {6, 74, 6}}, + {306.17283950617286, {8, 123, 8}}, + {306.25, {7, 48, 3}}, + {306.66666666666663, {8, 68, 4}}, + {306.6666666666667, {4, 22, 2}}, + {307.14285714285717, {6, 42, 3}}, + {307.4074074074074, {8, 82, 5}}, + {307.40740740740745, {5, 82, 8}}, + {307.5, {9, 122, 7}}, + {307.93650793650795, {8, 96, 6}}, + {308.0, {9, 76, 4}}, + {308.3333333333333, {7, 36, 2}}, + {308.33333333333337, {5, 36, 3}}, + {308.57142857142856, {6, 53, 4}}, + {308.641975308642, {8, 124, 8}}, + {308.8888888888889, {9, 138, 8}}, + {309.375, {7, 98, 7}}, + {309.5238095238096, {6, 64, 5}}, + {310.0, {9, 30, 1}}, + {310.2040816326531, {6, 75, 6}}, + {310.7142857142857, {7, 86, 6}}, + {311.1111111111111, {8, 27, 1}}, + {311.11111111111114, {2, 13, 2}}, + {311.42857142857144, {9, 108, 6}}, + {312.0, {4, 38, 4}}, + {312.5, {7, 24, 1}}, + {313.3333333333333, {9, 46, 2}}, + {313.33333333333337, {5, 46, 4}}, + {313.58024691358025, {8, 126, 8}}, + {313.88888888888886, {8, 112, 7}}, + {313.8888888888889, {7, 112, 8}}, + {314.2857142857143, {6, 21, 1}}, + {314.28571428571433, {6, 54, 4}}, + {314.81481481481484, {8, 84, 5}}, + {315.0, {9, 62, 3}}, + {315.55555555555554, {8, 70, 4}}, + {315.625, {7, 100, 7}}, + {316.0, {9, 78, 4}}, + {316.04938271604937, {8, 127, 8}}, + {316.66666666666663, {8, 56, 3}}, + {316.6666666666667, {5, 18, 1}}, + {317.14285714285717, {9, 110, 6}}, + {317.46031746031747, {8, 99, 6}}, + {317.5, {9, 126, 7}}, + {317.77777777777777, {9, 142, 8}}, + {317.85714285714283, {7, 88, 6}}, + {317.8571428571429, {6, 88, 7}}, + {318.36734693877554, {6, 77, 6}}, + {318.5185185185185, {8, 128, 8}}, + {318.51851851851853, {8, 42, 2}}, + {318.75, {7, 50, 3}}, + {319.0476190476191, {6, 66, 5}}, + {319.44444444444446, {8, 114, 7}}, + {320.0, {4, 15, 1}}, + {320.6349206349206, {8, 100, 6}}, + {320.63492063492066, {6, 100, 8}}, + {320.8333333333333, {7, 76, 5}}, + {320.83333333333337, {5, 76, 7}}, + {320.98765432098764, {8, 129, 8}}, + {321.42857142857144, {6, 44, 3}}, + {321.875, {7, 102, 7}}, + {322.22222222222223, {8, 28, 1}}, + {322.44897959183675, {6, 78, 6}}, + {322.5, {9, 128, 7}}, + {322.85714285714283, {9, 112, 6}}, + {323.3333333333333, {9, 96, 5}}, + {323.45679012345676, {8, 130, 8}}, + {323.8095238095238, {6, 33, 2}}, + {323.80952380952385, {2, 33, 6}}, + {324.0, {9, 80, 4}}, + {324.44444444444446, {8, 72, 4}}, + {325.0, {3, 12, 1}}, + {325.7142857142857, {6, 56, 4}}, + {325.92592592592587, {8, 131, 8}}, + {325.9259259259259, {8, 43, 2}}, + {326.53061224489795, {6, 79, 6}}, + {326.6666666666667, {9, 48, 2}}, + {326.98412698412693, {8, 102, 6}}, + {326.984126984127, {6, 102, 8}}, + {327.5, {9, 130, 7}}, + {327.77777777777777, {8, 58, 3}}, + {328.0, {4, 40, 4}}, + {328.125, {7, 104, 7}}, + {328.3950617283951, {8, 132, 8}}, + {328.57142857142856, {1, 22, 6}}, + {328.5714285714286, {6, 22, 1}}, + {328.88888888888886, {8, 73, 4}}, + {328.8888888888889, {4, 73, 8}}, + {329.1666666666667, {7, 78, 5}}, + {329.6296296296296, {8, 88, 5}}, + {329.6296296296297, {5, 88, 8}}, + {330.0, {9, 32, 1}}, + {330.1587301587301, {8, 103, 6}}, + {330.1587301587302, {6, 103, 8}}, + {330.55555555555554, {8, 118, 7}}, + {330.61224489795916, {6, 80, 6}}, + {330.8641975308642, {8, 133, 8}}, + {331.1111111111111, {9, 148, 8}}, + {331.25, {7, 52, 3}}, + {331.42857142857144, {6, 57, 4}}, + {332.0, {9, 82, 4}}, + {332.14285714285717, {7, 92, 6}}, + {332.5, {9, 132, 7}}, + {333.3333333333333, {8, 29, 1}}, + {333.33333333333337, {2, 9, 1}}, + {334.2857142857143, {9, 116, 6}}, + {334.375, {7, 106, 7}}, + {334.6938775510204, {6, 81, 6}}, + {335.0, {9, 66, 3}}, + {335.7142857142857, {6, 46, 3}}, + {336.0, {4, 41, 4}}, + {336.1111111111111, {8, 120, 7}}, + {336.5079365079365, {8, 105, 6}}, + {336.6666666666667, {9, 100, 5}}, + {337.037037037037, {8, 90, 5}}, + {337.14285714285717, {6, 58, 4}}, + {337.5, {7, 26, 1}}, + {337.77777777777777, {8, 75, 4}}, + {338.09523809523813, {6, 70, 5}}, + {338.7755102040816, {6, 82, 6}}, + {338.88888888888886, {8, 60, 3}}, + {338.8888888888889, {5, 60, 5}}, + {339.2857142857143, {7, 94, 6}}, + {339.6825396825397, {8, 106, 6}}, + {340.0, {4, 16, 1}}, + {340.00000000000006, {5, 50, 4}}, + {340.625, {7, 108, 7}}, + {340.7407407407407, {8, 45, 2}}, + {341.66666666666663, {8, 122, 7}}, + {341.6666666666667, {7, 40, 2}}, + {342.22222222222223, {8, 76, 4}}, + {342.5, {9, 136, 7}}, + {342.85714285714283, {0, 11, 6}}, + {342.8571428571429, {6, 23, 1}}, + {343.3333333333333, {9, 102, 5}}, + {343.75, {7, 54, 3}}, + {344.0, {4, 42, 4}}, + {344.4444444444444, {8, 92, 5}}, + {344.44444444444446, {8, 30, 1}}, + {344.4444444444445, {5, 30, 2}}, + {345.0, {9, 68, 3}}, + {345.7142857142857, {9, 120, 6}}, + {345.8333333333333, {7, 82, 5}}, + {345.83333333333337, {5, 82, 7}}, + {346.031746031746, {8, 108, 6}}, + {346.42857142857144, {7, 96, 6}}, + {346.66666666666663, {8, 77, 4}}, + {346.6666666666667, {4, 25, 2}}, + {346.875, {7, 110, 7}}, + {346.93877551020415, {6, 84, 6}}, + {347.22222222222223, {8, 124, 7}}, + {347.5, {9, 138, 7}}, + {347.61904761904765, {6, 72, 5}}, + {348.0, {9, 86, 4}}, + {348.1481481481481, {8, 46, 2}}, + {348.57142857142856, {6, 60, 4}}, + {349.2063492063492, {8, 109, 6}}, + {350.0, {1, 6, 1}}, + {351.02040816326536, {6, 85, 6}}, + {351.1111111111111, {8, 78, 4}}, + {351.42857142857144, {9, 122, 6}}, + {351.8518518518518, {8, 94, 5}}, + {352.0, {4, 43, 4}}, + {352.38095238095235, {6, 36, 2}}, + {352.3809523809524, {2, 36, 6}}, + {352.5, {9, 140, 7}}, + {352.77777777777777, {8, 126, 7}}, + {353.125, {7, 112, 7}}, + {353.3333333333333, {9, 52, 2}}, + {353.33333333333337, {5, 52, 4}}, + {353.57142857142856, {7, 98, 6}}, + {353.5714285714286, {6, 98, 7}}, + {354.1666666666667, {7, 84, 5}}, + {354.2857142857143, {4, 61, 6}}, + {354.28571428571433, {6, 61, 4}}, + {355.0, {9, 70, 3}}, + {355.10204081632656, {6, 86, 6}}, + {355.5555555555555, {8, 47, 2}}, + {355.55555555555554, {8, 31, 1}}, + {355.5555555555556, {2, 15, 2}}, + {356.0, {9, 88, 4}}, + {356.25, {7, 56, 3}}, + {356.6666666666667, {9, 106, 5}}, + {357.14285714285717, {6, 24, 1}}, + {357.5, {9, 142, 7}}, + {358.3333333333333, {7, 42, 2}}, + {358.33333333333337, {5, 42, 3}}, + {358.7301587301587, {8, 112, 6}}, + {359.18367346938777, {6, 87, 6}}, + {359.2592592592593, {8, 96, 5}}, + {359.375, {7, 114, 7}}, + {360.0, {4, 17, 1}}, + {360.00000000000006, {2, 26, 4}}, + {360.7142857142857, {7, 100, 6}}, + {361.1111111111111, {8, 64, 3}}, + {361.11111111111114, {5, 64, 5}}, + {361.90476190476187, {8, 113, 6}}, + {361.9047619047619, {6, 37, 2}}, + {362.5, {7, 28, 1}}, + {362.85714285714283, {9, 126, 6}}, + {362.962962962963, {8, 48, 2}}, + {363.26530612244903, {6, 88, 6}}, + {363.3333333333333, {9, 108, 5}}, + {363.88888888888886, {8, 130, 7}}, + {364.0, {9, 90, 4}}, + {364.2857142857143, {6, 50, 3}}, + {364.44444444444446, {8, 81, 4}}, + {365.0, {9, 72, 3}}, + {365.0793650793651, {8, 114, 6}}, + {365.625, {7, 116, 7}}, + {365.7142857142857, {6, 63, 4}}, + {366.66666666666663, {8, 32, 1}}, + {366.6666666666667, {2, 10, 1}}, + {367.34693877551024, {6, 89, 6}}, + {367.5, {9, 146, 7}}, + {367.85714285714283, {7, 102, 6}}, + {367.8571428571429, {6, 102, 7}}, + {368.0, {4, 45, 4}}, + {368.25396825396825, {8, 115, 6}}, + {368.57142857142856, {9, 128, 6}}, + {368.75, {7, 58, 3}}, + {368.88888888888886, {8, 82, 4}}, + {369.44444444444446, {8, 132, 7}}, + {370.0, {9, 36, 1}}, + {370.3703703703704, {8, 49, 2}}, + {370.8333333333333, {7, 88, 5}}, + {370.83333333333337, {5, 88, 7}}, + {371.42857142857144, {6, 25, 1}}, + {371.4285714285715, {6, 38, 2}}, + {371.875, {7, 118, 7}}, + {372.0, {9, 92, 4}}, + {372.22222222222223, {8, 66, 3}}, + {372.5, {9, 148, 7}}, + {373.3333333333333, {4, 27, 2}}, + {373.33333333333337, {2, 27, 4}}, + {374.0740740740741, {8, 100, 5}}, + {374.2857142857143, {9, 130, 6}}, + {374.6031746031746, {8, 117, 6}}, + {375.0, {3, 14, 1}}, + {375.5102040816327, {6, 91, 6}}, + {376.0, {4, 46, 4}}, + {376.1904761904762, {6, 78, 5}}, + {376.6666666666667, {9, 112, 5}}, + {377.14285714285717, {6, 65, 4}}, + {377.77777777777777, {8, 33, 1}}, + {377.7777777777778, {2, 16, 2}}, + {378.57142857142856, {3, 52, 6}}, + {378.5714285714286, {6, 52, 3}}, + {379.1666666666667, {7, 90, 5}}, + {379.5918367346939, {6, 92, 6}}, + {380.0, {4, 18, 1}}, + {380.00000000000006, {5, 56, 4}}, + {380.9523809523809, {8, 119, 6}}, + {380.95238095238096, {6, 39, 2}}, + {380.952380952381, {2, 39, 6}}, + {381.25, {7, 60, 3}}, + {381.48148148148147, {8, 102, 5}}, + {382.14285714285717, {7, 106, 6}}, + {382.22222222222223, {8, 85, 4}}, + {382.85714285714283, {4, 66, 6}}, + {382.8571428571429, {6, 66, 4}}, + {383.3333333333333, {3, 22, 2}}, + {383.33333333333337, {5, 22, 1}}, + {383.6734693877551, {6, 93, 6}}, + {384.0, {4, 47, 4}}, + {384.1269841269841, {8, 120, 6}}, + {385.0, {9, 76, 3}}, + {385.18518518518516, {8, 51, 2}}, + {385.7142857142857, {6, 26, 1}}, + {386.66666666666663, {8, 86, 4}}, + {386.6666666666667, {4, 28, 2}}, + {387.3015873015873, {8, 121, 6}}, + {387.5, {7, 30, 1}}, + {387.7551020408163, {6, 94, 6}}, + {388.0, {9, 96, 4}}, + {388.57142857142856, {6, 67, 4}}, + {388.88888888888886, {8, 34, 1}}, + {388.8888888888889, {5, 34, 2}}, + {389.2857142857143, {7, 108, 6}}, + {390.0, {9, 38, 1}}, + {390.4761904761904, {8, 122, 6}}, + {390.4761904761905, {2, 40, 6}}, + {390.47619047619054, {6, 40, 2}}, + {391.1111111111111, {8, 87, 4}}, + {391.42857142857144, {9, 136, 6}}, + {391.6666666666667, {7, 46, 2}}, + {391.8367346938776, {6, 95, 6}}, + {392.0, {4, 48, 4}}, + {392.5925925925926, {8, 52, 2}}, + {392.85714285714283, {3, 54, 6}}, + {392.8571428571429, {6, 54, 3}}, + {393.3333333333333, {9, 58, 2}}, + {393.33333333333337, {5, 58, 4}}, + {393.6507936507937, {8, 123, 6}}, + {393.75, {7, 62, 3}}, + {394.2857142857143, {4, 68, 6}}, + {394.28571428571433, {6, 68, 4}}, + {394.44444444444446, {8, 70, 3}}, + {394.4444444444445, {5, 70, 5}}, + {395.0, {9, 78, 3}}, + {395.23809523809524, {6, 82, 5}}, + {395.2380952380953, {5, 82, 6}}, + {395.55555555555554, {8, 88, 4}}, + {395.8333333333333, {7, 94, 5}}, + {395.9183673469388, {6, 96, 6}}, + {396.0, {9, 98, 4}}, + {396.2962962962963, {8, 106, 5}}, + {396.42857142857144, {7, 110, 6}}, + {396.6666666666667, {9, 118, 5}}, + {396.8253968253968, {8, 124, 6}}, + {397.14285714285717, {9, 138, 6}}, + {400.0, {0, 3, 1}}, + {400.00000000000006, {2, 29, 4}}, + {402.85714285714283, {9, 140, 6}}, + {403.1746031746032, {8, 126, 6}}, + {403.3333333333333, {9, 120, 5}}, + {403.57142857142856, {7, 112, 6}}, + {403.7037037037037, {8, 108, 5}}, + {404.0, {9, 100, 4}}, + {404.08163265306126, {6, 98, 6}}, + {404.1666666666667, {7, 96, 5}}, + {404.44444444444446, {8, 90, 4}}, + {404.76190476190476, {5, 84, 6}}, + {404.7619047619048, {6, 84, 5}}, + {405.0, {9, 80, 3}}, + {405.55555555555554, {8, 72, 3}}, + {405.5555555555556, {5, 72, 5}}, + {405.7142857142857, {6, 70, 4}}, + {406.25, {7, 64, 3}}, + {406.3492063492063, {8, 127, 6}}, + {406.6666666666667, {9, 60, 2}}, + {407.14285714285717, {6, 56, 3}}, + {407.4074074074074, {8, 54, 2}}, + {408.0, {4, 50, 4}}, + {408.16326530612247, {6, 99, 6}}, + {408.3333333333333, {7, 48, 2}}, + {408.33333333333337, {5, 48, 3}}, + {408.57142857142856, {9, 142, 6}}, + {408.88888888888886, {8, 91, 4}}, + {409.5238095238095, {8, 128, 6}}, + {409.5238095238096, {6, 42, 2}}, + {410.0, {9, 40, 1}}, + {410.7142857142857, {7, 114, 6}}, + {411.1111111111111, {8, 36, 1}}, + {411.11111111111114, {5, 36, 2}}, + {411.42857142857144, {6, 71, 4}}, + {412.0, {9, 102, 4}}, + {412.2448979591837, {6, 100, 6}}, + {412.5, {7, 32, 1}}, + {412.69841269841265, {8, 129, 6}}, + {413.3333333333333, {4, 30, 2}}, + {413.33333333333337, {2, 30, 4}}, + {414.2857142857143, {6, 86, 5}}, + {414.28571428571433, {6, 28, 1}}, + {414.8148148148148, {8, 55, 2}}, + {415.0, {9, 82, 3}}, + {415.87301587301585, {8, 130, 6}}, + {416.0, {4, 51, 4}}, + {416.3265306122449, {6, 101, 6}}, + {416.66666666666663, {8, 74, 3}}, + {416.6666666666667, {5, 24, 1}}, + {417.14285714285717, {6, 72, 4}}, + {417.7777777777777, {8, 93, 4}}, + {417.85714285714283, {7, 116, 6}}, + {418.5185185185185, {8, 112, 5}}, + {418.75, {7, 66, 3}}, + {419.047619047619, {8, 131, 6}}, + {419.04761904761904, {6, 43, 2}}, + {419.0476190476191, {2, 43, 6}}, + {420.0, {4, 20, 1}}, + {420.40816326530614, {6, 102, 6}}, + {420.8333333333333, {7, 100, 5}}, + {421.42857142857144, {6, 58, 3}}, + {422.2222222222222, {8, 56, 2}}, + {422.22222222222223, {8, 37, 1}}, + {422.85714285714283, {6, 73, 4}}, + {423.3333333333333, {9, 126, 5}}, + {423.80952380952385, {6, 88, 5}}, + {424.0, {4, 52, 4}}, + {424.48979591836735, {6, 103, 6}}, + {425.0, {3, 16, 1}}, + {425.00000000000006, {5, 50, 3}}, + {425.3968253968254, {8, 133, 6}}, + {425.7142857142857, {9, 148, 6}}, + {425.9259259259259, {8, 114, 5}}, + {426.66666666666663, {8, 95, 4}}, + {426.6666666666667, {4, 31, 2}}, + {427.77777777777777, {8, 76, 3}}, + {427.7777777777778, {5, 76, 5}}, + {428.0, {9, 106, 4}}, + {428.57142857142856, {0, 14, 6}}, + {428.5714285714286, {6, 29, 1}}, + {429.1666666666667, {7, 102, 5}}, + {429.6296296296296, {8, 57, 2}}, + {430.0, {9, 42, 1}}, + {431.11111111111114, {8, 96, 4}}, + {431.25, {7, 68, 3}}, + {432.0, {4, 53, 4}}, + {433.3333333333333, {8, 38, 1}}, + {433.33333333333337, {2, 12, 1}}, + {434.28571428571433, {6, 75, 4}}, + {435.0, {9, 86, 3}}, + {435.55555555555554, {8, 97, 4}}, + {435.7142857142857, {6, 60, 3}}, + {436.0, {9, 108, 4}}, + {436.6666666666667, {9, 130, 5}}, + {437.037037037037, {8, 58, 2}}, + {437.5, {7, 34, 1}}, + {438.09523809523813, {6, 45, 2}}, + {438.88888888888886, {8, 78, 3}}, + {438.8888888888889, {5, 78, 5}}, + {440.0, {4, 21, 1}}, + {440.7407407407407, {8, 118, 5}}, + {441.6666666666667, {7, 52, 2}}, + {442.8571428571429, {6, 30, 1}}, + {443.3333333333333, {9, 132, 5}}, + {443.75, {7, 70, 3}}, + {444.0, {9, 110, 4}}, + {444.4444444444444, {8, 59, 2}}, + {444.44444444444446, {8, 39, 1}}, + {444.4444444444445, {2, 19, 2}}, + {445.0, {9, 88, 3}}, + {445.7142857142858, {6, 77, 4}}, + {445.8333333333333, {7, 106, 5}}, + {446.6666666666667, {9, 66, 2}}, + {447.61904761904765, {6, 46, 2}}, + {448.0, {4, 55, 4}}, + {448.1481481481481, {8, 120, 5}}, + {448.88888888888886, {8, 100, 4}}, + {450.0, {1, 8, 1}}, + {450.00000000000006, {5, 26, 1}}, + {451.42857142857144, {6, 78, 4}}, + {451.8518518518518, {8, 60, 2}}, + {452.0, {9, 112, 4}}, + {452.38095238095235, {6, 94, 5}}, + {453.3333333333333, {4, 33, 2}}, + {453.33333333333337, {2, 33, 4}}, + {454.1666666666667, {7, 108, 5}}, + {455.0, {9, 90, 3}}, + {455.5555555555555, {8, 122, 5}}, + {455.55555555555554, {8, 40, 1}}, + {455.5555555555556, {5, 40, 2}}, + {456.0, {4, 56, 4}}, + {456.25, {7, 72, 3}}, + {456.6666666666667, {9, 136, 5}}, + {457.14285714285717, {6, 31, 1}}, + {457.7777777777777, {8, 102, 4}}, + {458.3333333333333, {7, 54, 2}}, + {458.33333333333337, {5, 54, 3}}, + {459.2592592592593, {8, 61, 2}}, + {460.0, {4, 22, 1}}, + {461.1111111111111, {8, 82, 3}}, + {461.11111111111114, {5, 82, 5}}, + {461.9047619047619, {6, 96, 5}}, + {462.2222222222222, {8, 103, 4}}, + {462.5, {7, 36, 1}}, + {462.85714285714283, {6, 80, 4}}, + {462.962962962963, {8, 124, 5}}, + {463.3333333333333, {9, 138, 5}}, + {464.0, {4, 57, 4}}, + {464.28571428571433, {6, 64, 3}}, + {465.0, {9, 92, 3}}, + {466.66666666666663, {8, 41, 1}}, + {466.6666666666667, {2, 13, 1}}, + {468.0, {9, 116, 4}}, + {468.5714285714286, {6, 81, 4}}, + {468.75, {7, 74, 3}}, + {470.0, {9, 46, 1}}, + {470.3703703703704, {8, 126, 5}}, + {470.8333333333333, {7, 112, 5}}, + {471.11111111111114, {8, 105, 4}}, + {471.42857142857144, {6, 32, 1}}, + {471.4285714285715, {6, 98, 5}}, + {472.0, {4, 58, 4}}, + {472.22222222222223, {8, 84, 3}}, + {473.3333333333333, {9, 70, 2}}, + {473.33333333333337, {5, 70, 4}}, + {474.0740740740741, {8, 63, 2}}, + {474.28571428571433, {6, 82, 4}}, + {475.0, {3, 18, 1}}, + {475.00000000000006, {5, 56, 3}}, + {475.55555555555554, {8, 106, 4}}, + {476.0, {9, 118, 4}}, + {476.1904761904762, {6, 49, 2}}, + {476.6666666666667, {9, 142, 5}}, + {477.77777777777777, {8, 42, 1}}, + {477.7777777777778, {5, 42, 2}}, + {478.5714285714286, {6, 66, 3}}, + {479.1666666666667, {7, 114, 5}}, + {480.0, {4, 23, 1}}, + {480.95238095238096, {6, 100, 5}}, + {481.25, {7, 76, 3}}, + {481.48148148148147, {8, 64, 2}}, + {483.3333333333333, {3, 28, 2}}, + {483.33333333333337, {5, 28, 1}}, + {484.0, {9, 120, 4}}, + {484.44444444444446, {8, 108, 4}}, + {485.0, {9, 96, 3}}, + {485.18518518518516, {8, 130, 5}}, + {485.7142857142857, {6, 33, 1}}, + {485.7142857142858, {6, 84, 4}}, + {486.6666666666667, {9, 72, 2}}, + {487.5, {7, 38, 1}}, + {488.0, {4, 60, 4}}, + {488.88888888888886, {8, 43, 1}}, + {488.8888888888889, {2, 21, 2}}, + {490.0, {9, 48, 1}}, + {490.47619047619054, {6, 102, 5}}, + {491.42857142857144, {6, 85, 4}}, + {491.6666666666667, {7, 58, 2}}, + {492.0, {9, 122, 4}}, + {492.5925925925926, {8, 132, 5}}, + {492.8571428571429, {6, 68, 3}}, + {493.3333333333333, {4, 36, 2}}, + {493.33333333333337, {2, 36, 4}}, + {493.75, {7, 78, 3}}, + {494.4444444444444, {8, 88, 3}}, + {494.4444444444445, {5, 88, 5}}, + {495.0, {9, 98, 3}}, + {495.23809523809524, {6, 51, 2}}, + {495.8333333333333, {7, 118, 5}}, + {496.0, {4, 61, 4}}, + {496.2962962962963, {8, 66, 2}}, + {496.6666666666667, {9, 148, 5}}, + {497.14285714285717, {6, 86, 4}}, + {497.7777777777777, {8, 111, 4}}, + {500.0, {0, 4, 1}}, + {500.00000000000006, {2, 14, 1}}, + {502.2222222222222, {8, 112, 4}}, + {502.85714285714283, {6, 87, 4}}, + {503.7037037037037, {8, 67, 2}}, + {504.0, {4, 62, 4}}, + {504.7619047619048, {6, 52, 2}}, + {505.0, {9, 100, 3}}, + {505.55555555555554, {8, 90, 3}}, + {506.25, {7, 80, 3}}, + {506.66666666666663, {8, 113, 4}}, + {506.6666666666667, {4, 37, 2}}, + {507.14285714285717, {6, 70, 3}}, + {508.0, {9, 126, 4}}, + {508.3333333333333, {7, 60, 2}}, + {508.33333333333337, {5, 60, 3}}, + {508.5714285714286, {6, 88, 4}}, + {510.0, {9, 50, 1}}, + {511.1111111111111, {8, 45, 1}}, + {511.11111111111114, {2, 22, 2}}, + {512.0, {4, 63, 4}}, + {512.5, {7, 40, 1}}, + {513.3333333333334, {9, 76, 2}}, + {514.2857142857143, {6, 35, 1}}, + {515.0, {9, 102, 3}}, + {515.5555555555555, {8, 115, 4}}, + {516.0, {9, 128, 4}}, + {516.6666666666666, {3, 30, 2}}, + {516.6666666666667, {5, 30, 1}}, + {518.5185185185185, {8, 69, 2}}, + {518.75, {7, 82, 3}}, + {520.0, {4, 25, 1}}, + {521.4285714285714, {6, 72, 3}}, + {522.2222222222222, {8, 46, 1}}, + {522.2222222222223, {5, 46, 2}}, + {523.8095238095239, {6, 54, 2}}, + {524.0, {9, 130, 4}}, + {524.4444444444445, {8, 117, 4}}, + {525.0, {3, 20, 1}}, + {525.7142857142858, {6, 91, 4}}, + {525.925925925926, {8, 70, 2}}, + {526.6666666666666, {9, 78, 2}}, + {526.6666666666667, {5, 78, 4}}, + {527.7777777777777, {8, 94, 3}}, + {528.0, {4, 65, 4}}, + {528.5714285714286, {6, 36, 1}}, + {528.8888888888889, {8, 118, 4}}, + {530.0, {9, 52, 1}}, + {531.25, {7, 84, 3}}, + {531.4285714285714, {6, 92, 4}}, + {532.0, {9, 132, 4}}, + {533.3333333333333, {8, 47, 1}}, + {533.3333333333334, {2, 15, 1}}, + {535.0, {9, 106, 3}}, + {535.7142857142858, {6, 74, 3}}, + {536.0, {4, 66, 4}}, + {537.1428571428571, {6, 93, 4}}, + {537.5, {7, 42, 1}}, + {537.7777777777777, {8, 120, 4}}, + {538.8888888888889, {8, 96, 3}}, + {540.0, {4, 26, 1}}, + {540.7407407407408, {8, 72, 2}}, + {541.6666666666666, {7, 64, 2}}, + {541.6666666666667, {5, 64, 3}}, + {542.2222222222222, {8, 121, 4}}, + {542.8571428571429, {6, 37, 1}}, + {543.75, {7, 86, 3}}, + {544.0, {4, 67, 4}}, + {544.4444444444445, {8, 48, 1}}, + {545.0, {9, 108, 3}}, + {546.6666666666666, {4, 40, 2}}, + {546.6666666666667, {2, 40, 4}}, + {548.0, {9, 136, 4}}, + {548.1481481481482, {8, 73, 2}}, + {548.5714285714287, {6, 95, 4}}, + {550.0, {1, 10, 1}}, + {551.1111111111111, {8, 123, 4}}, + {552.0, {4, 68, 4}}, + {552.3809523809524, {6, 57, 2}}, + {553.3333333333334, {9, 82, 2}}, + {554.2857142857143, {6, 96, 4}}, + {555.0, {9, 110, 3}}, + {555.5555555555555, {8, 49, 1}}, + {556.0, {9, 138, 4}}, + {556.25, {7, 88, 3}}, + {557.1428571428572, {6, 38, 1}}, + {558.3333333333334, {7, 66, 2}}, + {560.0, {4, 27, 1}}, + {561.1111111111111, {8, 100, 3}}, + {561.9047619047619, {6, 58, 2}}, + {562.5, {7, 44, 1}}, + {562.9629629629629, {8, 75, 2}}, + {564.0, {9, 140, 4}}, + {564.2857142857143, {6, 78, 3}}, + {564.4444444444445, {8, 126, 4}}, + {565.0, {9, 112, 3}}, + {565.7142857142858, {6, 98, 4}}, + {566.6666666666666, {8, 50, 1}}, + {566.6666666666667, {2, 16, 1}}, + {568.0, {4, 70, 4}}, + {568.75, {7, 90, 3}}, + {568.8888888888889, {8, 127, 4}}, + {570.0, {9, 56, 1}}, + {570.3703703703703, {8, 76, 2}}, + {571.4285714285714, {6, 39, 1}}, + {572.0, {9, 142, 4}}, + {572.2222222222222, {8, 102, 3}}, + {573.3333333333333, {8, 128, 4}}, + {573.3333333333334, {4, 42, 2}}, + {575.0, {3, 22, 1}}, + {576.0, {4, 71, 4}}, + {577.1428571428571, {6, 100, 4}}, + {577.7777777777777, {8, 51, 1}}, + {577.7777777777778, {2, 25, 2}}, + {578.5714285714286, {6, 80, 3}}, + {580.0, {4, 28, 1}}, + {580.952380952381, {6, 60, 2}}, + {581.25, {7, 92, 3}}, + {582.2222222222222, {8, 130, 4}}, + {582.8571428571429, {6, 101, 4}}, + {583.3333333333333, {8, 104, 3}}, + {583.3333333333334, {5, 34, 1}}, + {584.0, {4, 72, 4}}, + {585.0, {9, 116, 3}}, + {585.1851851851851, {8, 78, 2}}, + {585.7142857142858, {6, 40, 1}}, + {586.6666666666666, {4, 43, 2}}, + {586.6666666666667, {2, 43, 4}}, + {587.5, {7, 46, 1}}, + {588.0, {9, 146, 4}}, + {588.5714285714287, {6, 102, 4}}, + {588.8888888888889, {8, 52, 1}}, + {590.0, {9, 58, 1}}, + {590.4761904761905, {6, 61, 2}}, + {591.1111111111111, {8, 132, 4}}, + {591.6666666666666, {7, 70, 2}}, + {591.6666666666667, {5, 70, 3}}, + {592.0, {4, 73, 4}}, + {592.5925925925926, {8, 79, 2}}, + {592.8571428571429, {6, 82, 3}}, + {593.3333333333334, {9, 88, 2}}, + {593.75, {7, 94, 3}}, + {594.2857142857143, {6, 103, 4}}, + {594.4444444444445, {8, 106, 3}}, + {595.0, {9, 118, 3}}, + {595.5555555555555, {8, 133, 4}}, + {596.0, {9, 148, 4}}, + {600.0, {0, 2, 0}}, + {600.0000000000001, {2, 26, 2}}, + {605.0, {9, 120, 3}}, + {605.5555555555555, {8, 108, 3}}, + {606.25, {7, 96, 3}}, + {606.6666666666666, {9, 90, 2}}, + {607.1428571428572, {6, 84, 3}}, + {607.4074074074074, {8, 81, 2}}, + {608.3333333333334, {7, 72, 2}}, + {609.5238095238095, {6, 63, 2}}, + {610.0, {9, 60, 1}}, + {611.1111111111111, {8, 54, 1}}, + {611.1111111111112, {5, 54, 2}}, + {612.5, {7, 48, 1}}, + {613.3333333333334, {4, 45, 2}}, + {614.2857142857143, {6, 42, 1}}, + {614.8148148148148, {8, 82, 2}}, + {615.0, {9, 122, 3}}, + {616.6666666666666, {3, 36, 2}}, + {616.6666666666667, {5, 36, 1}}, + {618.75, {7, 98, 3}}, + {619.0476190476192, {6, 64, 2}}, + {620.0, {9, 30, 0}}, + {621.4285714285714, {6, 86, 3}}, + {622.2222222222222, {8, 27, 0}}, + {622.2222222222223, {2, 27, 2}}, + {625.0, {7, 24, 0}}, + {626.6666666666666, {4, 46, 2}}, + {627.7777777777777, {8, 112, 3}}, + {628.5714285714286, {6, 21, 0}}, + {629.6296296296297, {8, 84, 2}}, + {630.0, {9, 62, 1}}, + {631.25, {7, 100, 3}}, + {633.3333333333333, {8, 56, 1}}, + {633.3333333333334, {5, 18, 0}}, + {635.0, {9, 126, 3}}, + {635.7142857142858, {6, 88, 3}}, + {637.0370370370371, {8, 85, 2}}, + {637.5, {7, 50, 1}}, + {638.0952380952382, {6, 66, 2}}, + {638.8888888888889, {8, 114, 3}}, + {640.0, {4, 15, 0}}, + {641.6666666666666, {7, 76, 2}}, + {641.6666666666667, {5, 76, 3}}, + {642.8571428571429, {6, 44, 1}}, + {643.75, {7, 102, 3}}, + {644.4444444444445, {8, 28, 0}}, + {645.0, {9, 128, 3}}, + {646.6666666666666, {9, 96, 2}}, + {647.6190476190476, {6, 67, 2}}, + {650.0, {3, 12, 0}}, + {651.8518518518518, {8, 87, 2}}, + {653.3333333333334, {4, 48, 2}}, + {655.0, {9, 130, 3}}, + {655.5555555555555, {8, 58, 1}}, + {656.25, {7, 104, 3}}, + {657.1428571428572, {6, 22, 0}}, + {658.3333333333334, {7, 78, 2}}, + {659.2592592592592, {8, 88, 2}}, + {660.0, {9, 32, 0}}, + {661.1111111111111, {8, 118, 3}}, + {662.5, {7, 52, 1}}, + {664.2857142857143, {6, 92, 3}}, + {665.0, {9, 132, 3}}, + {666.6666666666666, {8, 29, 0}}, + {666.6666666666667, {2, 9, 0}}, + {668.75, {7, 106, 3}}, + {670.0, {9, 66, 1}}, + {671.4285714285714, {6, 46, 1}}, + {672.2222222222222, {8, 120, 3}}, + {673.3333333333334, {9, 100, 2}}, + {674.074074074074, {8, 90, 2}}, + {675.0, {7, 26, 0}}, + {676.1904761904763, {6, 70, 2}}, + {677.7777777777777, {8, 60, 1}}, + {677.7777777777778, {5, 60, 2}}, + {678.5714285714286, {6, 94, 3}}, + {680.0, {4, 16, 0}}, + {681.25, {7, 108, 3}}, + {681.4814814814814, {8, 91, 2}}, + {683.3333333333333, {8, 122, 3}}, + {683.3333333333334, {5, 40, 1}}, + {685.0, {9, 136, 3}}, + {685.7142857142858, {6, 23, 0}}, + {686.6666666666666, {9, 102, 2}}, + {687.5, {7, 54, 1}}, + {688.8888888888888, {8, 92, 2}}, + {688.8888888888889, {8, 30, 0}}, + {688.888888888889, {2, 30, 2}}, + {690.0, {9, 68, 1}}, + {691.6666666666666, {7, 82, 2}}, + {691.6666666666667, {5, 82, 3}}, + {692.8571428571429, {6, 96, 3}}, + {693.3333333333334, {4, 51, 2}}, + {693.75, {7, 110, 3}}, + {694.4444444444445, {8, 124, 3}}, + {695.0, {9, 138, 3}}, + {695.2380952380953, {6, 72, 2}}, + {696.2962962962962, {8, 93, 2}}, + {700.0, {1, 6, 0}}, + {703.7037037037036, {8, 94, 2}}, + {704.7619047619047, {6, 73, 2}}, + {705.0, {9, 140, 3}}, + {705.5555555555555, {8, 126, 3}}, + {706.25, {7, 112, 3}}, + {706.6666666666666, {4, 52, 2}}, + {707.1428571428572, {6, 98, 3}}, + {708.3333333333334, {7, 84, 2}}, + {710.0, {9, 70, 1}}, + {711.111111111111, {8, 95, 2}}, + {711.1111111111111, {8, 31, 0}}, + {711.1111111111112, {2, 31, 2}}, + {712.5, {7, 56, 1}}, + {713.3333333333334, {9, 106, 2}}, + {714.2857142857143, {6, 24, 0}}, + {715.0, {9, 142, 3}}, + {716.6666666666666, {3, 42, 2}}, + {716.6666666666667, {5, 42, 1}}, + {718.5185185185186, {8, 96, 2}}, + {718.75, {7, 114, 3}}, + {720.0, {4, 17, 0}}, + {721.4285714285714, {6, 100, 3}}, + {722.2222222222222, {8, 64, 1}}, + {722.2222222222223, {5, 64, 2}}, + {723.8095238095239, {6, 75, 2}}, + {725.0, {7, 28, 0}}, + {725.925925925926, {8, 97, 2}}, + {726.6666666666666, {9, 108, 2}}, + {727.7777777777777, {8, 130, 3}}, + {728.5714285714286, {6, 50, 1}}, + {730.0, {9, 72, 1}}, + {731.25, {7, 116, 3}}, + {733.3333333333333, {8, 32, 0}}, + {733.3333333333334, {2, 10, 0}}, + {735.0, {9, 146, 3}}, + {735.7142857142858, {6, 102, 3}}, + {737.5, {7, 58, 1}}, + {738.8888888888889, {8, 132, 3}}, + {740.0, {9, 36, 0}}, + {740.7407407407408, {8, 99, 2}}, + {741.6666666666666, {7, 88, 2}}, + {741.6666666666667, {5, 88, 3}}, + {742.8571428571429, {6, 25, 0}}, + {742.857142857143, {6, 77, 2}}, + {743.75, {7, 118, 3}}, + {744.4444444444445, {8, 66, 1}}, + {745.0, {9, 148, 3}}, + {746.6666666666666, {4, 55, 2}}, + {748.1481481481482, {8, 100, 2}}, + {750.0, {3, 14, 0}}, + {752.3809523809524, {6, 78, 2}}, + {753.3333333333334, {9, 112, 2}}, + {755.5555555555555, {8, 33, 0}}, + {755.5555555555557, {2, 33, 2}}, + {757.1428571428572, {6, 52, 1}}, + {758.3333333333334, {7, 90, 2}}, + {760.0, {4, 18, 0}}, + {761.9047619047619, {6, 79, 2}}, + {762.5, {7, 60, 1}}, + {762.9629629629629, {8, 102, 2}}, + {766.6666666666666, {8, 68, 1}}, + {766.6666666666667, {5, 22, 0}}, + {770.0, {9, 76, 1}}, + {770.3703703703703, {8, 103, 2}}, + {771.4285714285714, {6, 26, 0}}, + {773.3333333333334, {4, 57, 2}}, + {775.0, {7, 30, 0}}, + {777.7777777777777, {8, 34, 0}}, + {777.7777777777778, {2, 34, 2}}, + {780.0, {9, 38, 0}}, + {780.9523809523811, {6, 81, 2}}, + {783.3333333333334, {5, 46, 1}}, + {785.1851851851852, {8, 105, 2}}, + {785.7142857142858, {6, 54, 1}}, + {786.6666666666666, {4, 58, 2}}, + {787.5, {7, 62, 1}}, + {788.8888888888889, {8, 70, 1}}, + {788.888888888889, {5, 70, 2}}, + {790.0, {9, 78, 1}}, + {790.4761904761905, {6, 82, 2}}, + {791.6666666666666, {7, 94, 2}}, + {792.5925925925926, {8, 106, 2}}, + {793.3333333333334, {9, 118, 2}}, + {800.0, {0, 3, 0}}, + {806.6666666666666, {9, 120, 2}}, + {807.4074074074074, {8, 108, 2}}, + {808.3333333333334, {7, 96, 2}}, + {809.5238095238096, {6, 84, 2}}, + {810.0, {9, 80, 1}}, + {811.1111111111111, {8, 72, 1}}, + {811.1111111111112, {5, 72, 2}}, + {812.5, {7, 64, 1}}, + {813.3333333333334, {4, 60, 2}}, + {814.2857142857143, {6, 56, 1}}, + {814.8148148148148, {8, 109, 2}}, + {816.6666666666666, {3, 48, 2}}, + {816.6666666666667, {5, 48, 1}}, + {819.0476190476192, {6, 85, 2}}, + {820.0, {9, 40, 0}}, + {822.2222222222222, {8, 36, 0}}, + {822.2222222222223, {2, 36, 2}}, + {825.0, {7, 32, 0}}, + {826.6666666666666, {4, 61, 2}}, + {828.5714285714286, {6, 86, 2}}, + {828.5714285714287, {6, 28, 0}}, + {829.6296296296296, {8, 111, 2}}, + {830.0, {9, 82, 1}}, + {833.3333333333333, {8, 74, 1}}, + {833.3333333333334, {5, 24, 0}}, + {837.037037037037, {8, 112, 2}}, + {837.5, {7, 66, 1}}, + {838.0952380952381, {6, 87, 2}}, + {840.0, {4, 20, 0}}, + {841.6666666666666, {7, 100, 2}}, + {842.8571428571429, {6, 58, 1}}, + {844.4444444444443, {8, 113, 2}}, + {844.4444444444445, {8, 37, 0}}, + {846.6666666666666, {9, 126, 2}}, + {847.6190476190477, {6, 88, 2}}, + {850.0, {3, 16, 0}}, + {850.0000000000001, {5, 50, 1}}, + {851.8518518518518, {8, 114, 2}}, + {853.3333333333334, {4, 63, 2}}, + {855.5555555555555, {8, 76, 1}}, + {855.5555555555557, {5, 76, 2}}, + {857.1428571428572, {6, 29, 0}}, + {858.3333333333334, {7, 102, 2}}, + {859.2592592592592, {8, 115, 2}}, + {860.0, {9, 42, 0}}, + {862.5, {7, 68, 1}}, + {866.6666666666666, {8, 38, 0}}, + {866.6666666666667, {2, 12, 0}}, + {870.0, {9, 86, 1}}, + {871.4285714285714, {6, 60, 1}}, + {873.3333333333334, {9, 130, 2}}, + {874.074074074074, {8, 117, 2}}, + {875.0, {7, 34, 0}}, + {876.1904761904763, {6, 91, 2}}, + {877.7777777777777, {8, 78, 1}}, + {877.7777777777778, {5, 78, 2}}, + {880.0, {4, 21, 0}}, + {881.4814814814814, {8, 118, 2}}, + {883.3333333333334, {5, 52, 1}}, + {885.7142857142858, {6, 30, 0}}, + {886.6666666666666, {9, 132, 2}}, + {887.5, {7, 70, 1}}, + {888.8888888888888, {8, 119, 2}}, + {888.8888888888889, {8, 39, 0}}, + {888.888888888889, {2, 39, 2}}, + {890.0, {9, 88, 1}}, + {891.6666666666666, {7, 106, 2}}, + {893.3333333333334, {4, 66, 2}}, + {895.2380952380953, {6, 93, 2}}, + {896.2962962962962, {8, 120, 2}}, + {900.0, {1, 8, 0}}, + {900.0000000000001, {5, 26, 0}}, + {903.7037037037036, {8, 121, 2}}, + {904.7619047619047, {6, 94, 2}}, + {906.6666666666666, {4, 67, 2}}, + {908.3333333333334, {7, 108, 2}}, + {910.0, {9, 90, 1}}, + {911.111111111111, {8, 122, 2}}, + {911.1111111111111, {8, 40, 0}}, + {911.1111111111112, {2, 40, 2}}, + {912.5, {7, 72, 1}}, + {913.3333333333334, {9, 136, 2}}, + {914.2857142857143, {6, 31, 0}}, + {916.6666666666666, {3, 54, 2}}, + {916.6666666666667, {5, 54, 1}}, + {918.5185185185186, {8, 123, 2}}, + {920.0, {4, 22, 0}}, + {922.2222222222222, {8, 82, 1}}, + {922.2222222222223, {5, 82, 2}}, + {923.8095238095239, {6, 96, 2}}, + {925.0, {7, 36, 0}}, + {925.925925925926, {8, 124, 2}}, + {926.6666666666666, {9, 138, 2}}, + {928.5714285714287, {6, 64, 1}}, + {930.0, {9, 92, 1}}, + {933.3333333333333, {8, 41, 0}}, + {933.3333333333334, {2, 13, 0}}, + {937.5, {7, 74, 1}}, + {940.0, {9, 46, 0}}, + {940.7407407407408, {8, 126, 2}}, + {941.6666666666666, {7, 112, 2}}, + {942.8571428571429, {6, 32, 0}}, + {942.857142857143, {6, 98, 2}}, + {944.4444444444445, {8, 84, 1}}, + {946.6666666666666, {4, 70, 2}}, + {948.1481481481482, {8, 127, 2}}, + {950.0, {3, 18, 0}}, + {950.0000000000001, {5, 56, 1}}, + {952.3809523809524, {6, 99, 2}}, + {953.3333333333334, {9, 142, 2}}, + {955.5555555555555, {8, 42, 0}}, + {955.5555555555557, {2, 42, 2}}, + {957.1428571428572, {6, 66, 1}}, + {958.3333333333334, {7, 114, 2}}, + {960.0, {4, 23, 0}}, + {961.9047619047619, {6, 100, 2}}, + {962.5, {7, 76, 1}}, + {962.9629629629629, {8, 129, 2}}, + {966.6666666666666, {8, 86, 1}}, + {966.6666666666667, {5, 28, 0}}, + {970.0, {9, 96, 1}}, + {970.3703703703703, {8, 130, 2}}, + {971.4285714285714, {6, 33, 0}}, + {973.3333333333334, {4, 72, 2}}, + {975.0, {7, 38, 0}}, + {977.7777777777777, {8, 43, 0}}, + {977.7777777777778, {2, 43, 2}}, + {980.0, {9, 48, 0}}, + {980.9523809523811, {6, 102, 2}}, + {983.3333333333334, {5, 58, 1}}, + {985.1851851851852, {8, 132, 2}}, + {985.7142857142858, {6, 68, 1}}, + {986.6666666666666, {4, 73, 2}}, + {987.5, {7, 78, 1}}, + {988.8888888888888, {8, 88, 1}}, + {988.888888888889, {5, 88, 2}}, + {990.0, {9, 98, 1}}, + {990.4761904761905, {6, 103, 2}}, + {991.6666666666666, {7, 118, 2}}, + {992.5925925925926, {8, 133, 2}}, + {993.3333333333334, {9, 148, 2}}, + {1000.0, {0, 4, 0}}, + {1010.0, {9, 100, 1}}, + {1011.1111111111111, {8, 90, 1}}, + {1012.5, {7, 80, 1}}, + {1014.2857142857143, {6, 70, 1}}, + {1016.6666666666667, {5, 60, 1}}, + {1020.0, {9, 50, 0}}, + {1022.2222222222222, {8, 45, 0}}, + {1025.0, {7, 40, 0}}, + {1028.5714285714287, {6, 35, 0}}, + {1030.0, {9, 102, 1}}, + {1033.3333333333333, {8, 92, 1}}, + {1037.5, {7, 82, 1}}, + {1040.0, {4, 25, 0}}, + {1042.857142857143, {6, 72, 1}}, + {1044.4444444444443, {8, 46, 0}}, + {1050.0, {3, 20, 0}}, + {1055.5555555555554, {8, 94, 1}}, + {1057.142857142857, {6, 36, 0}}, + {1060.0, {9, 52, 0}}, + {1062.5, {7, 84, 1}}, + {1066.6666666666665, {8, 47, 0}}, + {1070.0, {9, 106, 1}}, + {1071.4285714285716, {6, 74, 1}}, + {1075.0, {7, 42, 0}}, + {1077.7777777777778, {8, 96, 1}}, + {1080.0, {4, 26, 0}}, + {1083.3333333333335, {5, 64, 1}}, + {1085.7142857142858, {6, 37, 0}}, + {1087.5, {7, 86, 1}}, + {1088.888888888889, {8, 48, 0}}, + {1090.0, {9, 108, 1}}, + {1100.0, {1, 10, 0}}, + {1110.0, {9, 110, 1}}, + {1111.111111111111, {8, 49, 0}}, + {1112.5, {7, 88, 1}}, + {1114.2857142857144, {6, 38, 0}}, + {1116.6666666666667, {5, 66, 1}}, + {1120.0, {4, 27, 0}}, + {1122.2222222222222, {8, 100, 1}}, + {1125.0, {7, 44, 0}}, + {1128.5714285714287, {6, 78, 1}}, + {1130.0, {9, 112, 1}}, + {1133.3333333333333, {8, 50, 0}}, + {1137.5, {7, 90, 1}}, + {1140.0, {9, 56, 0}}, + {1142.857142857143, {6, 39, 0}}, + {1144.4444444444443, {8, 102, 1}}, + {1150.0, {3, 22, 0}}, + {1155.5555555555554, {8, 51, 0}}, + {1157.142857142857, {6, 80, 1}}, + {1160.0, {4, 28, 0}}, + {1162.5, {7, 92, 1}}, + {1166.6666666666665, {8, 104, 1}}, + {1170.0, {9, 116, 1}}, + {1171.4285714285716, {6, 40, 0}}, + {1175.0, {7, 46, 0}}, + {1177.7777777777778, {8, 52, 0}}, + {1180.0, {9, 58, 0}}, + {1183.3333333333335, {5, 70, 1}}, + {1185.7142857142858, {6, 82, 1}}, + {1187.5, {7, 94, 1}}, + {1188.888888888889, {8, 106, 1}}, + {1190.0, {9, 118, 1}}, + {1200.0, {0, 5, 0}}, + {1210.0, {9, 120, 1}}, + {1211.111111111111, {8, 108, 1}}, + {1212.5, {7, 96, 1}}, + {1214.2857142857144, {6, 84, 1}}, + {1216.6666666666667, {5, 72, 1}}, + {1220.0, {9, 60, 0}}, + {1222.2222222222222, {8, 54, 0}}, + {1225.0, {7, 48, 0}}, + {1228.5714285714287, {6, 42, 0}}, + {1230.0, {9, 122, 1}}, + {1233.3333333333333, {8, 110, 1}}, + {1237.5, {7, 98, 1}}, + {1240.0, {4, 30, 0}}, + {1242.857142857143, {6, 86, 1}}, + {1244.4444444444443, {8, 55, 0}}, + {1250.0, {3, 24, 0}}, + {1255.5555555555554, {8, 112, 1}}, + {1257.142857142857, {6, 43, 0}}, + {1260.0, {9, 62, 0}}, + {1262.5, {7, 100, 1}}, + {1266.6666666666665, {8, 56, 0}}, + {1270.0, {9, 126, 1}}, + {1271.4285714285716, {6, 88, 1}}, + {1275.0, {7, 50, 0}}, + {1277.7777777777778, {8, 114, 1}}, + {1280.0, {4, 31, 0}}, + {1283.3333333333335, {5, 76, 1}}, + {1285.7142857142858, {6, 44, 0}}, + {1287.5, {7, 102, 1}}, + {1288.888888888889, {8, 57, 0}}, + {1290.0, {9, 128, 1}}, + {1300.0, {1, 12, 0}}, + {1310.0, {9, 130, 1}}, + {1311.111111111111, {8, 58, 0}}, + {1312.5, {7, 104, 1}}, + {1314.2857142857144, {6, 45, 0}}, + {1316.6666666666667, {5, 78, 1}}, + {1320.0, {4, 32, 0}}, + {1322.2222222222222, {8, 118, 1}}, + {1325.0, {7, 52, 0}}, + {1328.5714285714287, {6, 92, 1}}, + {1330.0, {9, 132, 1}}, + {1333.3333333333333, {8, 59, 0}}, + {1337.5, {7, 106, 1}}, + {1340.0, {9, 66, 0}}, + {1342.857142857143, {6, 46, 0}}, + {1344.4444444444443, {8, 120, 1}}, + {1350.0, {3, 26, 0}}, + {1355.5555555555554, {8, 60, 0}}, + {1357.142857142857, {6, 94, 1}}, + {1360.0, {4, 33, 0}}, + {1362.5, {7, 108, 1}}, + {1366.6666666666665, {8, 122, 1}}, + {1370.0, {9, 136, 1}}, + {1371.4285714285716, {6, 47, 0}}, + {1375.0, {7, 54, 0}}, + {1377.7777777777778, {8, 61, 0}}, + {1380.0, {9, 68, 0}}, + {1383.3333333333335, {5, 82, 1}}, + {1385.7142857142858, {6, 96, 1}}, + {1387.5, {7, 110, 1}}, + {1388.888888888889, {8, 124, 1}}, + {1390.0, {9, 138, 1}}, + {1400.0, {0, 6, 0}}, + {1410.0, {9, 140, 1}}, + {1411.111111111111, {8, 126, 1}}, + {1412.5, {7, 112, 1}}, + {1414.2857142857144, {6, 98, 1}}, + {1416.6666666666667, {5, 84, 1}}, + {1420.0, {9, 70, 0}}, + {1422.2222222222222, {8, 63, 0}}, + {1425.0, {7, 56, 0}}, + {1428.5714285714287, {6, 49, 0}}, + {1430.0, {9, 142, 1}}, + {1433.3333333333333, {8, 128, 1}}, + {1437.5, {7, 114, 1}}, + {1440.0, {4, 35, 0}}, + {1442.857142857143, {6, 100, 1}}, + {1444.4444444444443, {8, 64, 0}}, + {1450.0, {3, 28, 0}}, + {1455.5555555555554, {8, 130, 1}}, + {1457.142857142857, {6, 50, 0}}, + {1460.0, {9, 72, 0}}, + {1462.5, {7, 116, 1}}, + {1466.6666666666665, {8, 65, 0}}, + {1470.0, {9, 146, 1}}, + {1471.4285714285716, {6, 102, 1}}, + {1475.0, {7, 58, 0}}, + {1477.7777777777778, {8, 132, 1}}, + {1480.0, {4, 36, 0}}, + {1483.3333333333335, {5, 88, 1}}, + {1485.7142857142858, {6, 51, 0}}, + {1487.5, {7, 118, 1}}, + {1488.888888888889, {8, 66, 0}}, + {1490.0, {9, 148, 1}}, + {1500.0, {1, 14, 0}}, + {1511.111111111111, {8, 67, 0}}, + {1514.2857142857144, {6, 52, 0}}, + {1520.0, {4, 37, 0}}, + {1525.0, {7, 60, 0}}, + {1533.3333333333333, {8, 68, 0}}, + {1540.0, {9, 76, 0}}, + {1542.857142857143, {6, 53, 0}}, + {1550.0, {3, 30, 0}}, + {1555.5555555555554, {8, 69, 0}}, + {1560.0, {4, 38, 0}}, + {1566.6666666666667, {5, 46, 0}}, + {1571.4285714285716, {6, 54, 0}}, + {1575.0, {7, 62, 0}}, + {1577.7777777777778, {8, 70, 0}}, + {1580.0, {9, 78, 0}}, + {1600.0, {0, 7, 0}}, + {1620.0, {9, 80, 0}}, + {1622.2222222222222, {8, 72, 0}}, + {1625.0, {7, 64, 0}}, + {1628.5714285714287, {6, 56, 0}}, + {1633.3333333333335, {5, 48, 0}}, + {1640.0, {4, 40, 0}}, + {1644.4444444444443, {8, 73, 0}}, + {1650.0, {3, 32, 0}}, + {1657.1428571428573, {6, 57, 0}}, + {1660.0, {9, 82, 0}}, + {1666.6666666666665, {8, 74, 0}}, + {1675.0, {7, 66, 0}}, + {1680.0, {4, 41, 0}}, + {1685.7142857142858, {6, 58, 0}}, + {1688.888888888889, {8, 75, 0}}, + {1700.0, {1, 16, 0}}, + {1711.111111111111, {8, 76, 0}}, + {1714.2857142857144, {6, 59, 0}}, + {1720.0, {4, 42, 0}}, + {1725.0, {7, 68, 0}}, + {1733.3333333333333, {8, 77, 0}}, + {1740.0, {9, 86, 0}}, + {1742.857142857143, {6, 60, 0}}, + {1750.0, {3, 34, 0}}, + {1755.5555555555554, {8, 78, 0}}, + {1760.0, {4, 43, 0}}, + {1766.6666666666667, {5, 52, 0}}, + {1771.4285714285716, {6, 61, 0}}, + {1775.0, {7, 70, 0}}, + {1777.7777777777778, {8, 79, 0}}, + {1780.0, {9, 88, 0}}, + {1800.0, {0, 8, 0}}, + {1820.0, {9, 90, 0}}, + {1822.2222222222222, {8, 81, 0}}, + {1825.0, {7, 72, 0}}, + {1828.5714285714287, {6, 63, 0}}, + {1833.3333333333335, {5, 54, 0}}, + {1840.0, {4, 45, 0}}, + {1844.4444444444443, {8, 82, 0}}, + {1850.0, {3, 36, 0}}, + {1857.1428571428573, {6, 64, 0}}, + {1860.0, {9, 92, 0}}, + {1866.6666666666665, {8, 83, 0}}, + {1875.0, {7, 74, 0}}, + {1880.0, {4, 46, 0}}, + {1885.7142857142858, {6, 65, 0}}, + {1888.888888888889, {8, 84, 0}}, + {1900.0, {1, 18, 0}}, + {1911.111111111111, {8, 85, 0}}, + {1914.2857142857144, {6, 66, 0}}, + {1920.0, {4, 47, 0}}, + {1925.0, {7, 76, 0}}, + {1933.3333333333333, {8, 86, 0}}, + {1940.0, {9, 96, 0}}, + {1942.857142857143, {6, 67, 0}}, + {1950.0, {3, 38, 0}}, + {1955.5555555555554, {8, 87, 0}}, + {1960.0, {4, 48, 0}}, + {1966.6666666666667, {5, 58, 0}}, + {1971.4285714285716, {6, 68, 0}}, + {1975.0, {7, 78, 0}}, + {1977.7777777777776, {8, 88, 0}}, + {1980.0, {9, 98, 0}}, + {2000.0, {0, 9, 0}}, + {2020.0, {9, 100, 0}}, + {2022.2222222222222, {8, 90, 0}}, + {2025.0, {7, 80, 0}}, + {2028.5714285714287, {6, 70, 0}}, + {2033.3333333333335, {5, 60, 0}}, + {2040.0, {4, 50, 0}}, + {2044.4444444444443, {8, 91, 0}}, + {2050.0, {3, 40, 0}}, + {2057.1428571428573, {6, 71, 0}}, + {2060.0, {9, 102, 0}}, + {2066.6666666666665, {8, 92, 0}}, + {2075.0, {7, 82, 0}}, + {2080.0, {4, 51, 0}}, + {2085.714285714286, {6, 72, 0}}, + {2088.8888888888887, {8, 93, 0}}, + {2100.0, {1, 20, 0}}, + {2111.111111111111, {8, 94, 0}}, + {2114.285714285714, {6, 73, 0}}, + {2120.0, {4, 52, 0}}, + {2125.0, {7, 84, 0}}, + {2133.333333333333, {8, 95, 0}}, + {2140.0, {9, 106, 0}}, + {2142.857142857143, {6, 74, 0}}, + {2150.0, {3, 42, 0}}, + {2155.5555555555557, {8, 96, 0}}, + {2160.0, {4, 53, 0}}, + {2166.666666666667, {5, 64, 0}}, + {2171.4285714285716, {6, 75, 0}}, + {2175.0, {7, 86, 0}}, + {2177.777777777778, {8, 97, 0}}, + {2180.0, {9, 108, 0}}, + {2200.0, {0, 10, 0}}, + {2220.0, {9, 110, 0}}, + {2222.222222222222, {8, 99, 0}}, + {2225.0, {7, 88, 0}}, + {2228.571428571429, {6, 77, 0}}, + {2233.3333333333335, {5, 66, 0}}, + {2240.0, {4, 55, 0}}, + {2244.4444444444443, {8, 100, 0}}, + {2250.0, {3, 44, 0}}, + {2257.1428571428573, {6, 78, 0}}, + {2260.0, {9, 112, 0}}, + {2266.6666666666665, {8, 101, 0}}, + {2275.0, {7, 90, 0}}, + {2280.0, {4, 56, 0}}, + {2285.714285714286, {6, 79, 0}}, + {2288.8888888888887, {8, 102, 0}}, + {2300.0, {1, 22, 0}}, + {2311.111111111111, {8, 103, 0}}, + {2314.285714285714, {6, 80, 0}}, + {2320.0, {4, 57, 0}}, + {2325.0, {7, 92, 0}}, + {2333.333333333333, {8, 104, 0}}, + {2340.0, {9, 116, 0}}, + {2342.857142857143, {6, 81, 0}}, + {2350.0, {3, 46, 0}}, + {2355.5555555555557, {8, 105, 0}}, + {2360.0, {4, 58, 0}}, + {2366.666666666667, {5, 70, 0}}, + {2371.4285714285716, {6, 82, 0}}, + {2375.0, {7, 94, 0}}, + {2377.777777777778, {8, 106, 0}}, + {2380.0, {9, 118, 0}}, + {2400.0, {0, 11, 0}}, + {2420.0, {9, 120, 0}}, + {2422.222222222222, {8, 108, 0}}, + {2425.0, {7, 96, 0}}, + {2428.571428571429, {6, 84, 0}}, + {2433.3333333333335, {5, 72, 0}}, + {2440.0, {4, 60, 0}}, + {2444.4444444444443, {8, 109, 0}}, + {2450.0, {3, 48, 0}}, + {2457.1428571428573, {6, 85, 0}}, + {2460.0, {9, 122, 0}}, + {2466.6666666666665, {8, 110, 0}}, + {2475.0, {7, 98, 0}}, + {2480.0, {4, 61, 0}}, + {2485.714285714286, {6, 86, 0}}, + {2488.8888888888887, {8, 111, 0}}, + {2500.0, {1, 24, 0}}, + {2511.111111111111, {8, 112, 0}}, + {2514.285714285714, {6, 87, 0}}, + {2520.0, {4, 62, 0}}, + {2525.0, {7, 100, 0}}, + {2533.333333333333, {8, 113, 0}}, + {2540.0, {9, 126, 0}}, + {2542.857142857143, {6, 88, 0}}, + {2550.0, {3, 50, 0}}, + {2555.5555555555557, {8, 114, 0}}, + {2560.0, {4, 63, 0}}, + {2566.666666666667, {5, 76, 0}}, + {2571.4285714285716, {6, 89, 0}}, + {2575.0, {7, 102, 0}}, + {2577.777777777778, {8, 115, 0}}, + {2580.0, {9, 128, 0}}, + {2600.0, {0, 12, 0}}, + {2620.0, {9, 130, 0}}, + {2622.222222222222, {8, 117, 0}}, + {2625.0, {7, 104, 0}}, + {2628.571428571429, {6, 91, 0}}, + {2633.3333333333335, {5, 78, 0}}, + {2640.0, {4, 65, 0}}, + {2644.4444444444443, {8, 118, 0}}, + {2650.0, {3, 52, 0}}, + {2657.1428571428573, {6, 92, 0}}, + {2660.0, {9, 132, 0}}, + {2666.6666666666665, {8, 119, 0}}, + {2675.0, {7, 106, 0}}, + {2680.0, {4, 66, 0}}, + {2685.714285714286, {6, 93, 0}}, + {2688.8888888888887, {8, 120, 0}}, + {2700.0, {1, 26, 0}}, + {2711.111111111111, {8, 121, 0}}, + {2714.285714285714, {6, 94, 0}}, + {2720.0, {4, 67, 0}}, + {2725.0, {7, 108, 0}}, + {2733.333333333333, {8, 122, 0}}, + {2740.0, {9, 136, 0}}, + {2742.857142857143, {6, 95, 0}}, + {2750.0, {3, 54, 0}}, + {2755.5555555555557, {8, 123, 0}}, + {2760.0, {4, 68, 0}}, + {2766.666666666667, {5, 82, 0}}, + {2771.4285714285716, {6, 96, 0}}, + {2775.0, {7, 110, 0}}, + {2777.777777777778, {8, 124, 0}}, + {2780.0, {9, 138, 0}}, + {2800.0, {0, 13, 0}}, + {2820.0, {9, 140, 0}}, + {2822.222222222222, {8, 126, 0}}, + {2825.0, {7, 112, 0}}, + {2828.571428571429, {6, 98, 0}}, + {2833.3333333333335, {5, 84, 0}}, + {2840.0, {4, 70, 0}}, + {2844.4444444444443, {8, 127, 0}}, + {2850.0, {3, 56, 0}}, + {2857.1428571428573, {6, 99, 0}}, + {2860.0, {9, 142, 0}}, + {2866.6666666666665, {8, 128, 0}}, + {2875.0, {7, 114, 0}}, + {2880.0, {4, 71, 0}}, + {2885.714285714286, {6, 100, 0}}, + {2888.8888888888887, {8, 129, 0}}, + {2900.0, {1, 28, 0}}, + {2911.111111111111, {8, 130, 0}}, + {2914.285714285714, {6, 101, 0}}, + {2920.0, {4, 72, 0}}, + {2925.0, {7, 116, 0}}, + {2933.333333333333, {8, 131, 0}}, + {2940.0, {9, 146, 0}}, + {2942.857142857143, {6, 102, 0}}, + {2950.0, {3, 58, 0}}, + {2955.5555555555557, {8, 132, 0}}, + {2960.0, {4, 73, 0}}, + {2966.666666666667, {5, 88, 0}}, + {2971.4285714285716, {6, 103, 0}}, + {2975.0, {7, 118, 0}}, + {2977.777777777778, {8, 133, 0}}, + {2980.0, {9, 148, 0}}, + {3000.0, {0, 14, 0}} +}; diff --git a/src/hw/pll_freqs.hpp b/src/hw/pll_freqs.hpp new file mode 100644 index 00000000..211ccb3b --- /dev/null +++ b/src/hw/pll_freqs.hpp @@ -0,0 +1,43 @@ +#ifndef _PLL_FREQS_HPP_ +#define _PLL_FREQS_HPP_ + +#include + +#define VALID_PLL_FILTER_RANGES 8 +#define VALID_PLL_FREQS 8003 + +/* +struct pll_filter_range { + double low; + double high; +}; + +pll_filter_range pll_filter_ranges[VALID_PLL_FILTER_RANGES] = { + {5.0, 7.5}, + {7.5, 11.0}, + {11.0, 18.0}, + {18.0, 30.0}, + {30.0, 50.0}, + {50.0, 80.0}, + {80.0, 130.0}, + {130.0, 200,0} +}; +*/ + +extern double pll_filter_ranges[VALID_PLL_FILTER_RANGES]; + +struct pll_settings { + uint32_t divr; + uint32_t divfi; + uint32_t divq; +}; + +// freq = 400 * (divfi + 1) / (2 * (divr + 1) * (divq + 1)) +struct pll_entry { + double freq; + pll_settings settings; +}; + +extern pll_entry pll_entries[VALID_PLL_FREQS]; + +#endif // _PLL_FREQS_HPP_ diff --git a/src/hw/pvt.hpp b/src/hw/pvt.hpp new file mode 100644 index 00000000..6d61d182 --- /dev/null +++ b/src/hw/pvt.hpp @@ -0,0 +1,111 @@ +// Generated register defines for pvt +#ifndef _PVT_REG_DEFS_ +#define _PVT_REG_DEFS_ + +#ifdef __cplusplus +extern "C" { +#endif +// Register width +#define PVT_PARAM_REG_WIDTH 32 + +// PVT measurement control +#define PVT_ENABLE_REG_OFFSET 0x10000 +#define PVT_ENABLE_REG_RESVAL 0x0 +#define PVT_ENABLE_ENABLE_BIT 0 +#define PVT_ENABLE_STATUS_MASK 0xf +#define PVT_ENABLE_STATUS_OFFSET 12 +#define PVT_ENABLE_STATUS_FIELD \ + ((bitfield_field32_t) { .mask = PVT_ENABLE_STATUS_MASK, .index = PVT_ENABLE_STATUS_OFFSET }) + +// PVT clock period +#define PVT_PERIOD_REG_OFFSET 0x10004 +#define PVT_PERIOD_REG_RESVAL 0x0 +#define PVT_PERIOD_PERIOD_MASK 0x3f +#define PVT_PERIOD_PERIOD_OFFSET 0 +#define PVT_PERIOD_PERIOD_FIELD \ + ((bitfield_field32_t) { .mask = PVT_PERIOD_PERIOD_MASK, .index = PVT_PERIOD_PERIOD_OFFSET }) + +// PVT tuning for TRIMG +#define PVT_TRIMG_REG_OFFSET 0x10008 +#define PVT_TRIMG_REG_RESVAL 0xf +#define PVT_TRIMG_TRIMG_MASK 0x1f +#define PVT_TRIMG_TRIMG_OFFSET 0 +#define PVT_TRIMG_TRIMG_FIELD \ + ((bitfield_field32_t) { .mask = PVT_TRIMG_TRIMG_MASK, .index = PVT_TRIMG_TRIMG_OFFSET }) + +// PVT tuning for TRIMO +#define PVT_TRIMO_REG_OFFSET 0x1000c +#define PVT_TRIMO_REG_RESVAL 0x0 +#define PVT_TRIMO_TRIMO_MASK 0x3f +#define PVT_TRIMO_TRIMO_OFFSET 0 +#define PVT_TRIMO_TRIMO_FIELD \ + ((bitfield_field32_t) { .mask = PVT_TRIMO_TRIMO_MASK, .index = PVT_TRIMO_TRIMO_OFFSET }) + +// Die temperature measurement +#define PVT_TEMPERATURE_REG_OFFSET 0x10010 +#define PVT_TEMPERATURE_REG_RESVAL 0x0 +#define PVT_TEMPERATURE_TEMPERATURE_MASK 0x3ff +#define PVT_TEMPERATURE_TEMPERATURE_OFFSET 0 +#define PVT_TEMPERATURE_TEMPERATURE_FIELD \ + ((bitfield_field32_t) { .mask = PVT_TEMPERATURE_TEMPERATURE_MASK, .index = PVT_TEMPERATURE_TEMPERATURE_OFFSET }) + +// Die LVT process measurement +#define PVT_PROCESS_LVT_REG_OFFSET 0x10014 +#define PVT_PROCESS_LVT_REG_RESVAL 0x0 +#define PVT_PROCESS_LVT_LVT_MASK 0x3ff +#define PVT_PROCESS_LVT_LVT_OFFSET 0 +#define PVT_PROCESS_LVT_LVT_FIELD \ + ((bitfield_field32_t) { .mask = PVT_PROCESS_LVT_LVT_MASK, .index = PVT_PROCESS_LVT_LVT_OFFSET }) + +// Die SLVT process measurement +#define PVT_PROCESS_SLVT_REG_OFFSET 0x10018 +#define PVT_PROCESS_SLVT_REG_RESVAL 0x0 +#define PVT_PROCESS_SLVT_SLVT_MASK 0x3ff +#define PVT_PROCESS_SLVT_SLVT_OFFSET 0 +#define PVT_PROCESS_SLVT_SLVT_FIELD \ + ((bitfield_field32_t) { .mask = PVT_PROCESS_SLVT_SLVT_MASK, .index = PVT_PROCESS_SLVT_SLVT_OFFSET }) + +// Die RVT process measurement +#define PVT_PROCESS_RVT_REG_OFFSET 0x1001c +#define PVT_PROCESS_RVT_REG_RESVAL 0x0 +#define PVT_PROCESS_RVT_RVT_MASK 0x3ff +#define PVT_PROCESS_RVT_RVT_OFFSET 0 +#define PVT_PROCESS_RVT_RVT_FIELD \ + ((bitfield_field32_t) { .mask = PVT_PROCESS_RVT_RVT_MASK, .index = PVT_PROCESS_RVT_RVT_OFFSET }) + +// Voltage measurement +#define PVT_VOLTAGE_REG_OFFSET 0x10020 +#define PVT_VOLTAGE_REG_RESVAL 0x0 +#define PVT_VOLTAGE_VOLTAGE_MASK 0x3ff +#define PVT_VOLTAGE_VOLTAGE_OFFSET 0 +#define PVT_VOLTAGE_VOLTAGE_FIELD \ + ((bitfield_field32_t) { .mask = PVT_VOLTAGE_VOLTAGE_MASK, .index = PVT_VOLTAGE_VOLTAGE_OFFSET }) + +// Temperature alarm to external pin. +#define PVT_TEMP_ALARM_EXTERNAL_REG_OFFSET 0x10024 +#define PVT_TEMP_ALARM_EXTERNAL_REG_RESVAL 0x3ff +#define PVT_TEMP_ALARM_EXTERNAL_THRESHOLD_MASK 0x3ff +#define PVT_TEMP_ALARM_EXTERNAL_THRESHOLD_OFFSET 0 +#define PVT_TEMP_ALARM_EXTERNAL_THRESHOLD_FIELD \ + ((bitfield_field32_t) { .mask = PVT_TEMP_ALARM_EXTERNAL_THRESHOLD_MASK, .index = PVT_TEMP_ALARM_EXTERNAL_THRESHOLD_OFFSET }) +#define PVT_TEMP_ALARM_EXTERNAL_STATUS_BIT 15 + +// Temperature alarm to engines +#define PVT_TEMP_ALARM_ENGINE_REG_OFFSET 0x10028 +#define PVT_TEMP_ALARM_ENGINE_REG_RESVAL 0x3ff +#define PVT_TEMP_ALARM_ENGINE_THRESHOLD_MASK 0x3ff +#define PVT_TEMP_ALARM_ENGINE_THRESHOLD_OFFSET 0 +#define PVT_TEMP_ALARM_ENGINE_THRESHOLD_FIELD \ + ((bitfield_field32_t) { .mask = PVT_TEMP_ALARM_ENGINE_THRESHOLD_MASK, .index = PVT_TEMP_ALARM_ENGINE_THRESHOLD_OFFSET }) +#define PVT_TEMP_ALARM_ENGINE_STATUS_BIT 15 + +// Mark the end of the address space +#define PVT_END_OF_RANGE_REG_OFFSET 0x1fffc +#define PVT_END_OF_RANGE_REG_RESVAL 0x0 +#define PVT_END_OF_RANGE_MARKER_BIT 0 + +#ifdef __cplusplus +} // extern "C" +#endif +#endif // _PVT_REG_DEFS_ +// End generated register defines for pvt diff --git a/src/hw/real_hw.cpp b/src/hw/real_hw.cpp new file mode 100644 index 00000000..7662df43 --- /dev/null +++ b/src/hw/real_hw.cpp @@ -0,0 +1,2 @@ +// This is used to determine that we're running the real hardware (not emulated) +int chia_vdf_is_emu = 0; diff --git a/src/hw/vdf_driver.cpp b/src/hw/vdf_driver.cpp new file mode 100644 index 00000000..15109165 --- /dev/null +++ b/src/hw/vdf_driver.cpp @@ -0,0 +1,628 @@ +#include +#include +#include +#include +#include +#include "vdf_driver.hpp" +#include "pll_freqs.hpp" + +#define VR_I2C_ADDR 0x38 +#define CS_I2C_ADDR 0x70 + +size_t VdfDriver::write_bytes(size_t size, size_t offset, uint8_t *buf, + uint32_t val) { + // Insert bytes from val in big endian order + uint8_t *p = (uint8_t *)&val; + for (unsigned i = 0; i < REG_BYTES; i++) { + buf[i + offset] = p[REG_BYTES - i - 1]; + } + + return size; +} + +size_t VdfDriver::write_bytes(size_t size, size_t offset, uint8_t *buf, + uint64_t val) { + write_bytes(REG_BYTES, offset, buf, (uint32_t)val); + write_bytes(REG_BYTES, offset + REG_BYTES, buf, (uint32_t)(val >> REG_BITS)); + return size; +} + +size_t VdfDriver::write_bytes(size_t size, size_t offset, uint8_t *buf, + mpz_t _val, size_t num_coeffs) { + mpz_t tmp, val; + mpz_inits(tmp, val, NULL); + + // Copy val so we don't alter it + mpz_set(val, _val); + + // Two's complement signed values + if (mpz_sgn(val) < 0) { + unsigned bits = num_coeffs * WORD_BITS + REDUNDANT_BITS; + mpz_t shifted; + mpz_init(shifted); + mpz_set_ui(shifted, 1); + mpz_mul_2exp(shifted, shifted, bits); // left shift + mpz_neg(val, val); + mpz_sub(val, shifted, val); + mpz_clear(shifted); + } + mpz_set(tmp, val); + + // Extract coefficients + uint32_t word_mask = (1UL << WORD_BITS) - 1; + std::vector coeffs; + for (size_t i = 0; i < num_coeffs - 1; i++) { + uint32_t coeff = mpz_get_ui(tmp) & word_mask; + coeffs.push_back(coeff); + mpz_tdiv_q_2exp(tmp, tmp, WORD_BITS); + } + // Last coeff does not get masked + coeffs.push_back(mpz_get_ui(tmp)); + + // Pack coefficients, with redundant bits + mpz_set_ui(tmp, 0); + for (int i = num_coeffs - 1; i >= 0; i--) { + mpz_mul_2exp(tmp, tmp, REDUNDANT_BITS); // left shift + mpz_add_ui(tmp, tmp, coeffs[i]); + } + + // Clear the buffer space + memset(buf + offset, 0, size); + + // For simplicity assume size is divisible by 32 bits + assert(size % REG_BYTES == 0); + + // Write 32 bits at a time + uint64_t mask = (1ULL << REG_BITS) - 1; + for (size_t count = 0; count < size; count += REG_BYTES) { + write_bytes(REG_BYTES, offset + count, buf, + (uint32_t)(mpz_get_ui(tmp) & mask)); + + mpz_tdiv_q_2exp(tmp, tmp, REG_BITS); + } + + mpz_clears(tmp, val, NULL); + return size; +} + +size_t VdfDriver::read_bytes(size_t size, size_t offset, uint8_t *buf, + uint32_t &val) { + // Reads bytes from buf into val in big endian order + uint8_t *p = (uint8_t *)&val; + for (unsigned i = 0; i < REG_BYTES; i++) { + p[REG_BYTES - i - 1] = buf[i + offset]; + } + + return size; +} + +size_t VdfDriver::read_bytes(size_t size, size_t offset, uint8_t *buf, + uint64_t &val) { + uint32_t val32; + read_bytes(REG_BYTES, offset, buf, val32); + val = val32; + + read_bytes(REG_BYTES, offset + REG_BYTES, buf, val32); + val |= ((uint64_t)val32) << REG_BITS; + + return size; +} + +size_t VdfDriver::read_bytes(size_t size, size_t offset, uint8_t *buf, + mpz_t val, size_t num_coeffs) { + mpz_t tmp, tmp2; + mpz_inits(tmp, tmp2, NULL); + + // Gather uint32s + std::vector words; + for (size_t count = 0; count < size; count += REG_BYTES) { + uint32_t word; + read_bytes(REG_BYTES, offset + count, buf, word); + words.push_back(word); + } + + // Pack redundant coeffs, most significant first + mpz_set_ui(tmp, 0); + for (int i = words.size() - 1; i >= 0; i--) { + mpz_mul_2exp(tmp, tmp, REG_BITS); // left shift + mpz_add_ui(tmp, tmp, words[i]); + } + + // Unpack and reduce + mpz_set_ui(val, 0); + uint32_t coeff_mask = (1UL << REDUNDANT_BITS) - 1; + for (size_t i = 0; i < num_coeffs && mpz_sgn(tmp) != 0; i++) { + uint32_t coeff = mpz_get_ui(tmp) & coeff_mask; + if (SIGNED && coeff >> (REDUNDANT_BITS - 1)) { + // Negative coeff, so two complement and subtract + coeff = (1 << REDUNDANT_BITS) - coeff; + mpz_set_ui(tmp2, coeff); + mpz_mul_2exp(tmp2, tmp2, WORD_BITS * i); // left shift + mpz_sub(val, val, tmp2); + } else { + mpz_set_ui(tmp2, coeff); + mpz_mul_2exp(tmp2, tmp2, WORD_BITS * i); // left shift + mpz_add(val, val, tmp2); + } + + mpz_tdiv_q_2exp(tmp, tmp, REDUNDANT_BITS); + } + + mpz_clears(tmp, tmp2, NULL); + return size; +} + +// Enable PVT +void VdfDriver::EnablePvt() { + uint32_t pvt_period = 83; + RegWrite(PVT_PERIOD_REG_OFFSET, pvt_period); + RegWrite(PVT_ENABLE_REG_OFFSET, (uint32_t)1); +} + +// Calculate temperature (C) from input code +double VdfDriver::ValueToTemp(uint32_t temp_code) { + double a4 = -0.000000000008929; + double a3 = 0.000000065714; + double a2 = -0.00018002; + double a1 = 0.33061; + double a0 = -60.9267; + + double x4 = pow((double) temp_code, 4.0); + double x3 = pow((double) temp_code, 3.0); + double x2 = pow((double) temp_code, 2.0); + + double temp = (a4 * x4) + (a3 * x3) + (a2 * x2) + + (a1 * (double) temp_code) + a0; + return temp; +} + +// Calculate code from temperature input (C) +uint32_t VdfDriver::TempToValue(double temp) { + double a4 = 0.000000027093; + double a3 = 0.00002108; + double a2 = 0.0076534; + double a1 = 3.7764; + double a0 = 205.64; + + double x4 = pow(temp, 4.0); + double x3 = pow(temp, 3.0); + double x2 = pow(temp, 2.0); + + uint32_t temp_code = (uint32_t)((a4 * x4) + (a3 * x3) + (a2 * x2) + + (a1 * temp) + a0 + 0.5); + + return temp_code; +} + +// Get temperature from PVT +double VdfDriver::GetPvtTemp() { + int ret_val; + uint32_t temp_data; + ret_val = RegRead(PVT_TEMPERATURE_REG_OFFSET, temp_data); + + if (ret_val != 0) { + fprintf(stderr, "GetPvtTemp bad reg read %d\n", ret_val); + return 0.0; + } + + double temp = ValueToTemp(temp_data); + + return temp; +} + +// Get voltage from PVT +double VdfDriver::GetPvtVoltage() { + int ret_val; + uint32_t voltage_data; + ret_val = RegRead(PVT_VOLTAGE_REG_OFFSET, voltage_data); + + if (ret_val != 0) { + fprintf(stderr, "GetPvtVoltage bad reg read %d\n", ret_val); + return 0.0; + } + + double a1 = 0.00054903; + double a0 = 0.45727; + + double voltage = (a1 * (double) voltage_data) + a0; + return voltage; +} + +// Get the programmed temperature external alarm (C) +double VdfDriver::GetTempAlarmExternal() { + int ret_val; + uint32_t temp_data; + ret_val = RegRead(PVT_TEMP_ALARM_EXTERNAL_REG_OFFSET, temp_data); + + if (ret_val != 0) { + fprintf(stderr, "GetTempAlarmExternal bad reg read %d\n", ret_val); + return 0.0; + } + + temp_data &= PVT_TEMP_ALARM_EXTERNAL_THRESHOLD_MASK; + + double temp = ValueToTemp(temp_data); + return temp; +} + +// Get the programmed temperature engine alarm (C) +double VdfDriver::GetTempAlarmEngine() { + int ret_val; + uint32_t temp_data; + ret_val = RegRead(PVT_TEMP_ALARM_ENGINE_REG_OFFSET, temp_data); + + if (ret_val != 0) { + fprintf(stderr, "GetTempAlarmEngine bad reg read %d\n", ret_val); + return 0.0; + } + + temp_data &= PVT_TEMP_ALARM_ENGINE_THRESHOLD_MASK; + + double temp = ValueToTemp(temp_data); + return temp; +} + +// Check if the temperature external alarm is triggered +bool VdfDriver::IsTempAlarmExternalSet() { + int ret_val; + uint32_t temp_data; + ret_val = RegRead(PVT_TEMP_ALARM_EXTERNAL_REG_OFFSET, temp_data); + + if (ret_val != 0) { + fprintf(stderr, "GetTempAlarmExternal bad reg read %d\n", ret_val); + return true; + } + + return (((temp_data >> PVT_TEMP_ALARM_EXTERNAL_STATUS_BIT) & 0x1) == 1); +} + +// Check if the temperature engine alarm is triggered +bool VdfDriver::IsTempAlarmEngineSet() { + int ret_val; + uint32_t temp_data; + ret_val = RegRead(PVT_TEMP_ALARM_ENGINE_REG_OFFSET, temp_data); + + if (ret_val != 0) { + fprintf(stderr, "GetTempAlarmEngine bad reg read %d\n", ret_val); + return true; + } + + return (((temp_data >> PVT_TEMP_ALARM_ENGINE_STATUS_BIT) & 0x1) == 1); +} + +bool VdfDriver::IsTempAlarmSet() { + bool eng_alarm = IsTempAlarmEngineSet(); + bool ext_alarm = IsTempAlarmExternalSet(); + return (eng_alarm || ext_alarm); +} + +// Set the PVT temperature external alarm threshold +bool VdfDriver::SetTempAlarmExternal(double temp) { + uint32_t temp_code = TempToValue(temp); + if ((temp_code < 0x0) || (temp_code > 0x3FF)) { + fprintf(stderr, "SetTempAlarmExternal bad code %X from temp %lf\n", + temp_code, temp); + return false; + } + RegWrite(PVT_TEMP_ALARM_EXTERNAL_REG_OFFSET, temp_code); + return true; +} + +// Set the PVT temperature engine alarm threshold +bool VdfDriver::SetTempAlarmEngine(double temp) { + uint32_t temp_code = TempToValue(temp); + if ((temp_code < 0x0) || (temp_code > 0x3FF)) { + fprintf(stderr, "SetTempAlarmEngine bad code %X from temp %lf\n", + temp_code, temp); + return false; + } + RegWrite(PVT_TEMP_ALARM_ENGINE_REG_OFFSET, temp_code); + return true; +} + +void VdfDriver::ResetPLL() { + RegWrite(CLOCK_CONTROL_REG_OFFSET, (uint32_t)0x1); // Reset +} + +bool VdfDriver::SetPLLFrequency(double frequency, uint32_t entry_index) { + if (frequency > pll_entries[VALID_PLL_FREQS - 1].freq) { + fprintf(stderr, "SetPLLFrequency frequency too high %lf\n", frequency); + return false; + } + + if (!entry_index) { + // Reset is necessary for the initial setting of frequency + Reset(10000); + while (frequency > pll_entries[entry_index].freq) { + entry_index++; + } + } + + uint32_t divr = pll_entries[entry_index].settings.divr; + uint32_t divfi = pll_entries[entry_index].settings.divfi; + uint32_t divq = pll_entries[entry_index].settings.divq; + + double ref_freq = 100.0 / (divr + 1); + if (ref_freq > pll_filter_ranges[VALID_PLL_FILTER_RANGES - 1]) { + fprintf(stderr, "SetPLLFrequency ref_freq too high %lf\n", ref_freq); + return false; + } + + uint32_t filter_range = 0; + while (ref_freq >= pll_filter_ranges[filter_range]) { + filter_range++; + } + + //printf("Frequency %lf should use entry %d - divr %d fi %d q %d range %d\n", + // frequency, entry_index, divr, divfi, divq, filter_range); + + RegWrite(CLOCK_CONTROL_REG_OFFSET, (uint32_t)0x1); // Reset + + RegWrite(CLOCK_PRE_DIVIDE_REG_OFFSET, divr); + RegWrite(CLOCK_FB_DIVIDE_INTEGER_REG_OFFSET, divfi); + RegWrite(CLOCK_POST_DIVIDE_REG_OFFSET, divq); + RegWrite(CLOCK_FILTER_RANGE_REG_OFFSET, filter_range); + + RegWrite(CLOCK_CONTROL_REG_OFFSET, (uint32_t)0x4); // New div + + // Wait for ack on new div + int ret_val; + uint32_t pll_status = 0; + int read_attempts = 0; + while (((pll_status >> CLOCK_STATUS_DIVACK_BIT) & 0x1) == 0) { + ret_val = RegRead(CLOCK_STATUS_REG_OFFSET, pll_status); + read_attempts++; + usleep(1000); + if ((read_attempts > 4) || (ret_val != 0)) { + fprintf(stderr, "SetPLLFrequency pll div never ack'd\n"); + return false; + } + } + + // Clear control reg + RegWrite(CLOCK_CONTROL_REG_OFFSET, (uint32_t)0x0); + + // Wait for lock + pll_status = 0; + read_attempts = 0; + while (((pll_status >> CLOCK_STATUS_LOCK_BIT) & 0x1) == 0) { + ret_val = RegRead(CLOCK_STATUS_REG_OFFSET, pll_status); + read_attempts++; + usleep(1000); + if ((read_attempts > 4) || (ret_val != 0)) { + fprintf(stderr, "SetPLLFrequency pll never locked\n"); + return false; + } + } + + // Remember current frequency + this->freq_idx = entry_index; + this->last_freq_update = vdf_get_cur_time(); + + return true; +} + +double VdfDriver::GetPLLFrequency() { + int ret_val; + uint32_t pll_status = 0; + ret_val = RegRead(CLOCK_CONTROL_REG_OFFSET, pll_status); + + if (ret_val != 0) { + fprintf(stderr, "GetPLLFrequency bad reg read %d\n", ret_val); + return 0.0; + } + + //printf("GetPLLFrequency status %x\n", pll_status); + if (((pll_status >> CLOCK_CONTROL_BYPASS_BIT) & 0x1) == 1) { + return 100.0; + } else if (((pll_status >> CLOCK_CONTROL_USEREF_BIT) & 0x1) == 1) { + return 100.0; + } else if (((pll_status >> CLOCK_CONTROL_RESET_BIT) & 0x1) == 1) { + return 0.0; + } + + uint32_t divr; + uint32_t divfi; + uint32_t divq; + + ret_val |= RegRead(CLOCK_PRE_DIVIDE_REG_OFFSET, divr); + ret_val |= RegRead(CLOCK_FB_DIVIDE_INTEGER_REG_OFFSET, divfi); + ret_val |= RegRead(CLOCK_POST_DIVIDE_REG_OFFSET, divq); + + //printf("Frequency registers - divr %d fi %d q %d\n", divr, divfi, divq); + + if (ret_val != 0) { + fprintf(stderr, "GetPLLFrequency bad reg read %d\n", ret_val); + return 0.0; + } + + double ref_freq = 100.0 / (divr + 1); + double vco_freq = ref_freq * (divfi + 1) * 4; + double freq = vco_freq / ((divq + 1) * 2); + return freq; +} + +int VdfDriver::Reset(uint32_t sleep_duration = 1000) { + int ret_val; + ret_val = ftdi.SetGPIO(GPIO_PORT2, 0); + if (ret_val != 0) { + fprintf(stderr, "Reset failed to set gpio, %d\n", ret_val); + return ret_val; + } + usleep(sleep_duration); + // Some boards will contain FT4222H chips with the OTP programmed such + // that GPIO2 (VDF_RST_N) is configured as an open drain output. In + // this case, GPIO2 powers up actively driving out low. In order to + // release reset, the GPIO2 needs to not be actively driven so the 1.8V + // 10Kohm pullup on the board causes VDF_RST_N to be high thus removing + // the reset condition. This is accomplished not by the method + // TriGPIO(port=2) but by SetGPIO(port=2, value=1). + // + // Other boards may not have their OTP programmed in which case, GPIO2 + // acts as a generic GPIO whose output enable and output value are + // fully under the control of software. In this case TriGPIO(port=2) + // removes the reset condition. Using SetGPIO(port=2, value=1) would + // actively drive high which could cause contention between low and + // high drivers in the event that another reset initiator (voltage + // regulator or reset button for instance) were driving reset low. + // + // A compromise here is to issue SetGPIO(port=2, value=1) followed + // immediately by TriGPIO(2). The hope is that the amount of potential + // low/high contention is limited in the event that the FT4222H has + // not had its OTP programmed. + ret_val = ftdi.SetGPIO(GPIO_PORT2, 1); + if (ret_val != 0) { + fprintf(stderr, "Reset failed to set gpio, %d\n", ret_val); + return ret_val; + } + ret_val = ftdi.TriGPIO(GPIO_PORT2); + if (ret_val != 0) { + fprintf(stderr, "Reset failed to tri-state gpio, %d\n", ret_val); + } + usleep(100000); + return ret_val; +} + +int VdfDriver::TurnFanOn() { + int ret_val; + ret_val = ftdi.SetGPIO(GPIO_PORT3, 1); + if (ret_val != 0) { + fprintf(stderr, "TurnFanOn failed to set gpio, %d\n", ret_val); + } + return ret_val; +} + +int VdfDriver::TurnFanOff() { + int ret_val; + ret_val = ftdi.SetGPIO(GPIO_PORT3, 0); + if (ret_val != 0) { + fprintf(stderr, "TurnFanOff failed to set gpio, %d\n", ret_val); + } + return ret_val; +} + +int VdfDriver::I2CWriteReg(uint8_t i2c_addr, uint8_t reg_addr, uint8_t data) { + int ret; + uint8_t wbuf[2]; + uint16_t bytesXfered; + + wbuf[0] = reg_addr; + wbuf[1] = data; + + ret = ftdi.i2c_TransmitX(1, 1, i2c_addr, wbuf, 2, bytesXfered ); + if (ret != FtdiDriver::I2C_RETURN_CODE_success) { + fprintf(stderr, "I2CWriteReg reg %x failed %d\n", reg_addr, ret); + return ret; + } else if (bytesXfered != 2) { + fprintf(stderr, "I2CWriteReg reg %x nack b %d\n", reg_addr, bytesXfered); + return FtdiDriver::I2C_RETURN_CODE_nack; + } + //printf("I2CWriteReg %x %x with %x OK\n", i2c_addr, reg_addr, data); + + return FtdiDriver::I2C_RETURN_CODE_success; +} + +int VdfDriver::I2CReadReg(uint8_t i2c_addr, uint8_t reg_addr, + size_t len, uint8_t* data) { + int ret; + uint8_t wbuf[1]; + uint16_t bytesXfered; + + wbuf[0] = reg_addr; + + ret = ftdi.i2c_TransmitX(1, 0, i2c_addr, wbuf, 1, bytesXfered); + if (ret != FtdiDriver::I2C_RETURN_CODE_success) { + fprintf(stderr, "I2CReadReg wr reg %x failed %d\n", reg_addr, ret); + return ret; + } else if (bytesXfered != 1) { + fprintf(stderr, "I2CReadReg wr reg %x nack b %d\n", reg_addr, bytesXfered); + return FtdiDriver::I2C_RETURN_CODE_nack; + } + + ret = ftdi.i2c_ReceiveX(1, 1, i2c_addr, data, len, bytesXfered); + if (ret != FtdiDriver::I2C_RETURN_CODE_success) { + fprintf(stderr, "I2CReadReg rd reg %x failed %d\n", reg_addr, ret); + return ret; + } else if (bytesXfered != len) { + fprintf(stderr, "I2CReadReg rd reg %x nack b %d\n", reg_addr, bytesXfered); + return FtdiDriver::I2C_RETURN_CODE_nack; + } + + if (len == 2) { + uint16_t d = (((uint16_t)data[0]) << 4) | (((uint16_t)data[1]) >> 4); + data[0] = d & 0xFF; + data[1] = (d >> 8) & 0xFF; + } + + return FtdiDriver::I2C_RETURN_CODE_success; +} + +double VdfDriver::GetBoardVoltage() { + uint8_t vid; + int ret_val = I2CReadReg(VR_I2C_ADDR, 0x7, 1, &vid); + if (ret_val != 0) { + fprintf(stderr, "GetBoardVoltage failed to read reg, %d\n", ret_val); + return 0.0; + } + + double vr_factor = 100000.0; + double vr_slope = 625.0; + double vr_intercept = 24375.0; + double voltage = (vr_intercept + (vid * vr_slope)) / vr_factor; + return voltage; +} + +int VdfDriver::SetBoardVoltage(double voltage) { + uint8_t vid; + double vr_factor = 100000.0; + uint32_t vr_slope = 625; + uint32_t vr_intercept = 24375; + vid = + (uint8_t)((((uint32_t)(voltage * vr_factor)) - vr_intercept) / vr_slope); + + if ((vid < 0x29) || (vid > 0x79)) { + fprintf(stderr, "SetBoardVoltage illegal vid %d for voltage %1.3f\n", + vid, voltage); + return 1; + } + + int ret_val = I2CWriteReg(VR_I2C_ADDR, 0x8, 0xe4); // Fixed compensation value + ret_val |= I2CWriteReg(VR_I2C_ADDR, 0x7, vid); // Voltage value + if (ret_val != 0) { + fprintf(stderr, "SetBoardVoltage failed to write reg, %d\n", ret_val); + } + + return ret_val; +} + +double VdfDriver::GetBoardCurrent() { + uint16_t cs; + + int ret_val = I2CWriteReg(CS_I2C_ADDR, 0xA, 0x2); + if (ret_val != 0) { + fprintf(stderr, "GetBoardCurrent failed to write reg, %d\n", ret_val); + return 0.0; + } + + usleep(10000); + + ret_val = I2CReadReg(CS_I2C_ADDR, 0x0, 2, (uint8_t*)(&cs)); + if (ret_val != 0) { + fprintf(stderr, "GetBoardCurrent failed to read reg, %d\n", ret_val); + return 0.0; + } + + double cs_vmax = 440.0; // mv + double cs_gain = 8.0; + double cs_adc_max = 4096.0; + + double c = ((double)cs * cs_vmax) / (cs_gain * cs_adc_max); + + return c; +} + +double VdfDriver::GetPower() { + double current = GetBoardCurrent(); + double voltage = GetBoardVoltage(); + return (current * voltage); +} diff --git a/src/hw/vdf_driver.hpp b/src/hw/vdf_driver.hpp new file mode 100644 index 00000000..e78a9b80 --- /dev/null +++ b/src/hw/vdf_driver.hpp @@ -0,0 +1,130 @@ +#ifndef VDF_DRIVER_HPP +#define VDF_DRIVER_HPP + +#include +#include "ftdi_driver.hpp" +#include "pvt.hpp" +#include "clock.hpp" +#include "hw_util.hpp" + +// Define the baseclass VDF driver +class VdfDriver { +public: + // Bit sizes for polynomial conversion + unsigned WORD_BITS; + unsigned REDUNDANT_BITS; + bool SIGNED; + + // CSR width + static const unsigned REG_BITS = 32; + static const unsigned REG_BYTES = 32/8; + static const uint32_t RESET_BIT = 0x10; + static const uint32_t CLOCK_BIT = 0x01; + static const uint32_t BURST_ADDR = 0x300000; + static const uint32_t VDF_ENGINE_STRIDE = 0x10000; + + FtdiDriver ftdi; + uint32_t freq_idx; + timepoint_t last_freq_update; + + VdfDriver(unsigned _WORD_BITS, unsigned _REDUNDANT_BITS, + bool _SIGNED) + : WORD_BITS(_WORD_BITS), REDUNDANT_BITS(_REDUNDANT_BITS), + SIGNED(_SIGNED) { + } + + virtual ~VdfDriver() {} + + // Functions for serializing to buffers + // Append size bytes to 'buf' starting at offset. Returns size. + size_t write_bytes(size_t size, size_t offset, uint8_t *buf, + uint32_t val); + size_t write_bytes(size_t size, size_t offset, uint8_t *buf, + uint64_t val); + size_t write_bytes(size_t size, size_t offset, uint8_t *buf, + mpz_t val, size_t num_coeffs); + + // Functions for deserializing from buffers + size_t read_bytes(size_t size, size_t offset, uint8_t *buf, + uint32_t &val); + size_t read_bytes(size_t size, size_t offset, uint8_t *buf, + uint64_t &val); + size_t read_bytes(size_t size, size_t offset, uint8_t *buf, + mpz_t val, size_t num_coeffs); + + // Returns the buffer size needed for a command + virtual size_t CmdSize() = 0; + + // Returns the buffer size needed for a status + virtual size_t StatusSize() = 0; + + // Perform a single dword register write, return 0 on success + int RegWrite(uint32_t addr, uint32_t data) { + uint32_t buf; + int stat; + write_bytes(REG_BYTES, 0, (uint8_t *)&buf, data); + stat = ftdi.WriteCmd(addr, (uint8_t *)&buf, REG_BYTES); + if (stat) { + fprintf(stderr, "ftdi.WriteCmd in RegWrite failed (error %d)\n",stat); + return stat; + }; + return 0; + } + + // Perform a single dword register read, return 0 on success + int RegRead(uint32_t addr, uint32_t &data) { + uint32_t buf; + int stat; + stat = ftdi.ReadCmd(addr, (uint8_t *)&buf, REG_BYTES); + if (stat) { + fprintf(stderr, "ftdi.ReadCmd in RegRead failed (error %d)\n",stat); + return stat; + }; + read_bytes(REG_BYTES, 0, (uint8_t *)&buf, data); + return 0; + } + + // Enable the engine at the provided address + void EnableEngine(unsigned control_csr) { + RegWrite(control_csr, (uint32_t)0); // Clear reset + RegWrite(control_csr, CLOCK_BIT); // Enable clock + } + + // Disable the engine at the provided address + void DisableEngine(unsigned control_csr) { + RegWrite(control_csr, (uint32_t)0); // Disable clock + RegWrite(control_csr, RESET_BIT); // Set reset + } + + // Reset the engine at the provided address + void ResetEngine(unsigned control_csr) { + DisableEngine(control_csr); + EnableEngine(control_csr); + } + + void EnablePvt(); + double ValueToTemp(uint32_t temp_code); + uint32_t TempToValue(double temp); + double GetPvtTemp(); + double GetPvtVoltage(); + double GetTempAlarmExternal(); + double GetTempAlarmEngine(); + bool IsTempAlarmExternalSet(); + bool IsTempAlarmEngineSet(); + bool IsTempAlarmSet(); + bool SetTempAlarmExternal(double temp); + bool SetTempAlarmEngine(double temp); + void ResetPLL(); + bool SetPLLFrequency(double frequency, uint32_t entry_index); + double GetPLLFrequency(); + int Reset(uint32_t sleep_duration); + int TurnFanOn(); + int TurnFanOff(); + int I2CWriteReg(uint8_t i2c_addr, uint8_t reg_addr, uint8_t data); + int I2CReadReg(uint8_t i2c_addr, uint8_t reg_addr, size_t len, uint8_t* data); + double GetBoardVoltage(); + int SetBoardVoltage(double voltage); + double GetBoardCurrent(); + double GetPower(); +}; +#endif diff --git a/src/integer_common.h b/src/integer_common.h index 361d35a9..4f015234 100644 --- a/src/integer_common.h +++ b/src/integer_common.h @@ -127,34 +127,50 @@ static bool allow_integer_constructor=false; //don't want static integers becaus struct integer { mpz_struct impl[1]; - ~integer() { + inline ~integer() { mpz_clear(impl); } - integer() { - assert(allow_integer_constructor); + inline integer() { + //assert(allow_integer_constructor); mpz_init(impl); } - integer(const integer& t) { + inline integer(mpz_t t) { + mpz_init_set(impl, t); + } + + inline integer(const integer& t) { mpz_init(impl); mpz_set(impl, t.impl); } - integer(integer&& t) { + inline integer(integer&& t) { mpz_init(impl); mpz_swap(impl, t.impl); } - explicit integer(int64 i) { - mpz_init(impl); - mpz_set_si(impl, i); + explicit inline integer(int i) { + mpz_init_set_si(impl, i); + } + + explicit inline integer(uint32_t i) { + mpz_init_set_ui(impl, i); + } + + explicit inline integer(int64 i) { + mpz_init_set_si(impl, i); + } + + explicit inline integer(uint64_t i) { + mpz_init_set_ui(impl, i); } explicit integer(const string& s) { mpz_init(impl); - int res=mpz_set_str(impl, s.c_str(), 0); - assert(res==0); + int res = mpz_set_str(impl, s.c_str(), 0); + assert(res == 0); + (void)res; } explicit integer(const std::vector v) { @@ -192,12 +208,12 @@ struct integer { return res; } - integer& operator=(const integer& t) { + inline integer& operator=(const integer& t) { mpz_set(impl, t.impl); return *this; } - integer& operator=(integer&& t) { + inline integer& operator=(integer&& t) { mpz_swap(impl, t.impl); return *this; } @@ -208,8 +224,9 @@ struct integer { } integer& operator=(const string& s) { - int res=mpz_set_str(impl, s.c_str(), 0); - assert(res==0); + int res = mpz_set_str(impl, s.c_str(), 0); + assert(res == 0); + (void)res; return *this; } diff --git a/src/proof_common.h b/src/proof_common.h index 0054e170..b7a4289c 100644 --- a/src/proof_common.h +++ b/src/proof_common.h @@ -114,14 +114,13 @@ form FastPowFormNucomp(form x, integer &D, integer num_iterations, integer &L, P return form::identity(D); form res = x; - int max_size = -D.impl->_mp_size / 2 + 1, i; + int max_size = -D.impl->_mp_size / 2, i; // Do exponentiation by squaring from top bits of exponent to bottom for (i = num_iterations.num_bits() - 2; i >= 0; i--) { nudupl_form(res, res, D, L); if (res.a.impl->_mp_size > max_size) { - // Reduce only when 'a' exceeds a half of the discriminant size by - // more than one limb + // Reduce only when 'a' exceeds a half of the discriminant size reducer.reduce(res); } diff --git a/src/prover_base.hpp b/src/prover_base.hpp new file mode 100644 index 00000000..2643a4a8 --- /dev/null +++ b/src/prover_base.hpp @@ -0,0 +1,115 @@ +#ifndef PROVER_BASE_H +#define PROVER_BASE_H + +#include + +#include "proof_common.h" +#include "util.h" + +class Prover { + public: + Prover(Segment segm, integer D) { + this->segm = segm; + this->D = D; + this->num_iterations = segm.length; + is_finished = false; + } + + virtual form* GetForm(uint64_t iteration) = 0; + virtual void start() = 0; + virtual void stop() = 0; + virtual bool PerformExtraStep() = 0; + virtual void OnFinish() = 0; + + bool IsFinished() { + return is_finished; + } + + form GetProof() { + return proof; + } + + uint64_t GetBlock(uint64_t i, uint64_t k, uint64_t T, integer& B) { + integer res = FastPow(2, T - k * (i + 1), B); + mpz_mul_2exp(res.impl, res.impl, k); + res = res / B; + auto res_vector = res.to_vector(); + return res_vector.empty() ? 0 : res_vector[0]; + } + + void GenerateProof() { + PulmarkReducer reducer; + + integer B = GetB(D, segm.x, segm.y); + integer L=root(-D, 4); + form id; + try { + id = form::identity(D); + } catch(std::exception& e) { + std::cout << "Warning: Could not create identity: " << e.what() << "\n"; + std::cout << "Discriminant: " << D.impl << "\n"; + std::cout << "Segment start:" << segm.start << "\n"; + std::cout << "Segment length:" << segm.length << "\n"; + std::cout << std::flush; + + return ; + } + uint64_t k1 = k / 2; + uint64_t k0 = k - k1; + form x = id; + + for (int64_t j = l - 1; j >= 0; j--) { + x = FastPowFormNucomp(x, D, integer(1 << k), L, reducer); + + std::vector ys((1 << k)); + for (uint64_t i = 0; i < (1UL << k); i++) + ys[i] = id; + + form *tmp; + uint64_t limit = num_iterations / (k * l); + if (num_iterations % (k * l)) + limit++; + for (uint64_t i = 0; i < limit; i++) { + if (num_iterations >= k * (i * l + j + 1)) { + uint64_t b = GetBlock(i*l + j, k, num_iterations, B); + if (!PerformExtraStep()) return; + tmp = GetForm(i); + nucomp_form(ys[b], ys[b], *tmp, D, L); + } + } + + for (uint64_t b1 = 0; b1 < (1UL << k1); b1++) { + form z = id; + for (uint64_t b0 = 0; b0 < (1UL << k0); b0++) { + if (!PerformExtraStep()) return; + nucomp_form(z, z, ys[b1 * (1 << k0) + b0], D, L); + } + z = FastPowFormNucomp(z, D, integer(b1 * (1 << k0)), L, reducer); + nucomp_form(x, x, z, D, L); + } + + for (uint64_t b0 = 0; b0 < (1UL << k0); b0++) { + form z = id; + for (uint64_t b1 = 0; b1 < (1UL << k1); b1++) { + if (!PerformExtraStep()) return; + nucomp_form(z, z, ys[b1 * (1 << k0) + b0], D, L); + } + z = FastPowFormNucomp(z, D, integer(b0), L, reducer); + nucomp_form(x, x, z, D, L); + } + } + reducer.reduce(x); + proof = x; + OnFinish(); + } + + protected: + Segment segm; + integer D; + form proof; + uint64_t num_iterations; + uint32_t k; + uint32_t l; + std::atomic is_finished; +}; +#endif // PROVER_BASE_H diff --git a/src/prover_parallel.hpp b/src/prover_parallel.hpp new file mode 100644 index 00000000..6967477e --- /dev/null +++ b/src/prover_parallel.hpp @@ -0,0 +1,110 @@ +#ifndef PROVER_PARALLEL_H +#define PROVER_PARALLEL_H + +#include + +#include "proof_common.h" +#include "util.h" + +#define PARALLEL_PROVER_N_THREADS 2 + +class ParallelProver : public Prover { + private: + static void ProofThread(ParallelProver *prover, uint8_t thr_idx, uint32_t start, uint32_t len) { + prover->ProvePart(thr_idx, start, len); + } + + void SquareFormN(form &f, uint64_t cnt, PulmarkReducer &reducer) + { + for (uint64_t i = 0; i < cnt; i++) { + nudupl_form(f, f, D, L); + reducer.reduce(f); + } + } + + void ProvePart(uint8_t thr_idx, uint32_t start, uint32_t len) { + PulmarkReducer reducer; + + uint64_t k1 = k / 2; + uint64_t k0 = k - k1; + form x = id; + int64_t end = start - len; + int64_t j; + + for (j = start - 1; j >= end; j--) { + x = FastPowFormNucomp(x, D, integer(1 << k), L, reducer); + + std::vector ys((1 << k)); + for (uint64_t i = 0; i < (1UL << k); i++) + ys[i] = id; + + form *tmp; + uint64_t limit = num_iterations / (k * l); + if (num_iterations % (k * l)) + limit++; + for (uint64_t i = 0; i < limit; i++) { + if (num_iterations >= k * (i * l + j + 1)) { + uint64_t b = GetBlock(i*l + j, k, num_iterations, B); + if (!PerformExtraStep()) return; + tmp = GetForm(i); + nucomp_form(ys[b], ys[b], *tmp, D, L); + } + } + + for (uint64_t b1 = 0; b1 < (1UL << k1); b1++) { + form z = id; + for (uint64_t b0 = 0; b0 < (1UL << k0); b0++) { + if (!PerformExtraStep()) return; + nucomp_form(z, z, ys[b1 * (1 << k0) + b0], D, L); + } + z = FastPowFormNucomp(z, D, integer(b1 * (1 << k0)), L, reducer); + nucomp_form(x, x, z, D, L); + } + + for (uint64_t b0 = 0; b0 < (1UL << k0); b0++) { + form z = id; + for (uint64_t b1 = 0; b1 < (1UL << k1); b1++) { + if (!PerformExtraStep()) return; + nucomp_form(z, z, ys[b1 * (1 << k0) + b0], D, L); + } + z = FastPowFormNucomp(z, D, integer(b0), L, reducer); + nucomp_form(x, x, z, D, L); + } + } + + SquareFormN(x, end * k, reducer); + x_vals[thr_idx] = x; + } + public: + ParallelProver(Segment segm, integer D) : Prover(segm, D) {} + void GenerateProof(); + + protected: + integer B; + integer L; + form id; + form x_vals[PARALLEL_PROVER_N_THREADS]; +}; + +void ParallelProver::GenerateProof() { + PulmarkReducer reducer; + + this->B = GetB(D, segm.x, segm.y); + this->L = root(-D, 4); + this->id = form::identity(D); + + uint32_t l0 = l / 2; + uint32_t l1 = l - l0; + std::thread proof_thr(ParallelProver::ProofThread, this, 0, l, l0); + ProvePart(1, l1, l1); + + proof_thr.join(); + if (!PerformExtraStep()) { + return; + } + nucomp_form(proof, x_vals[0], x_vals[1], D, L); + reducer.reduce(proof); + OnFinish(); +} + +#endif // PROVER_PARALLEL_H diff --git a/src/prover_slow.h b/src/prover_slow.h index de3f5108..b739c92b 100644 --- a/src/prover_slow.h +++ b/src/prover_slow.h @@ -47,7 +47,7 @@ form GenerateWesolowski(form &y, form &x_init, x = FastPowFormNucomp(x, D, integer(1 << k), L, reducer); std::vector ys((1 << k)); - for (uint64_t i = 0; i < (1 << k); i++) + for (uint64_t i = 0; i < (1UL << k); i++) ys[i] = form::identity(D); for (uint64_t i = 0; i < ceil(double(num_iterations) / (k * l)); i++) { @@ -56,17 +56,17 @@ form GenerateWesolowski(form &y, form &x_init, nucomp_form(ys[b], ys[b], intermediates[i], D, L); } } - for (uint64_t b1 = 0; b1 < (1 << k1); b1++) { + for (uint64_t b1 = 0; b1 < (1UL << k1); b1++) { form z = form::identity(D); - for (uint64_t b0 = 0; b0 < (1 << k0); b0++) { + for (uint64_t b0 = 0; b0 < (1UL << k0); b0++) { nucomp_form(z, z, ys[b1 * (1 << k0) + b0], D, L); } z = FastPowFormNucomp(z, D, integer(b1 * (1 << k0)), L, reducer); nucomp_form(x, x, z, D, L); } - for (uint64_t b0 = 0; b0 < (1 << k0); b0++) { + for (uint64_t b0 = 0; b0 < (1UL << k0); b0++) { form z = form::identity(D); - for (uint64_t b1 = 0; b1 < (1 << k1); b1++) { + for (uint64_t b1 = 0; b1 < (1UL << k1); b1++) { nucomp_form(z, z, ys[b1 * (1 << k0) + b0], D, L); } z = FastPowFormNucomp(z, D, integer(b0), L, reducer); diff --git a/src/provers.h b/src/provers.h index 02b1a945..c10a7ca4 100644 --- a/src/provers.h +++ b/src/provers.h @@ -1,119 +1,9 @@ #ifndef PROVERS_H #define PROVERS_H -#include - -#include "proof_common.h" -#include "util.h" +#include "prover_base.hpp" #include "callback.h" -class Prover { - public: - Prover(Segment segm, integer D) { - this->segm = segm; - this->D = D; - this->num_iterations = segm.length; - is_finished = false; - } - - virtual form* GetForm(uint64_t iteration) = 0; - virtual void start() = 0; - virtual void stop() = 0; - virtual bool PerformExtraStep() = 0; - virtual void OnFinish() = 0; - - bool IsFinished() { - return is_finished; - } - - form GetProof() { - return proof; - } - - uint64_t GetBlock(uint64_t i, uint64_t k, uint64_t T, integer& B) { - integer res = FastPow(2, T - k * (i + 1), B); - mpz_mul_2exp(res.impl, res.impl, k); - res = res / B; - auto res_vector = res.to_vector(); - return res_vector.empty() ? 0 : res_vector[0]; - } - - void GenerateProof() { - PulmarkReducer reducer; - - integer B = GetB(D, segm.x, segm.y); - integer L=root(-D, 4); - form id; - try { - id = form::identity(D); - } catch(std::exception& e) { - std::cout << "Warning: Could not create identity: " << e.what() << "\n"; - std::cout << "Discriminant: " << D.impl << "\n"; - std::cout << "Segment start:" << segm.start << "\n"; - std::cout << "Segment length:" << segm.length << "\n"; - std::cout << std::flush; - - return ; - } - uint64_t k1 = k / 2; - uint64_t k0 = k - k1; - form x = id; - - for (int64_t j = l - 1; j >= 0; j--) { - x = FastPowFormNucomp(x, D, integer(1 << k), L, reducer); - - std::vector ys((1 << k)); - for (uint64_t i = 0; i < (1 << k); i++) - ys[i] = id; - - form *tmp; - uint64_t limit = num_iterations / (k * l); - if (num_iterations % (k * l)) - limit++; - for (uint64_t i = 0; i < limit; i++) { - if (num_iterations >= k * (i * l + j + 1)) { - uint64_t b = GetBlock(i*l + j, k, num_iterations, B); - if (!PerformExtraStep()) return; - tmp = GetForm(i); - nucomp_form(ys[b], ys[b], *tmp, D, L); - } - } - - for (uint64_t b1 = 0; b1 < (1 << k1); b1++) { - form z = id; - for (uint64_t b0 = 0; b0 < (1 << k0); b0++) { - if (!PerformExtraStep()) return; - nucomp_form(z, z, ys[b1 * (1 << k0) + b0], D, L); - } - z = FastPowFormNucomp(z, D, integer(b1 * (1 << k0)), L, reducer); - nucomp_form(x, x, z, D, L); - } - - for (uint64_t b0 = 0; b0 < (1 << k0); b0++) { - form z = id; - for (uint64_t b1 = 0; b1 < (1 << k1); b1++) { - if (!PerformExtraStep()) return; - nucomp_form(z, z, ys[b1 * (1 << k0) + b0], D, L); - } - z = FastPowFormNucomp(z, D, integer(b0), L, reducer); - nucomp_form(x, x, z, D, L); - } - } - reducer.reduce(x); - proof = x; - OnFinish(); - } - - protected: - Segment segm; - integer D; - form proof; - uint64_t num_iterations; - uint32_t k; - uint32_t l; - std::atomic is_finished; -}; - class OneWesolowskiProver : public Prover { public: OneWesolowskiProver(Segment segm, integer D, form* intermediates, std::atomic& stop_signal) diff --git a/src/tl_emu.py b/src/tl_emu.py new file mode 100644 index 00000000..e707a37f --- /dev/null +++ b/src/tl_emu.py @@ -0,0 +1,168 @@ +import chiavdf + +import asyncio, random, sys + +# Overview of Timelord <-> VDF client protocol + +# Timelord -> VDF client +# Session init: "T", "S" or "N" (prover type) +# Initial value: "" "" "" "" +# ("" in decimal (3 digits), "" parsable by GMP) +# "" as 1 byte, "" as is + +# VDF client -> Timelord +# "OK" + +# Timelord -> VDF client +# Iters: iters size "NN" (decimal) and iter count "NNNN..." (decimal) +# "010" to stop + +# VDF client -> Timelord (if proof requested) +# "" (4 bytes, big endian) +# "" (hex encoded) +# Proof items (bytes): iters (8), y size (8), y, witness type (1), proof +# proof for witness type=0: proof value (100 bytes as compressed form) + +# VDF client -> Timelord +# "STOP" + +# Timelord -> VDF client +# "ACK" + +top_seed = 0xae0666f161fed1a +DISCR_BITS = 1024 +MAX_CONNS = 3 +INIT_FORM = b"\x08" + b"\x00" * 99 +MIN_ITERS = 500 * 1000 +MAX_ITERS = 50 * 1000**2 +MIN_WAIT = 5 +MAX_WAIT = 100 +N_PROOFS = 4 + +def get_discr(conn_idx, cnt): + s = (top_seed << 16) + (conn_idx << 14) + cnt + return chiavdf.create_discriminant(s.to_bytes(16, 'big'), DISCR_BITS) + +conn_idxs = set() +cnts = [0 for i in range(MAX_CONNS)] + +def get_conn_idx(): + for i in range(MAX_CONNS): + if i not in conn_idxs: + conn_idxs.add(i) + return i + raise ValueError("Too many connections!") + +def clear_conn_idx(idx): + conn_idxs.remove(idx) + +async def send_msg(w, msg): + #print("Sending:", msg) + w.write(msg) + await w.drain() + +def decode_resp(data): + return data.decode(errors="replace") + +async def read_conn(reader, writer, d, idx, task): + try: + while True: + data = await reader.read(4) + if data == b"STOP": + await send_msg(writer, b"ACK") + print("Closing connection for VDF %d" % (idx,)) + clear_conn_idx(idx) + writer.close() + task.cancel() + break + + size = int.from_bytes(data, 'big') + if not size: + raise ValueError("Empty proof!") + + data = await reader.readexactly(size) + data = bytes.fromhex(data.decode()) + iters = int.from_bytes(data[:8], 'big') + y_size = int.from_bytes(data[8:16], 'big') + y = data[16:16+y_size] + w_type = int.from_bytes(data[16+y_size:17+y_size], 'big') + proof = data[17+y_size:] + + try: + is_valid = chiavdf.verify_n_wesolowski(d, INIT_FORM, y + proof, iters, 1024, w_type) + except Exception as e: + print("Proof verification failed for VDF %d, iters=%d" % (idx, iters)) + print(e) + is_valid = False + if is_valid: + print("Proof for VDF %d, iters=%d is VALID" % (idx, iters)) + else: + print("\n!!!!!\nInvalid proof for VDF %d, iters=%d!\n!!!!!" % + (idx, iters)) + + except Exception as e: + print("VDF %d error (read_conn):" % (idx,), e) + clear_conn_idx(idx) + writer.close() + task.cancel() + +async def init_conn(reader, writer, idx): + d = get_discr(idx, cnts[idx]).encode() + + await send_msg(writer, b"T") + msg = b"%03d%s" % (len(d), d) + await send_msg(writer, msg) + msg = b"%c%s" % (len(INIT_FORM), INIT_FORM) + await send_msg(writer, msg) + print("Sent initial value for VDF %d, cnt %d" % (idx, cnts[idx])) + print(" d = %s" % (d.decode(),)) + + ok = decode_resp(await reader.read(2)) + if ok != "OK": + raise ValueError("Bad response from VDF client: %s" % (ok,)) + + task = asyncio.current_task() + read_task = asyncio.create_task(read_conn(reader, writer, d, idx, task)) + wait_sec = random.randint(MIN_WAIT, MAX_WAIT) + print("Waiting %d sec for VDF %d, cnt %d" % (wait_sec, idx, cnts[idx])) + cnts[idx] += 1 + try: + await asyncio.sleep(1) + iters_list = [random.randint(MIN_ITERS, MAX_ITERS) for _ in range(N_PROOFS)] + iters_enc = "".join("%02d%d" % (len(str(n)), n) for n in iters_list) + print("Requesting proofs for iters:", iters_list) + await send_msg(writer, iters_enc.encode()) + + await asyncio.sleep(wait_sec) + + await send_msg(writer, b"010") + print("Stopping VDF", idx) + + await read_task + except asyncio.CancelledError: + print("VDF %d task cancelled" % (idx,)) + + +async def conn_wrapper(r, w): + idx = get_conn_idx() + try: + await init_conn(r, w, idx) + except Exception as e: + print("VDF %d error:" % (idx,), e) + +async def main(): + seed = 1 + if len(sys.argv) > 1: + seed = int(sys.argv[1]) + random.seed(seed) + server = await asyncio.start_server(conn_wrapper, '127.0.0.1', 8000) + + addrs = ', '.join(str(sock.getsockname()) for sock in server.sockets) + print(f'Serving on {addrs}') + + await server.serve_forever() + +try: + asyncio.run(main()) +except KeyboardInterrupt: + print("Stopped") diff --git a/src/vdf_base.cpp b/src/vdf_base.cpp new file mode 100644 index 00000000..fd332c15 --- /dev/null +++ b/src/vdf_base.cpp @@ -0,0 +1,22 @@ +#include "verifier.h" +#include "prover_slow.h" +#include "alloc.hpp" +#include "prover_base.hpp" +#include "prover_parallel.hpp" + +void VdfBaseInit(void) +{ + init_gmp(); + fesetround(FE_TOWARDZERO); +} + +bool dummy_form_check_valid(form &f, integer &d) +{ + return f.check_valid(d); +} + +form dummy_get_proof(ParallelProver &p) +{ + p.GenerateProof(); + return p.GetProof(); +} diff --git a/src/vdf_base.hpp b/src/vdf_base.hpp new file mode 100644 index 00000000..dba3c29b --- /dev/null +++ b/src/vdf_base.hpp @@ -0,0 +1,325 @@ +#ifndef VDF_BASE_H +#define VDF_BASE_H + +#if VDF_MODE==0 + #define NDEBUG +#endif + +#include "Reducer.h" +#include + +//#include +//#include "include.h" + +#include +#include +#include +#include + +#ifndef _WIN32 +#define USED __attribute__((used)) +#else +#define USED +#endif + +//using namespace std; +using std::string, std::vector; + +typedef int64_t int64; +typedef uint64_t uint64; + +void VdfBaseInit(void); + +typedef __mpz_struct mpz_struct; +struct integer { +public: + mpz_struct impl[1]; + + inline ~integer() { + mpz_clear(impl); + } + + inline integer() { + //assert(allow_integer_constructor); + mpz_init(impl); + } + + inline integer(mpz_t t) { + mpz_init_set(impl, t); + } + + inline integer(const integer& t) { + mpz_init(impl); + mpz_set(impl, t.impl); + } + + inline integer(integer&& t) { + mpz_init(impl); + mpz_swap(impl, t.impl); + } + + explicit inline integer(int i) { + mpz_init_set_si(impl, i); + } + + explicit inline integer(uint32_t i) { + mpz_init_set_ui(impl, i); + } + + explicit inline integer(int64 i) { + mpz_init_set_si(impl, i); + } + + explicit inline integer(uint64_t i) { + mpz_init_set_ui(impl, i); + } + + explicit integer(const string& s); + + explicit integer(const std::vector v); + + //lsb first + explicit integer(const vector& data); + + integer(const uint8_t *bytes, size_t size); + + //lsb first + vector to_vector() const; + + vector to_bytes() const; + + inline integer& operator=(const integer& t) { + mpz_set(impl, t.impl); + return *this; + } + + inline integer& operator=(integer&& t) { + mpz_swap(impl, t.impl); + return *this; + } + + integer& operator=(int64 i); + + integer& operator=(const string& s); + + void set_bit(int index, bool value); + + bool get_bit(int index); + + USED string to_string() const; + + string to_string_dec() const; + + integer& operator+=(const integer& t); + + integer operator+(const integer& t) const; + + integer& operator-=(const integer& t); + + integer operator-(const integer& t) const; + + integer& operator*=(const integer& t); + + integer operator*(const integer& t) const; + + integer& operator<<=(int i); + + integer operator<<(int i) const; + + integer operator-() const; + + integer& operator/=(const integer& t); + + integer operator/(const integer& t) const; + + integer& operator>>=(int i); + + integer operator>>(int i) const; + + //this is different from mpz_fdiv_r because it ignores the sign of t + integer& operator%=(const integer& t); + + integer operator%(const integer& t) const; + + integer fdiv_r(const integer& t) const; + + bool prime() const; + + bool operator<(const integer& t) const; + + bool operator<=(const integer& t) const; + + bool operator==(const integer& t) const; + + bool operator>=(const integer& t) const; + + bool operator>(const integer& t) const; + + bool operator!=(const integer& t) const; + + bool operator<(int i) const; + + bool operator<=(int i) const; + + bool operator==(int i) const; + + bool operator>=(int i) const; + + bool operator>(int i) const; + + bool operator!=(int i) const; + + int num_bits() const; +}; + +integer root(const integer& t, int n); +integer CreateDiscriminant(std::vector& seed, int length = 1024); + +struct form { + integer a; + integer b; + integer c; + + static form from_abd(const integer& t_a, const integer& t_b, const integer& d); + static form identity(const integer& d); + static form generator(const integer& d) { + return from_abd(integer(2), integer(1), d); + } + void reduce(); + + bool is_reduced(); + + form inverse() const; + + bool check_valid(const integer& d); + + void assert_valid(const integer& d); + + bool operator==(const form& f) const; + + bool operator<(const form& f) const; + + //assumes this is normalized (c has the highest magnitude) + //the inverse has the same hash + int hash() const; +}; + + +class PulmarkReducer { + ClassGroupContext *t; + Reducer *reducer; + + public: + PulmarkReducer() { + t=new ClassGroupContext(4096); + reducer=new Reducer(*t); + } + + ~PulmarkReducer() { + delete(reducer); + delete(t); + } + + void reduce(form &f) { + mpz_set(t->a, f.a.impl); + mpz_set(t->b, f.b.impl); + mpz_set(t->c, f.c.impl); + + reducer->run(); + + mpz_set(f.a.impl, t->a); + mpz_set(f.b.impl, t->b); + mpz_set(f.c.impl, t->c); + } +}; + +struct Segment { + uint64_t start; + uint64_t length; + form x; + form y; + form proof; + bool is_empty; + + Segment() { + is_empty = true; + } + + Segment(uint64_t start, uint64_t length, form& x, form& y) { + this->start = start; + this->length = length; + this->x = x; + this->y = y; + is_empty = false; + } + + bool IsWorseThan(Segment& other); + + int GetSegmentBucket(); +}; + +class Prover { + public: + Prover(Segment segm, integer D) { + this->segm = segm; + this->D = D; + this->num_iterations = segm.length; + is_finished = false; + } + + virtual form* GetForm(uint64_t iteration) = 0; + virtual void start() = 0; + virtual void stop() = 0; + virtual bool PerformExtraStep() = 0; + virtual void OnFinish() = 0; + + bool IsFinished() { + return is_finished; + } + + form GetProof() { + return proof; + } + + uint64_t GetBlock(uint64_t i, uint64_t k, uint64_t T, integer& B); + + void GenerateProof(); + + protected: + Segment segm; + integer D; + form proof; + uint64_t num_iterations; + uint32_t k; + uint32_t l; + std::atomic is_finished; +}; + +#define PARALLEL_PROVER_N_THREADS 2 + +class ParallelProver : public Prover { + public: + ParallelProver(Segment segm, integer D) : Prover(segm, D) {} + void GenerateProof(); + protected: + integer B; + integer L; + form id; + form x_vals[PARALLEL_PROVER_N_THREADS]; +}; + +void nudupl_form(form &a, form &b, integer &D, integer &L); + +integer GetB(const integer& D, form &x, form& y); + +form GenerateWesolowski(form &y, form &x_init, + integer &D, PulmarkReducer& reducer, + std::vector& intermediates, + uint64_t num_iterations, + uint64_t k, uint64_t l); + +void VerifyWesolowskiProof(integer &D, form x, form y, form proof, uint64_t iters, bool &is_valid); + +void Int64ToBytes(uint8_t *result, uint64_t input); +void Int32ToBytes(uint8_t *result, uint32_t input); +#endif // VDF_BASE_H diff --git a/src/vdf_new.h b/src/vdf_new.h index 2d273ae0..84030cec 100644 --- a/src/vdf_new.h +++ b/src/vdf_new.h @@ -155,9 +155,7 @@ struct form { return res; } - bool check_valid(const integer& d) { - return b*b-integer(4)*a*c==d; - } + bool check_valid(const integer& d); void assert_valid(const integer& d) { assert(check_valid(d)); @@ -179,6 +177,10 @@ struct form { } }; +bool form::check_valid(const integer& d) { + return b*b-integer(4)*a*c==d; +} + integer generate_discriminant(int num_bits, int seed=-1) { integer res=rand_integer(num_bits, seed); while (true) { @@ -206,7 +208,6 @@ integer three_gcd(integer a, integer b, integer c) { gcd_res test_gcd(integer a_signed, integer b_signed, int index=0) { bool a_negative=a_signed