อ่าน 8 นาที
แอลซีเอ็มเอ
LZMA ( อัลกอริทึมลูกโซ่ Lempel–Ziv–Markov [ 1 ] ) เป็น อัลกอริทึม การบีบอัดข้อมูลแบบไม่สูญเสียข้อมูล ที่พัฒนาขึ้นตั้งแต่ปี 1998 โดย Igor Pavlov ผู้พัฒนา 7-Zip มีการใช้ใน รูปแบบ 7z...
แอลซีเอ็มเอ
LZMA ( อัลกอริทึมลูกโซ่ Lempel–Ziv–Markov [ 1 ] ) เป็น อัลกอริทึม การบีบอัดข้อมูลแบบไม่สูญเสียข้อมูลที่พัฒนาขึ้นตั้งแต่ปี 1998 โดย Igor Pavlov ผู้พัฒนา7-Zipมีการใช้ใน รูปแบบ 7zของโปรแกรมบีบอัด 7-Zip ตั้งแต่ปี 2001 [ 2 ]อัลกอริทึมนี้ใช้ รูปแบบ การบีบอัดแบบพจนานุกรมที่ค่อนข้างคล้ายกับ อัลกอริทึม LZ77ที่เผยแพร่โดยAbraham LempelและJacob Zivในปี 1977 และมีอัตราส่วนการบีบอัดสูง (โดยทั่วไปสูงกว่าbzip2 ) [ 3 ] [ 4 ]และขนาดพจนานุกรมการบีบอัดที่แปรผันได้ (สูงสุด 4 GB ) [ 5 ]ในขณะที่ยังคงรักษาความเร็วในการคลายการบีบอัดที่คล้ายกับอัลกอริทึมการบีบอัดอื่นๆ ที่ใช้กันทั่วไป[ 6 ]
LZMA2เป็นรูปแบบคอนเทนเนอร์ที่เรียบง่ายซึ่งอนุญาตให้มีการบีบอัดและคลายการบีบอัดแบบมัลติเธรดโดยใช้สตรีม LZMA แยกกันหลายรายการ มีการใช้ทั้งในรูปแบบ 7z และ xz [ 7 ]
ภาพรวม
LZMA ใช้ อัลกอริธึม การบีบอัดพจนานุกรม (ซึ่งเป็นรูปแบบหนึ่งของLZ77ที่มีขนาดพจนานุกรมขนาดใหญ่และรองรับระยะการจับคู่ที่ใช้ซ้ำเป็นพิเศษ) จากนั้นเอาต์พุตจะถูกเข้ารหัสด้วยตัวเข้ารหัสช่วงโดยใช้แบบจำลองที่ซับซ้อนเพื่อทำนายความน่าจะเป็นของแต่ละบิต ตัวบีบอัดพจนานุกรมจะค้นหาการจับคู่โดยใช้โครงสร้างข้อมูลพจนานุกรมที่ซับซ้อน และสร้างกระแสของสัญลักษณ์ตัวอักษรและการอ้างอิงวลี ซึ่งจะถูกเข้ารหัสทีละบิตโดยตัวเข้ารหัสช่วง: มีการเข้ารหัสหลายแบบที่เป็นไปได้ และ มีการใช้อัลกอริธึม การเขียนโปรแกรมแบบไดนามิกเพื่อเลือกแบบที่เหมาะสมที่สุดภายใต้การประมาณค่าบางอย่าง[ 8 ]
ก่อน LZMA โมเดลการเข้ารหัสส่วนใหญ่เป็นแบบไบต์ล้วนๆ (กล่าวคือ พวกมันเข้ารหัสแต่ละบิตโดยใช้เพียงลำดับของบริบทเพื่อแสดงการพึ่งพาของบิตก่อนหน้าจากไบต์เดียวกัน) นวัตกรรมหลักของ LZMA คือ แทนที่จะใช้โมเดลแบบไบต์ทั่วไป โมเดลของ LZMA ใช้บริบทเฉพาะสำหรับบิตฟิลด์ในแต่ละการแสดงของตัวอักษรหรือวลี: ซึ่งเกือบจะง่ายเหมือนโมเดลแบบไบต์ทั่วไป แต่ให้การบีบอัดที่ดีกว่ามากเพราะหลีกเลี่ยงการผสมบิตที่ไม่เกี่ยวข้องกันในบริบทเดียวกัน ยิ่งไปกว่านั้น เมื่อเทียบกับการบีบอัดพจนานุกรมแบบคลาสสิก (เช่นที่ใช้ใน รูปแบบ zipและgzip ) ขนาดของพจนานุกรมสามารถและมักจะใหญ่กว่ามาก โดยใช้ประโยชน์จากหน่วยความจำจำนวนมากที่มีอยู่ในระบบสมัยใหม่[ 8 ]
ภาพรวมรูปแบบการบีบอัด
ในการบีบอัด LZMA สตรีมที่ถูกบีบอัดคือสตรีมของบิตที่เข้ารหัสโดยใช้ตัวเข้ารหัสช่วงไบนารีแบบปรับได้ สตรีมจะถูกแบ่งออกเป็นแพ็กเก็ต โดยแต่ละแพ็กเก็ตจะอธิบายไบต์เดียวหรือลำดับ LZ77 พร้อมความยาวและระยะทางที่เข้ารหัสโดยปริยายหรือโดยชัดแจ้ง แต่ละส่วนของแต่ละแพ็กเก็ตจะถูกจำลองด้วยบริบทอิสระ ดังนั้นการคาดการณ์ความน่าจะเป็นสำหรับแต่ละบิตจึงมีความสัมพันธ์กับค่าของบิตนั้น (และบิตที่เกี่ยวข้องจากฟิลด์เดียวกัน) ในแพ็กเก็ตก่อนหน้าประเภทเดียวกัน ทั้ง lzip [ 9 ]และเอกสารประกอบ LZMA SDK อธิบายรูปแบบสตรีมนี้[ 8 ]
มีแพ็กเก็ต 7 ประเภท: [ 9 ]
| รหัสที่บรรจุ (ลำดับบิต) | ชื่อแพ็กเก็ต | คำอธิบายแพ็กเก็ต |
|---|---|---|
| 0 + ไบต์โค้ด | ลิต | ไบต์เดียวที่เข้ารหัสโดยใช้ตัวเข้ารหัสช่วงไบนารีแบบปรับได้ |
| 1+0 + ความยาว + ระยะทาง | จับคู่ | ลำดับ LZ77 ทั่วไปที่อธิบายความยาวและระยะห่างของลำดับ |
| 1+1+0+0 | ชอร์ทเทรป | ลำดับ LZ77 ขนาดหนึ่งไบต์ ระยะห่างเท่ากับระยะห่าง LZ77 ที่ใช้ครั้งล่าสุด |
| 1+1+0+1 + ความยาว | ลองเกรป[0] | ลำดับ LZ77 ระยะทางเท่ากับระยะทาง LZ77 ที่ใช้ครั้งล่าสุด |
| 1+1+1+0 + ความยาว | LONGREP[1] | ลำดับ LZ77 ระยะทางเท่ากับระยะทาง LZ77 ที่ใช้เป็นอันดับสองจากท้าย |
| 1+1+1+1+0 + ความยาว | LONGREP[2] | ลำดับ LZ77 ระยะทางเท่ากับระยะทาง LZ77 ที่ใช้ครั้งสุดท้ายลำดับที่สาม |
| 1+1+1+1+1 + ความยาว | LONGREP[3] | ลำดับ LZ77 ระยะทางเท่ากับระยะทาง LZ77 ที่ใช้ครั้งที่สี่จากท้ายสุด |
LONGREP[*] หมายถึงแพ็กเก็ต LONGREP[0–3], *REP หมายถึงทั้ง LONGREP และ SHORTREP และ *MATCH หมายถึงทั้ง MATCH และ *REP
แพ็กเก็ต LONGREP[n] จะลบระยะทางที่ใช้ออกจากรายการระยะทางล่าสุดและแทรกกลับเข้าไปที่ด้านหน้า เพื่อหลีกเลี่ยงการป้อนข้อมูลซ้ำที่ไม่จำเป็น ในขณะที่ MATCH จะเพิ่มระยะทางเข้าไปที่ด้านหน้าแม้ว่าจะมีอยู่ในรายการอยู่แล้วก็ตาม และ SHORTREP และ LONGREP[0] จะไม่เปลี่ยนแปลงรายการ
ความยาวจะถูกเข้ารหัสในรูปแบบดังต่อไปนี้:
| รหัสความยาว (ลำดับบิต) | คำอธิบาย |
|---|---|
| 0+ 3 บิต | ความยาวที่เข้ารหัสโดยใช้ 3 บิต จะให้ค่าความยาวตั้งแต่ 2 ถึง 9 |
| 1+0+ 3 บิต | ความยาวที่เข้ารหัสโดยใช้ 3 บิต จะได้ช่วงความยาวตั้งแต่ 10 ถึง 17 |
| 1+1+8 บิต | ความยาวที่เข้ารหัสโดยใช้ 8 บิต จะได้ช่วงความยาวตั้งแต่ 18 ถึง 273 |
เช่นเดียวกับใน LZ77 ความยาวไม่ได้ถูกจำกัดด้วยระยะทาง เพราะการคัดลอกจากพจนานุกรมถูกกำหนดเสมือนว่าเป็นการคัดลอกทีละไบต์ โดยรักษาระยะทางให้คงที่
ระยะทางมีค่าทางตรรกะ 32 บิต และระยะทาง 0 หมายถึงไบต์ที่เพิ่มเข้ามาล่าสุดในพจนานุกรม
การเข้ารหัสระยะทางเริ่มต้นด้วย "ช่องระยะทาง" 6 บิต ซึ่งกำหนดว่าต้องใช้บิตเพิ่มเติมอีกกี่บิต ระยะทางจะถูกถอดรหัสเป็นการต่อกันของเลขฐานสอง โดยเรียงจากบิตที่มีค่ามากที่สุดไปยังบิตที่มีค่าน้อยที่สุด ขึ้นอยู่กับช่องระยะทาง บิตบางส่วนจะถูกเข้ารหัสด้วยความน่าจะเป็นคงที่ 0.5 และบิตบางส่วนจะถูกเข้ารหัสตามบริบท ตามตารางต่อไปนี้ (ช่องระยะทาง 0-3 จะเข้ารหัสระยะทาง 0-3 โดยตรง)
| ช่องระยะห่าง 6 บิต | 2 บิตสูงสุด | บิตความน่าจะเป็นคงที่ 0.5 | บิตที่เข้ารหัสตามบริบท |
|---|---|---|---|
| 0 | 00 | 0 | 0 |
| 1 | 01 | 0 | 0 |
| 2 | 10 | 0 | 0 |
| 3 | 11 | 0 | 0 |
| 4 | 10 | 0 | 1 |
| 5 | 11 | 0 | 1 |
| 6 | 10 | 0 | 2 |
| 7 | 11 | 0 | 2 |
| 8 | 10 | 0 | 3 |
| 9 | 11 | 0 | 3 |
| 10 | 10 | 0 | 4 |
| 11 | 11 | 0 | 4 |
| 12 | 10 | 0 | 5 |
| 13 | 11 | 0 | 5 |
| 14–62 (เลขคู่) | 10 | ช่อง / 2 − 5 | 4 |
| 15–63 (เลขคี่) | 11 | (ช่อง − 1) / 2 − 5 | 4 |
รายละเอียดของอัลกอริธึมการคลายการบีบอัด
ดูเหมือนว่าจะไม่มีข้อกำหนดภาษาธรรมชาติที่สมบูรณ์สำหรับรูปแบบการบีบอัดข้อมูล นอกเหนือจากข้อกำหนดที่พยายามใช้ในข้อความต่อไปนี้
คำอธิบายด้านล่างนี้อ้างอิงจาก ตัวถอดรหัส XZ Embedded ขนาดกะทัดรัดโดย Lasse Collin ซึ่งรวมอยู่ในซอร์สโค้ดเคอร์เนล Linux [ 10 ]ซึ่งสามารถอนุมานรายละเอียดของอัลกอริธึม LZMA และ LZMA2 ได้ค่อนข้างง่าย ดังนั้น แม้ว่าการอ้างอิงซอร์สโค้ดเป็นข้อมูลอ้างอิงจะไม่เหมาะสม แต่โปรแกรมเมอร์ทุกคนควรจะสามารถตรวจสอบข้อกล่าวอ้างด้านล่างนี้ได้ภายในเวลาไม่กี่ชั่วโมง
การเข้ารหัสช่วงของบิต
ข้อมูล LZMA ในระดับต่ำสุดจะถูกถอดรหัสทีละบิตโดยตัวถอดรหัสช่วง ตามทิศทางของตัวถอดรหัส LZMA
การถอดรหัสช่วงตามบริบทจะถูกเรียกใช้โดยอัลกอริทึม LZMA โดยส่งการอ้างอิงไปยัง "บริบท" ซึ่งประกอบด้วยตัวแปรprob ขนาด 11 บิตที่ไม่มีเครื่องหมาย (โดยทั่วไปจะใช้ชนิดข้อมูล 16 บิต) ซึ่งแสดงถึงความน่าจะเป็นที่คาดการณ์ไว้ของบิตที่เป็น 0 โดยตัวถอดรหัสช่วงจะอ่านและอัปเดตค่านี้ (และควรเริ่มต้นด้วยค่า 0 ซึ่งแสดงถึงความน่าจะเป็น 0.5)
การถอดรหัสช่วงความน่าจะเป็นคงที่นั้นถือว่ามีความน่าจะเป็น 0.5 แต่ทำงานแตกต่างจากการถอดรหัสช่วงตามบริบทเล็กน้อย
สถานะของตัวถอดรหัสช่วงประกอบด้วยตัวแปร 32 บิตแบบไม่มีเครื่องหมายสองตัว ได้แก่ช่วง (แทนขนาดของช่วง) และรหัส (แทนจุดที่เข้ารหัสภายในช่วง)
การเริ่มต้นใช้งานตัวถอดรหัสช่วงประกอบด้วยการตั้งค่าช่วงเป็น2 32 − 1และเข้ารหัสเป็นค่า 32 บิตโดยเริ่มจากไบต์ที่สองในสตรีมที่ตีความว่าเป็นแบบบิ๊กเอนเดียน ส่วนไบต์แรกในสตรีมจะถูกละเลยโดยสิ้นเชิง
กระบวนการทำให้เป็นมาตรฐานจะดำเนินการดังนี้:
- เลื่อนทั้งช่วงและรหัสไปทางซ้าย 8 บิต
- อ่านไบต์จากสตรีมที่ถูกบีบอัด
- กำหนดค่า 8 บิตสุดท้ายของรหัสให้ตรงกับค่าไบต์ที่อ่านได้
การถอดรหัสช่วงตามบริบทของบิตโดยใช้ ตัวแปรความน่าจะเป็น probดำเนินการดังนี้:
- ถ้าช่วงน้อยกว่า ให้ทำการปรับค่าให้เป็นมาตรฐาน
- ตั้งค่าการผูกกับ
- ถ้าโค้ดน้อยกว่าขอบเขตที่กำหนด :
- กำหนดช่วงให้เป็นขอบเขต
- ตั้งค่าprobเป็นprob +
- ส่งคืนบิต 0
- ในกรณีอื่นๆ (หากรหัสมีค่ามากกว่าหรือเท่ากับค่าขอบเขต ):
- ตั้งค่าช่วงเป็นขอบเขตช่วง
- กำหนดรหัสให้กับรหัส − ขอบเขต
- ตั้งค่าความน่าจะเป็นเป็น
- ส่งคืนบิต 1
การถอดรหัสบิตด้วยช่วงความน่าจะเป็นคงที่ดำเนินการดังนี้:
- ถ้าช่วงน้อยกว่า ให้ทำการปรับค่าให้เป็นมาตรฐาน
- ตั้งค่าช่วงเป็น
- ถ้าโค้ดน้อยกว่าช่วงที่กำหนด :
- ส่งคืนบิต 0
- ในกรณีอื่น ๆ (ถ้าค่ารหัสมากกว่าหรือเท่ากับช่วง ):
- ตั้งค่ารหัสเป็นรหัส − ช่วง
- ส่งคืนบิต 1
การใช้งานการถอดรหัสความน่าจะเป็นคงที่ในเคอร์เนล Linux นั้นrc_direct()ด้วยเหตุผลด้านประสิทธิภาพ จึงไม่มีการแยกสาขาแบบมีเงื่อนไข แต่จะลบช่วง ออก จากรหัสโดยไม่มีเงื่อนไขแทน บิตเครื่องหมายที่ได้จะถูกนำมาใช้ทั้งในการตัดสินใจว่าจะส่งคืนค่าบิตใด และเพื่อสร้างมาสก์ที่จะนำไปรวมกับรหัสและเพิ่มเข้าไปใน ช่วง
โปรดทราบว่า:
- การหารด้วย เมื่อคำนวณขอบเขตและการปัดเศษลง จะทำก่อนการคูณ ไม่ใช่หลังจากนั้น (เห็นได้ชัดว่าเพื่อหลีกเลี่ยงการต้องใช้ฮาร์ดแวร์ที่รวดเร็วในการคูณ 32 บิตด้วยผลลัพธ์ 64 บิต)
- การถอดรหัสด้วยความน่าจะเป็นคงที่นั้นไม่เทียบเท่ากับการถอดรหัสช่วงตามบริบทโดยใช้ ค่า ความน่าจะเป็น ใดๆ อย่างเคร่งครัด เนื่องจากวิธีการถอดรหัสช่วงตามบริบทจะตัดบิต 11 บิตล่างของช่วงออกก่อนที่จะคูณด้วยความน่าจะเป็นดังที่ได้อธิบายไว้ ในขณะที่การถอดรหัสด้วยความน่าจะเป็นคงที่นั้นจะตัดเฉพาะบิตสุดท้ายออกเท่านั้น
การเข้ารหัสช่วงของจำนวนเต็ม
ตัวถอดรหัสช่วงยังให้ความสามารถในการถอดรหัสแบบบิตทรี บิตทรีแบบย้อนกลับ และจำนวนเต็มที่มีความน่าจะเป็นคงที่ ซึ่งใช้ในการถอดรหัสจำนวนเต็ม และเป็นการขยายการถอดรหัสแบบบิตเดียวที่อธิบายไว้ข้างต้น ในการถอดรหัสจำนวนเต็มที่ไม่มีเครื่องหมายซึ่งน้อยกว่าlimit จะมีการจัดเตรียม อาร์เรย์ของ ตัวแปรความน่าจะเป็น 11 บิต ( limit − 1)ซึ่งจัดเรียงในเชิงแนวคิดเป็นโหนดภายในของต้นไม้ไบนารีสมบูรณ์ที่มีใบ limit
การถอดรหัสบิตทรีแบบไม่ย้อนกลับทำงานโดยการเก็บตัวชี้ไปยังต้นไม้ของตัวแปร ซึ่งเริ่มต้นที่ราก ตราบใดที่ตัวชี้ไม่ได้ชี้ไปยังใบ การถอดรหัสบิตจะใช้ตัวแปรที่ระบุโดยตัวชี้ และตัวชี้จะถูกย้ายไปยังลูกทางซ้ายหรือขวาขึ้นอยู่กับว่าบิตนั้นเป็น 0 หรือ 1 เมื่อตัวชี้ชี้ไปยังใบ ระบบจะส่งคืนค่าที่เกี่ยวข้องกับใบนั้น
ดังนั้น การถอดรหัสแบบบิตทรีที่ไม่ย้อนกลับจึงเกิดขึ้นจากบิตที่มีนัยสำคัญมากที่สุดไปยังบิตที่มีนัยสำคัญน้อยที่สุด โดยจะหยุดเมื่อมีค่าเพียงค่าเดียวในช่วงที่ถูกต้อง (ในทางแนวคิดแล้ว สิ่งนี้ช่วยให้สามารถมีขนาดช่วงที่ไม่ใช่กำลังของสองได้ แม้ว่า LZMA จะไม่ได้ใช้ประโยชน์จากสิ่งนี้ก็ตาม)
การถอดรหัสแบบบิตทรีแบบย้อนกลับจะถอดรหัสจากบิตที่มีค่าน้อยที่สุดไปยังบิตที่มีค่ามากที่สุด ดังนั้นจึงรองรับเฉพาะช่วงที่เป็นกำลังของสองเท่านั้น และจะถอดรหัสจำนวนบิตเท่ากันเสมอ ซึ่งเทียบเท่ากับการถอดรหัสแบบบิตทรีที่ไม่ใช่แบบย้อนกลับโดยมีขีดจำกัด เป็นกำลังของสอง และกลับ บิต log 2 ( limit ) สุดท้าย ในผลลัพธ์
ใน ฟังก์ชัน rc_bittreeในเคอร์เนล Linux ค่าจำนวนเต็มจะถูกส่งคืนใน ช่วง [ limit , 2 × limit ) (โดยที่limitถูกบวกเข้ากับค่าเชิงแนวคิด) และตัวแปรที่ดัชนี 0 ในอาร์เรย์นั้นไม่ได้ถูกใช้งาน ในขณะที่ตัวแปรที่ดัชนี 1 เป็นราก และดัชนีของลูกซ้ายและขวาจะถูกคำนวณเป็น 2 iและ 2 i + 1 ส่วนฟังก์ชัน rc_bittree_reverseจะเพิ่มค่าจำนวนเต็มใน ช่วง [0, limit )ให้กับตัวแปรที่ผู้เรียกกำหนด โดยที่limitจะถูกแทนด้วยลอการิทึมโดยปริยาย และมีการใช้งานที่เป็นอิสระของตัวเองเพื่อเหตุผลด้านประสิทธิภาพ
การถอดรหัสจำนวนเต็มด้วยความน่าจะเป็นคงที่นั้น เป็นการถอดรหัสบิตด้วยความน่าจะเป็นคงที่ซ้ำๆ โดยอ่านบิตจากบิตที่มีความสำคัญมากที่สุดไปยังบิตที่มีความสำคัญน้อยที่สุด
การกำหนดค่า LZMA
ตัวถอดรหัส LZMA ถูกกำหนดค่าโดย ไบต์ "คุณสมบัติ" lclppbและขนาดพจนานุกรม ค่าของ ไบต์ lclppbคือโดยที่: lc + lp * 9 + pb * 9 * 5
- lcคือจำนวนบิตสูงของไบต์ก่อนหน้าที่จะใช้เป็นบริบทสำหรับการเข้ารหัสแบบลิเทอรัล (ค่าเริ่มต้นที่ใช้โดย LZMA SDK คือ 3)
- lpคือจำนวนบิตต่ำของตำแหน่งในพจนานุกรมที่จะรวมอยู่ใน literal_pos_state (ค่าเริ่มต้นที่ใช้โดย LZMA SDK คือ 0)
- pbคือจำนวนบิตต่ำของตำแหน่งในพจนานุกรมที่จะรวมอยู่ใน pos_state (ค่าเริ่มต้นที่ใช้โดย LZMA SDK คือ 2)
ในสตรีมที่ไม่ใช้ LZMA2 ค่า lcต้องไม่เกิน 8 และค่า lpและpbต้องไม่เกิน 4 ส่งผลให้ช่วงค่าอยู่ระหว่าง 0 ถึง 224 ในสตรีมที่ใช้ LZMA2 ค่า lc และpbต้องไม่เกิน 4 ซึ่งทำให้ช่วงค่าที่เป็นไปไม่ได้มีขนาดใหญ่กว่ามาก lc + lp
ในรูปแบบไฟล์ LZMA แบบ 7-zip การกำหนดค่าจะดำเนินการโดยส่วนหัวที่มีไบต์ "properties" ตามด้วยขนาดพจนานุกรมแบบ little-endian 32 บิตในหน่วยไบต์ ใน LZMA2 ไบต์ properties สามารถเปลี่ยนแปลงได้ตามต้องการที่จุดเริ่มต้นของแพ็กเก็ต LZMA2 ในขณะที่ขนาดพจนานุกรมจะระบุไว้ในส่วนหัวของ LZMA2 ดังที่จะอธิบายต่อไป
บริบทการเข้ารหัส LZMA
รูปแบบแพ็กเก็ต LZMA ได้รับการอธิบายไปแล้ว และส่วนนี้จะระบุวิธีการที่ LZMA สร้างแบบจำลองทางสถิติของสตรีมที่เข้ารหัส LZ หรือกล่าวอีกนัยหนึ่งคือ ตัวแปรความน่าจะเป็นใดที่ถูกส่งไปยังตัวถอดรหัสช่วงเพื่อถอดรหัสแต่ละบิต
ตัวแปรความน่าจะเป็นเหล่านั้นถูกนำไปใช้ในรูปแบบของอาร์เรย์หลายมิติ โดยก่อนที่จะนำตัวแปรเหล่านั้นมาใช้ จะมีการกำหนดค่าบางค่าที่ใช้เป็นดัชนีในอาร์เรย์หลายมิติเหล่านั้นเสียก่อน
ค่าสถานะจะอิงตามแนวคิดจากรูปแบบใดในตารางต่อไปนี้ที่ตรงกับประเภทแพ็กเก็ต 2-4 ประเภทล่าสุดที่พบ และจะถูกนำไปใช้ในรูปแบบสถานะของเครื่องสถานะ ซึ่งจะได้รับการอัปเดตตามตารางการเปลี่ยนสถานะที่แสดงในตารางทุกครั้งที่มีการส่งออกแพ็กเก็ต
สถานะเริ่มต้นคือ 0 ดังนั้นแพ็กเก็ตก่อนจุดเริ่มต้นจึงถือว่าเป็นแพ็กเก็ต LIT
| สถานะ | แพ็กเก็ตก่อนหน้า | สถานะถัดไปเมื่อแพ็กเก็ตถัดไปคือ | ||||||
|---|---|---|---|---|---|---|---|---|
| ลำดับที่ 4 ก่อนหน้า | ลำดับที่ 3 ก่อนหน้า | ครั้งที่ 2 ก่อนหน้า | ก่อนหน้า | ลิต | จับคู่ | ลองเกรป[*] | ชอร์ทเทรป | |
| 0 | ลิต | ลิต | ลิต | 0 | 7 | 8 | 9 | |
| 1 | จับคู่ | ลิต | ลิต | 0 | 7 | 8 | 9 | |
| 2 | ลองเกรป[*] | ลิต | ลิต | 0 | 7 | 8 | 9 | |
| *จับคู่ | ชอร์ทเทรป | |||||||
| 3 | ลิต | ชอร์ทเทรป | ลิต | ลิต | 0 | 7 | 8 | 9 |
| 4 | จับคู่ | ลิต | 1 | 7 | 8 | 9 | ||
| 5 | ลองเกรป[*] | ลิต | 2 | 7 | 8 | 9 | ||
| *จับคู่ | ชอร์ทเทรป | |||||||
| 6 | ลิต | ชอร์ทเทรป | ลิต | 3 | 7 | 8 | 9 | |
| 7 | ลิต | จับคู่ | 4 | 10 | 11 | 11 | ||
| 8 | ลิต | ลองเกรป[*] | 5 | 10 | 11 | 11 | ||
| 9 | ลิต | ชอร์ทเทรป | 6 | 10 | 11 | 11 | ||
| 10 | *จับคู่ | จับคู่ | 4 | 10 | 11 | 11 | ||
| 11 | *จับคู่ | *ตัวแทน | 5 | 10 | 11 | 11 | ||
ค่าpos_stateและliteral_pos_stateประกอบด้วย บิตที่มีค่าน้อยที่สุด ( pbและlp) ตามลำดับ (สูงสุด 4 บิต จากส่วนหัว LZMA หรือแพ็กเก็ตคุณสมบัติ LZMA2) ของตำแหน่งในพจนานุกรม (จำนวนไบต์ที่เข้ารหัสตั้งแต่การรีเซ็ตพจนานุกรมครั้งล่าสุด หารด้วยขนาดของพจนานุกรม) โปรดทราบว่าขนาดของพจนานุกรมโดยปกติจะเป็นพหุคูณของกำลังสองขนาดใหญ่ ดังนั้นค่าเหล่านี้จึงเทียบเท่ากับการอธิบายบิตที่มีค่าน้อยที่สุดของจำนวนไบต์ที่ไม่ได้บีบอัดที่เห็นตั้งแต่การรีเซ็ตพจนานุกรมครั้งล่าสุด
ค่าprev_byte_lc_msbsจะถูกตั้งค่าเป็น บิตที่มีนัยสำคัญมากที่สุด lc (สูงสุด 4 บิต จากส่วนหัว LZMA หรือแพ็กเก็ตคุณสมบัติ LZMA2) ของไบต์ที่ไม่ได้บีบอัดก่อนหน้า
ค่าis_REPบ่งบอกว่าแพ็กเก็ตที่มีความยาวนั้นเป็น LONGREP หรือ MATCH
ค่า match_byte คือไบต์ที่จะถูกถอดรหัสหากมีการใช้แพ็กเก็ต SHORTREP (กล่าวคือ ไบต์ที่พบในพจนานุกรมที่ระยะทางที่ใช้ล่าสุด) โดยจะใช้เฉพาะหลังจากแพ็กเก็ต *MATCH เท่านั้น
literal_bit_modeเป็นอาร์เรย์ของค่า 8 ค่าในช่วง 0–2 โดยแต่ละค่าแทนตำแหน่งบิตในไบต์ ซึ่งจะมีค่าเป็น 1 หรือ 2 หากแพ็กเก็ตก่อนหน้าเป็น *MATCH และเป็นตำแหน่งบิตที่มีนัยสำคัญที่สุด หรือบิตที่มีนัยสำคัญทั้งหมดในลิเทอรัลที่จะเข้ารหัส/ถอดรหัสมีค่าเท่ากับบิตในตำแหน่งที่สอดคล้องกันใน match_byteมิฉะนั้นจะมีค่าเป็น 0 การเลือกค่าระหว่าง 1 หรือ 2 ขึ้นอยู่กับค่าของบิตในตำแหน่งเดียวกันใน match_byte
ชุดตัวแปร literal/Literal สามารถมองได้ว่าเป็น "โครงสร้างบิตเสมือน" คล้ายกับโครงสร้างบิต แต่มีตัวแปร 3 ตัวแทนที่จะเป็น 1 ตัวในแต่ละโหนด โดยตัวแปรเหล่านั้นจะถูกเลือกตาม ค่า literal_bit_modeที่ตำแหน่งบิตของบิตถัดไปที่จะถอดรหัสหลังจากบริบทของโครงสร้างบิตที่ระบุโดยโหนดนั้น
ข้อกล่าวอ้างที่พบในบางแหล่งข้อมูลว่า ค่าตัวอักษรหลัง *MATCH จะถูกเข้ารหัสโดยการ XOR ค่าไบต์กับmatch_byteนั้นไม่ถูกต้อง ที่จริงแล้ว ค่าตัวอักษรจะถูกเข้ารหัสตามค่าไบต์นั้นโดยตรง แต่ใช้โครงสร้างข้อมูลแบบบิตทรีเสมือนที่อธิบายไว้ข้างต้น และบริบทเพิ่มเติมที่แสดงในตารางด้านล่าง
กลุ่มตัวแปรความน่าจะเป็นที่ใช้ใน LZMA ได้แก่:
| ชื่อ XZ | ชื่อ SDK ของ LZMA | กำหนดพารามิเตอร์โดย | ใช้เมื่อ | โหมดการเขียนโค้ด | ถ้าบิตเป็น 0 แล้ว | ถ้าบิตที่ 1 แล้ว |
|---|---|---|---|---|---|---|
| ตรงกัน | อิสแมทช์ | สถานะ ,สถานะตำแหน่ง | แพ็กเก็ตเริ่มต้น | นิดหน่อย | ลิต | *จับคู่ |
| คือตัวแทน | ตัวแทน | สถานะ | หลังจากลำดับบิตที่ 1 | นิดหน่อย | จับคู่ | *ตัวแทน |
| คือตัวแทน 0 | IsRepG0 | สถานะ | หลังจากลำดับบิตที่ 11 | นิดหน่อย | เส้นทางสั้น/ เส้นทางยาว[0] | LONGREP[1–3] |
| is_rep0_long | IsRep0Long | สถานะ ,สถานะตำแหน่ง | หลังลำดับบิต 110 | นิดหน่อย | ชอร์ทเทรป | ลองเกรป[0] |
| คือตัวแทน 1 | IsRepG1 | สถานะ | หลังลำดับบิต 111 | นิดหน่อย | LONGREP[1] | ลองเกรป[2/3] |
| คือตัวแทน 2 | อิสเรปจี2 | สถานะ | หลังจากลำดับบิต 1111 | นิดหน่อย | LONGREP[2] | LONGREP[3] |
| ตามตัวอักษร | อย่างแท้จริง | prev_byte_lc_msbs , literal_pos_state ,, บริบทของบิตทรี literal_bit_mode[bit position] | หลังจากลำดับบิต 0 | ค่า 256 ค่าในโครงสร้างบิตเทียม | ค่าไบต์ตามตัวอักษร | |
| ดิสสล็อต | สล็อต | min(match_length, 5)บริบทของบิตทรี | ระยะทาง: เริ่มต้น | บิตทรี 64 ค่า | ช่องระยะทาง | |
| ดิสท์_พิเศษ | สเปคพอส | ระยะห่างของช่อง , บริบทบิตทรีแบบย้อนกลับ | ระยะห่าง: 4–13 ช่องระยะห่าง | ((distance_slot >> 1) − 1)-บิตแบบย้อนกลับของบิตทรี | ระยะทางบิตต่ำ | |
| ดิสท์_อะไลน์ | จัดเรียง | บริบทบิตทรีแบบย้อนกลับ | ระยะทาง: ช่องระยะทาง 14 ช่องขึ้นไป หลังจากบิตที่มีความน่าจะเป็นคงที่ | 4 บิตแบบย้อนกลับบิตทรี | ระยะทางบิตต่ำ | |
| len_dec.choice | เลนชัวรี | คือตัวแทน | ระยะเวลาการแข่งขัน: เริ่ม | นิดหน่อย | ความยาว 2–9 | ความยาว 10+ |
| len_dec.choice2 | LenChoice2 | คือตัวแทน | ความยาวการจับคู่: หลังลำดับบิตที่ 1 | นิดหน่อย | ความยาว 10–17 | ความยาว 18+ |
| len_dec.low | เลนโลว์ | is_REP , pos_state , บริบทบิตทรี | ความยาวการจับคู่: หลังลำดับบิต 0 | บิตทรี 8 ค่า | บิตที่มีความยาวต่ำ | |
| len_dec.mid | เลนมิด | is_REP , pos_state , บริบทบิตทรี | ความยาวการจับคู่: หลังลำดับบิต 10 | บิตทรี 8 ค่า | ส่วนกลางของความยาว | |
| len_dec.high | เลนไฮ | is_REPบริบทของบิตทรี | ความยาวการจับคู่: หลังลำดับบิตที่ 11 | บิตทรี 256 ค่า | ส่วนที่มีความยาวสูง | |
รูปแบบ LZMA2
คอนเทนเนอร์ LZMA2 รองรับการบีบอัดข้อมูล LZMA หลายรอบ และข้อมูลที่ไม่บีบอัด โดยแต่ละรอบการบีบอัด LZMA สามารถมีการกำหนดค่าและพจนานุกรม LZMA ที่แตกต่างกันได้ ซึ่งช่วยปรับปรุงการบีบอัดไฟล์ที่ไม่สามารถบีบอัดได้บางส่วนหรือทั้งหมด และช่วยให้สามารถบีบอัดและคลายการบีบอัดแบบมัลติเธรดได้ โดยการแบ่งไฟล์ออกเป็นส่วนๆ ที่สามารถบีบอัดหรือคลายการบีบอัดได้อย่างอิสระพร้อมกัน
ส่วนหัวของ LZMA2 ประกอบด้วยไบต์ที่ระบุขนาดของพจนานุกรม:
- 40 หมายถึงขนาดพจนานุกรม 4 GB − 1
- ค่าที่น้อยกว่า 40 แสดงถึงขนาดพจนานุกรม 2 v /2 + 12ไบต์
- ค่าคี่ที่น้อยกว่า 40 บ่งชี้ว่าขนาดพจนานุกรมคือ 3×2 ( v − 1)/2 + 11ไบต์
- ค่าที่สูงกว่า 40 ถือว่าไม่ถูกต้อง
ข้อมูล LZMA2 ประกอบด้วยแพ็กเก็ตที่เริ่มต้นด้วยไบต์ควบคุม โดยมีค่าดังต่อไปนี้:
- 0 หมายถึงจุดสิ้นสุดของไฟล์
- 1 หมายถึงการรีเซ็ตพจนานุกรมตามด้วยส่วนข้อมูลที่ไม่ถูกบีบอัด
- 2 หมายถึงส่วนข้อมูลที่ไม่ได้บีบอัดและไม่มีการรีเซ็ตพจนานุกรม
- 3–0x7f เป็นค่าที่ไม่ถูกต้อง
- 0x80–0xff หมายถึงส่วนของข้อมูลแบบ LZMA โดย 5 บิตล่างสุดจะถูกใช้เป็นบิตที่ 16–20 ของขนาดข้อมูลที่ไม่ถูกบีบอัดลบด้วยหนึ่ง และบิตที่ 5–6 จะระบุสิ่งที่ควรถูกรีเซ็ต
บิตที่ 5–6 สำหรับส่วนข้อมูล LZMA สามารถเป็นได้ดังนี้:
- 0: ไม่มีการรีเซ็ตใดๆ
- 1: รีเซ็ตสถานะ
- 2: รีเซ็ตสถานะ รีเซ็ตคุณสมบัติโดยใช้ไบต์คุณสมบัติ
- 3: รีเซ็ตสถานะ, รีเซ็ตคุณสมบัติโดยใช้ไบต์คุณสมบัติ, รีเซ็ตพจนานุกรม
การรีเซ็ตสถานะ LZMA จะทำให้สถานะ LZMA ทั้งหมดถูกรีเซ็ต ยกเว้นพจนานุกรม โดยเฉพาะอย่างยิ่ง:
- ตัวเข้ารหัสช่วง
- ค่าสถานะ
- ระยะทางสุดท้ายสำหรับการแข่งขันซ้ำ
- ความน่าจะเป็นทั้งหมดของ LZMA
ไฟล์ข้อมูลที่ไม่ได้บีบอัดประกอบด้วย:
- ค่าแบบ big-endian 16 บิต ที่เข้ารหัสขนาดข้อมูลลบหนึ่ง
- ข้อมูลที่จะคัดลอกลงในพจนานุกรมโดยไม่เปลี่ยนแปลง และผลลัพธ์
กลุ่ม LZMA ประกอบด้วย:
- ค่าแบบ big-endian 16 บิต ที่เข้ารหัส 16 บิตล่างของขนาดที่ไม่ถูกบีบอัดลบหนึ่ง
- ค่าแบบ big-endian 16 บิต ที่เข้ารหัสขนาดที่บีบอัดลบด้วยหนึ่ง
- ไบต์ properties/lclppb หากบิตที่ 6 ในไบต์ควบคุมถูกตั้งค่า
- ข้อมูลที่ถูกบีบอัดด้วยวิธี LZMA เริ่มต้นด้วย 5 ไบต์ (ซึ่งไบต์แรกจะถูกละเว้น) ที่ใช้ในการเริ่มต้นตัวเข้ารหัสช่วง (ซึ่งรวมอยู่ในขนาดที่ถูกบีบอัดแล้ว)
รูปแบบ xz และ 7z
รูปแบบ . xzซึ่งสามารถบรรจุข้อมูล LZMA2 ได้นั้น มีเอกสารอยู่ที่tukaani.org [ 11 ] ในขณะที่รูปแบบไฟล์ .7z ซึ่งสามารถบรรจุข้อมูล LZMA หรือ LZMA2 ได้นั้น มีเอกสารอยู่ในไฟล์ 7zformat.txt ที่อยู่ใน LZMA SDK [ 12 ]
ตัวอย่างการใช้งาน 7-Zip
การใช้งาน LZMA ที่แยกออกมาจาก7-Zipนั้นมีให้ใช้งานในชื่อ LZMA SDK เดิมทีได้รับอนุญาตแบบคู่ภายใต้ทั้งGNU LGPLและCommon Public License [ 13 ]โดยมีข้อยกเว้นพิเศษเพิ่มเติมสำหรับไบนารีที่เชื่อมโยง แต่Igor Pavlov ได้นำไปไว้ ในสาธารณสมบัติ เมื่อวันที่ 2 ธันวาคมพ.ศ. 2551 พร้อมกับการเผยแพร่เวอร์ชัน 4.62 [ 12 ]
การบีบอัด LZMA2 ซึ่งเป็นเวอร์ชันปรับปรุงของ LZMA [ 14 ]ปัจจุบันเป็นวิธีการบีบอัดเริ่มต้นสำหรับรูปแบบ .7z โดยเริ่มตั้งแต่เวอร์ชัน 9.30 ในวันที่ 26 ตุลาคม 2012 [ 15 ]
ไลบรารีการบีบอัด LZMA แบบโอเพนซอร์สอ้างอิงเดิมเขียนด้วยภาษาC ++แต่ได้รับการพอร์ตไปยังANSI C , C#และJava [ 12 ]นอกจากนี้ยังมีส่วนเชื่อมต่อ Python ของบุคคลที่สามสำหรับไลบรารี C++ [ 16 ]รวมถึงการพอร์ต LZMA ไปยัง Pascal [ 17 ] Go [ 18 ]และAda [ 19 ]
การใช้งาน 7-Zip ใช้โครงสร้างข้อมูลแบบแฮชเชนต้นไม้ไบนารีและต้นไม้แพทริเซีย หลายรูปแบบ เป็นพื้นฐานสำหรับอัลกอริธึมการค้นหาแบบพจนานุกรม
นอกจาก LZMA แล้ว SDK และ 7-Zip ยังมีตัวกรองการประมวลผล ล่วงหน้าหลายตัว ที่ออกแบบมาเพื่อปรับปรุงการบีบอัด ตั้งแต่การเข้ารหัสเดลต้า แบบง่าย (สำหรับรูปภาพ) และ BCJ สำหรับโค้ดที่สามารถเรียกใช้งานได้ นอกจากนี้ยังให้การใช้งานอัลกอริทึมการบีบอัดอื่นๆ ที่ใช้ใน 7z อีกด้วย
โดยทั่วไปแล้ว โค้ดสำหรับการคลายการบีบอัดอย่างเดียวของ LZMA จะมีขนาดประมาณ 5 KB และปริมาณ RAM ที่ต้องการระหว่างการคลายการบีบอัดนั้นส่วนใหญ่จะถูกกำหนดโดยขนาดของหน้าต่างเลื่อน ที่ใช้ระหว่างการบีบอัด ขนาดโค้ดที่เล็กและค่าใช้จ่ายด้านหน่วยความจำที่ค่อนข้างต่ำ โดยเฉพาะอย่างยิ่งกับความยาวของพจนานุกรมที่สั้นกว่า และซอร์สโค้ดแบบเปิด ทำให้ขั้นตอนวิธีคลายการบีบ อัด LZMA เหมาะอย่างยิ่งสำหรับแอปพลิ เคชันฝังตัว
การใช้งานอื่นๆ
นอกเหนือจากการใช้งาน 7-Zip ตามตัวอย่างแล้ว โปรแกรมต่อไปนี้ยังรองรับรูปแบบ LZMA ด้วย
- xz : การใช้งานการสตรีมที่มี เครื่องมือบรรทัดคำสั่งคล้าย gzip ซึ่ง รองรับ LZMA2 ในรูปแบบไฟล์ xz มันได้เข้ามาอยู่ในซอฟต์แวร์หลายตัวใน โลก ที่คล้าย Unixด้วยประสิทธิภาพสูง (เมื่อเทียบกับbzip2 ) และขนาดเล็ก (เมื่อเทียบกับgzip ) [ 3 ]เคอร์เนลLinux , ระบบ dpkgและRPMมีโค้ด xz และผู้จัดจำหน่ายซอฟต์แวร์หลายราย เช่นkernel.org , Debian [ 20 ]และFedoraใช้ xz สำหรับการบีบอัดเวอร์ชันของตน
- lzip : การใช้งาน LZMA อีกรูปแบบหนึ่งส่วนใหญ่สำหรับระบบที่คล้าย Unix ซึ่งเป็นทางเลือกแทน xz [ 21 ]มีรูปแบบไฟล์ที่ง่ายกว่าและกู้คืนข้อผิดพลาดได้ง่ายกว่า
- ZIPX : ส่วนขยายของ รูปแบบการบีบอัด ZIPที่สร้างขึ้นโดยWinZip ตั้งแต่เวอร์ชัน 12.1 นอกจาก นี้ยังสามารถใช้วิธีการบีบอัดอื่นๆ ได้หลากหลาย เช่นBZipและPPMd [ 22 ]
ลิงก์ภายนอก
- หน้าหลักอย่างเป็นทางการ
- ข้อกำหนดรูปแบบ Lzip
- ข้อกำหนดรูปแบบ XZ
- LZMA SDK (ชุดพัฒนาซอฟต์แวร์)
- LZMA Utils = XZ Utils
- ไฟล์ไบนารีสำหรับ Windows ของ XZ Utils
- การบีบอัดข้อมูล, ตัวบีบอัด และตัวจัดเก็บข้อมูล
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ แอลซีเอ็มเอ
LZMA ( อัลกอริทึมลูกโซ่ Lempel–Ziv–Markov [ 1 ] ) เป็น อัลกอริทึม การบีบอัดข้อมูลแบบไม่สูญเสียข้อมูล ที่พัฒนาขึ้นตั้งแต่ปี 1998 โดย Igor Pavlov ผู้พัฒนา 7-Zip มีการใช้ใน รูปแบบ 7z...
ภาพรวม
LZMA ใช้ อัลกอริธึม การบีบอัดพจนานุกรม (ซึ่งเป็นรูปแบบหนึ่งของ LZ77 ที่มีขนาดพจนานุกรมขนาดใหญ่และรองรับระยะการจับคู่ที่ใช้ซ้ำเป็นพิเศษ) จากนั้นเอาต์พุตจะถูกเข้ารหัสด้วย ตัวเข้ารหัสช่วง โดยใช้แบบจำลองที่ซับซ้อนเพื่อทำนายความน่าจะเป็นของแต่ละบิต...
ภาพรวมรูปแบบการบีบอัด
ในการบีบอัด LZMA สตรีมที่ถูกบีบอัดคือสตรีมของบิตที่เข้ารหัสโดยใช้ตัวเข้ารหัสช่วงไบนารีแบบปรับได้ สตรีมจะถูกแบ่งออกเป็นแพ็กเก็ต โดยแต่ละแพ็กเก็ตจะอธิบายไบต์เดียวหรือลำดับ LZ77 พร้อมความยาวและระยะทางที่เข้ารหัสโดยปริยายหรือโดยชัดแจ้ง...
รายละเอียดของอัลกอริธึมการคลายการบีบอัด
ดูเหมือนว่าจะไม่มีข้อกำหนดภาษาธรรมชาติที่สมบูรณ์สำหรับรูปแบบการบีบอัดข้อมูล นอกเหนือจากข้อกำหนดที่พยายามใช้ในข้อความต่อไปนี้