diff options
| author | eunhhu <[email protected]> | 2026-10-13 05:08:06 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-10-13 05:08:06 +0100 |
| commit | 41a2e5c65dc92a0c47212efcb7f5dfef8443f9b2 (patch) | |
| tree | 5c3354e41a5f15b253d333de24dd1bae4037c77b /docs | |
| parent | 5a44af0308017f4e7b54a8ff6ccdc797b5d94015 (diff) | |
| download | pure-41a2e5c65dc92a0c47212efcb7f5dfef8443f9b2.tar.gz pure-41a2e5c65dc92a0c47212efcb7f5dfef8443f9b2.zip | |
Research 140, 027's stage 1 measured: SHA-256 written in aup (its examples/sha256.aup) right for FIPS 180-2's examples and 138 more messages on every path, in make check against hashlib; 52 lines against Python's 28 (the bar missed: no formatting, no bytes joined or sliced, no lists as values, moved into stage 2), 176 times C's time and 0.43 of plain Python's (1,591 ns a byte; a block's 19,129 instructions, 39% of them the inlined fn's literals not folded); 044's check, time.c against the same algorithm in C (digests compared first) and the Python reference
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/design/027-computation-core.md | 10 | ||||
| -rw-r--r-- | docs/research/140-spec-suite.md | 60 |
2 files changed, 70 insertions, 0 deletions
diff --git a/docs/design/027-computation-core.md b/docs/design/027-computation-core.md index 4df67f9..f26f2d5 100644 --- a/docs/design/027-computation-core.md +++ b/docs/design/027-computation-core.md @@ -3,6 +3,11 @@ 작성일: 2026-10-13. 상태: 설계와 단계. [026](026-app-contract.md)이 얼릴 계약 안에서 계산의 언어를 다시 세운다. 잴 도구는 [140](../research/140-spec-suite.md)의 명세 묶음이다. 1.0 전이라 호환은 챙기지 않는다. 사용자의 말: "진행해" (2026-10-13). +1단계를 만들었다([140](../research/140-spec-suite.md)의 뒷절). +- aup로 쓴 SHA-256이 공식 벡터를 세 실행 길에서 모두 지난다. +- 줄 수는 막대에 못 미쳤다(aup 52 대 파이썬 28). 남은 차이는 형식 지정, 바이트 잇기와 자르기, 값으로서의 리스트다. 이것들을 2단계에 더했다. +- 시간은 C의 176배, 순수 파이썬의 0.43배다. + ## 쉬운 말로 - **지금의 꼴.** aup와 Pure는 패턴마다 종류와 명령을 둔다. 커서, 인덱스, 문서, 표 보기, 메시지의 행이 각각 따로다. 그래서 세상의 @@ -129,6 +134,11 @@ - 재귀하는 fn과 `while`을 둔다. Pure에는 부르기와 돌아가기, 함수마다의 검증이 생긴다. - `for c in t`로 글자(코드 포인트)를 읽는다. - 메시지의 필드가 아무 값을 가진다. JSON의 배열과 객체가 곧 리스트와 레코드다. +- 1단계의 SHA-256이 길었던 까닭을 여기서 푼다. + - 형식 지정(`{x:08x}`, `{price:.2}`) + - 바이트 값을 잇고 자르기(`b + c`, `b[a .. c]`)와 바이트를 담는 `let` + - 값으로서의 리스트: 블록 안에서 짓고 다시 짓는다 + - fn을 펼칠 때 리터럴 인자를 접기: 구현의 일이다. 140이 블록당 명령의 39%를 fn 호출의 몫으로 쟀다 - 먼저 이벤트와 보기의 값(메모리 안)에서 한다. 상태는 3단계다. - **막대.** - JSON 파서가 JSONTestSuite의 `y_`를 모두 받고 `n_`을 모두 거절한다. `i_`는 정한 쪽을 적는다. diff --git a/docs/research/140-spec-suite.md b/docs/research/140-spec-suite.md index 24d488a..4b799df 100644 --- a/docs/research/140-spec-suite.md +++ b/docs/research/140-spec-suite.md @@ -118,6 +118,66 @@ - **메시지의 행은 중첩의 땜질인가?** 레코드의 리스트를 메시지에만 허락한 것은 중첩이 없어서 낸 길로 보인다. 중첩이 들어오면 따로 둘 까닭이 없다. +## 027의 1단계: SHA-256 (2026-10-13) + +[027](../design/027-computation-core.md)의 1단계를 만들었다. +- **Pure.** 명령 넷이다. + - `I64_BITS`: and, or, xor, 두 시프트. `~x`는 xor −1이다. + - `BYTE_AT`: 자리의 바이트. + - `BYTES_OF`: i64 리스트의 바이트. + - `INDEX_AT`: 자리의 항목. 끝을 넘으면 멈춰 서지 않고 `not_found`다. +- **aup.** + - 16진 리터럴, 파이썬의 우선순위를 따르는 비트 연산자, `b[i]` + - `list of i64`(`number`, `bool`, `text`)와 그 리터럴, 자리로 읽고 쓰기, `bytes(xs)` + - 한 번에 주기 `a, b = x, y`와 `let a, b = …` +- **SHA-256.** aup의 `examples/sha256.aup`에 썼다. + +**맞음.** 공식 벡터를 Pure 안에서 돌려 맞는지 본다. +- 대조한 메시지는 142개다: FIPS 180-2의 예 넷("", "abc", 448비트, 896비트), 채움의 모든 경계를 덮는 길이 0–129, 255–32,000바이트. +- 다이제스트가 세 실행 길(묶음, 실행기만, 기계어)과 기본 길에서 모두 `hashlib`와 같다. +- 이 대조는 Pure의 `make check`(`module_assumptions`, 메시지 135개)에 들어갔다. +- aup의 검사에는 다음이 들어갔다. + - 진단 12건 + - 받아들이는 꼴 하나 + - 무작위 비트 식 192개: 사건 768개, 그중 넘침과 한도 실패 196개가 파이썬의 정수와 같다 + - 바이트와 리스트의 앱 하나 +- Pure 단위 시험(`bits_and_bytes`)은 비트 연산의 끝값 27개, 바이트 읽기 11개, 거절 7개를 본다. + +**막대.** + +| 막대 | 잰 것 | | +|---|---|---| +| 공식 벡터 모두 | 142/142, 세 길 | 지남 | +| 줄 수 ≤ 파이썬 참조 | aup 52줄(닫는 괄호만인 줄 7) 대 파이썬 28줄 | **못 미침** | +| C 대비 시간 | 65,536바이트에서 바이트당 1,591 ns 대 C 9.0 ns: **176배**. 순수 파이썬은 3,708 ns(Pure가 2.3배 빠름) | 기록(막대 없음) | +| 기존 일의 명령 수 | 아래 | 아래 | + +원본: `research/experiments/044-specs/` +- `check.py`: 맞음과 줄 수 +- `time.c`: 같은 바이트로 C와 견준 시간. 다이제스트가 같아야 잰다. +- `sha256.py`: 파이썬 참조 +- `2026-10-13-sha256.jsonl`: 잰 수 + +**줄을 길게 한 것.** 처음 쓴 것은 72줄이었다. 한 번에 주기가 없어서 상태 여덟 개를 옮기는 데만 24줄이 들었다. 그것을 1단계에 +넣어(싸고 범용이다) 52줄이 됐다. 남은 차이는 다음이다. +- 형식 지정이 없다. 16진 다이제스트에 7줄이 들었고, 파이썬은 `f'{x:08x}'` 한 줄이다. +- 바이트를 잇거나 자르지 못한다. 채움에 fn 하나와 바이트마다의 조건이 들었고, 낱말 만들기에 5줄이 들었다. 파이썬은 `data + b'\x80' + …`와 + `int.from_bytes` 한 줄씩이다. +- 리스트를 값으로 짓지 못한다. 메시지 스케줄을 블록마다 다시 만들지 못하고, 64칸을 미리 채워 덮어쓴다. +- `let`의 리스트는 핸들러 맨 바깥에만 둔다. 그래서 해시값을 리스트 대신 이름 여덟 개에 두었다. +- 닫는 괄호의 줄이 7줄이다. + +앞의 넷은 값의 일이라 2단계에 넣는다. 027의 2단계에 형식 지정(16진, 자릿수), 바이트 잇기와 자르기, 값으로서의 리스트를 더한다. + +**시간이 가는 곳.** 블록 하나에 Pure 명령 19,129개가 든다. +- 비트 연산이 21%다. +- fn 호출의 몫(인자를 꺼내는 PICK 16%, 리터럴 CONST 16%, 시프트 수를 바꾸는 I64_FROM 7%)이 39%다. +- `rotr(x, 7)`의 7은 상수인데도 fn을 펼칠 때 접히지 않아, `32 - n`을 매번 수로 계산하고 i64로 바꾼다. 인라인에서 리터럴 인자를 접으면 + 명령의 3분의 1 남짓이 줄 것으로 본다. 컴파일러의 구현 일이다. +- 명령 하나에 약 5.3 ns가 든다. 값의 칸(`Slot`)이 바이트 참조를 함께 들어 PICK마다 48바이트를 옮기는 꼴이다. +- 기계어 계층은 이 루프를 빠르게 하지 못했다. `PURE_JIT=all`이어도 시간이 같다. 새 명령마다 실행기의 걸음을 불러서다. +- 바이트와 비트의 일을 빠르게 하는 것은 핵이 선 뒤의 일이다(027). 그 과녁은 이제 수치 루프가 아니라 이런 일이다. + ## 착수 기준 (다음 일) - **바꿀 결정.** 계산의 핵을 설계한다(027). 위 표의 여덟 후보 가운데 무엇을 어떤 모양으로 받을지 정한다. |
