بسم الله الرحمن الرحيم
قمت بحمد الله من الإنتهاء من الإصدار 0.1a1 من مكتبة MathX و إليك نبذة مختصرة عنها.
ما هي MathX
هى مكتبة تحتوى على انواع رقمية مماثله للانواع الرقمية الأساسية بلغة C++/C و لكنك انت من يحدد احجامهم فمثلا يمكنك انشاء نوع رقمي بإشارة مماثل للنوع int و لكن بمساحة 1024 بت.
المكتبة تستخدم لغة ++C مع الـ Templates و لا يتم إستخدام اى مكتبات خارجية او داخلية من اى نوع حتى تزيد من محمولية المكتبة.
تحتوي المكتبة على الانواع التالية:
int_t: و يمثل عدد صحيح بإشارة.
uint_t: و يمثل عدد صحيح بدون إشارة.
float_t: و يمثل عدد عشرى يخضع لمواصفات IEEE 754-2008 القياسية.
fixed_t: و يمثل عدد عشرى بعدد محدود من الخانات.
حتى الان النوعين int_t و uint_t هما من يتم تطويرهم و عند الإنتهاء من الإصدار 1.0.0 سيتم إضافة النوع float_t بإذن الله.
النوعين int_t/uint_t يتم تغيير الـ layout الخاصه بهما تبعا لبنية النظام التى تعمل عليهم بمعنى انه إذا تم إستخدام المكتبة داخل نظام little-endian حينها الـ layout الخاصه بهم ستكون little-endian و بالمثل مع big-endian. الهدف من هذا التغيير هو امكانية استخدام النوعين بشكل يماثل إستخدام الأنواع الأساسية بلغة c++/c.
النسخه الحالية تحتوى على كود لـ little-endian فقط.
المكتبة تأتى بمجموعة جاهزه من int_t و uint_t و هم:
int128_t, uint128_t, int256_t, uint256_t, int512_t, uint512_t, int1024_t, uint1024_t, int2048_t, uint2048_t, int4096_t, uint4096_t
مدى الأرقام لهذه الانواع كما يلي:
int128_t: (16 bytes)
min: -170141183460469231731687303715884105728
max: 170141183460469231731687303715884105727
uint128_t:
max: 340282366920938463463374607431768211455
int256_t: (32 bytes)
min: -57896044618658097711785492504343953926634992332820282019728792003956564819968
max: 57896044618658097711785492504343953926634992332820282019728792003956564819967
uint256_t:
max: 115792089237316195423570985008687907853269984665640564039457584007913129639935
int512_t: (64 bytes)
min: -67039039649712985497870124991029230637396829102961966888617807218608820150367
73488400937149083451713845015929093243025426876941405973284973216824503042048
max: 67039039649712985497870124991029230637396829102961966888617807218608820150367
73488400937149083451713845015929093243025426876941405973284973216824503042047
uint512_t:
max: 134078079299425970995740249982058461274793658205923933777235614437217640300735
46976801874298166903427690031858186486050853753882811946569946433649006084095
int1024_t: (128 bytes)
min: -898846567431157953864652595394512366808988489471153286367150405788663379027504
815663542386612037680105600569399356966788293948844072083112464237153197370621
888839467124327426381511098006230470597265414760425028844190753411712314407369
56555270413618581675255342293149119973622969239858152417678164812112068608
max: 898846567431157953864652595394512366808988489471153286367150405788663379027504
815663542386612037680105600569399356966788293948844072083112464237153197370621
888839467124327426381511098006230470597265414760425028844190753411712314407369
56555270413618581675255342293149119973622969239858152417678164812112068607
uint1024_t:
max: 1797693134862315907729305190789024733617976978942306572734300811577326758055009
6313270847732240753602112011387987139335765878976881441662249284743063947412437
7767893424865485276302219601246094119453082952085005768838150682342462881473913
110540827237163350510684586298239947245938479716304835356329624224137215
int2048_t: (256 bytes)
min: -161585030356555036503574383443349759802220513348577420160651727137623275694339454465986007057614567318
443589804609490097470597795752454605475440761932241415603154386836504980458750988751948260533980288191
920337841383961093213098780809190471692380852352908229260181525214437879457705329043037761995619651927
609571666948341712103424873932822847474280880176631610290389028296655130963542301570751292964320885583
629718018592309286787991755761508229522018488066166436156135628423554101048625785508634656617348392712
903283489675229986341764993191077625831947186677718010677166148023226592393024760740967779268055297981
15328
max: 161585030356555036503574383443349759802220513348577420160651727137623275694339454465986007057614567318
443589804609490097470597795752454605475440761932241415603154386836504980458750988751948260533980288191
920337841383961093213098780809190471692380852352908229260181525214437879457705329043037761995619651927
609571666948341712103424873932822847474280880176631610290389028296655130963542301570751292964320885583
629718018592309286787991755761508229522018488066166436156135628423554101048625785508634656617348392712
903283489675229986341764993191077625831947186677718010677166148023226592393024760740967779268055297981
15327
uint2048_t:
max: 3231700607131100730071487668866995196044410266971548403213034542752465513886789089319720141152291346368
8717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384
0675682767922186426197561618380943384761704705816458520363050428875758915410658086075523991239303855219
1433338966834242068497478656456949485617603532632205807780565933102619270846031415025859286417711672594
3603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656
697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596230655
int4096_t: (512 bytes)
min: -522194440706576253345876355358312191289982124523691890192116741641976953985778728424413405967498779170
445053357219631418993786719092896803631618043925682638972978488271854999170180795067191859157214035005
927973113188159419698856372836167342172293308748403954352901852035642024370059304557233988891799014503
343469488440893892973452815095130470299789726716411734651513348221529512507986199933857107770846917779
942645743159118957217248367043905936319748237550094520674504208530837546834166925275516486044134775384
991808184705966507606898412918594045916828375610659246423184062775112999150206172392431297837246097308
511903252956622805412865917690043804311051417135098849101156584508839003337597742539960818209685142687
562392007453579567729991395256699805775897135553415567045292136442139895777424891477161767258532611634
530697452993846501061481697843891439474220308003706472837459911525285821188577408160690315522951458068
463354171428220365223949985950890732881736611925133626529949897998045399734600887312408859224933727829
625089164535236559716582775403784110923285873186648442456409760158728501220463308455437074192539205964
902261490928669488824051563042951500651206733594863336608245755565801460390869016718045121902354170201
577095168
max: 522194440706576253345876355358312191289982124523691890192116741641976953985778728424413405967498779170
445053357219631418993786719092896803631618043925682638972978488271854999170180795067191859157214035005
927973113188159419698856372836167342172293308748403954352901852035642024370059304557233988891799014503
343469488440893892973452815095130470299789726716411734651513348221529512507986199933857107770846917779
942645743159118957217248367043905936319748237550094520674504208530837546834166925275516486044134775384
991808184705966507606898412918594045916828375610659246423184062775112999150206172392431297837246097308
511903252956622805412865917690043804311051417135098849101156584508839003337597742539960818209685142687
562392007453579567729991395256699805775897135553415567045292136442139895777424891477161767258532611634
530697452993846501061481697843891439474220308003706472837459911525285821188577408160690315522951458068
463354171428220365223949985950890732881736611925133626529949897998045399734600887312408859224933727829
625089164535236559716582775403784110923285873186648442456409760158728501220463308455437074192539205964
902261490928669488824051563042951500651206733594863336608245755565801460390869016718045121902354170201
577095167
uint4096_t:
max: 1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340
8901067144392628379875734381857936072632360878513652779459569765437099983403615901343837183144280700118
5594622637631883939771274567233468434458661749680790870580370407128404874011860911446797778359802900668
6938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885
2914863182379144344967340878118726394964751001890413490084170616750936683338505510329720882695507699836
1636941193301521379682583718809183365675122131849284636812555022599830041234478486259567449219461702380
6505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784
0149071591354599827905133996115517942711068311340905842728842797915548497829543235345170652232690613949
0598769300212296339568778287894844061600741294567491982305057164237715481632138063104590291613692670834
2856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329
0704731194331655508075682218465717463732968849128195203174570024409266169108741483850784119298045229818
57338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190335يمكنك إنشاء نسخ من النوعين int_t/uint_t بإحجام تبدا من 16 بايت و حتى 256 ميجا و لكن مع كبر الحجم ستحتاج لتكبير حجم الـ stack ألخاص ببرنامجك.
لماذا MathX
أغلب المكتبات الموجوده مصممه لتعمل داخل الـ heap و بأحجام متغيره تبعا لإحتياجك و هذا يجعل من الصعب إستخدام هذه المكتبات داخل الـ embedded systems و المكتبات التى يمكنها العمل داخل الـ stack تجدها تعتمد على انواع بيانات معينه لا تستطيع تغييرها.
كل هذه المعوقات و غيرها تم تجنبها فى MathX حيث:
1- تقوم أنت بتحديد عدد البت داخل البايت الواحد فإن لم تقم بذلك سيتم إستخدام الحجم الإفتراضي الذى يقوم المترجم بتعريفه.
2- تقوم بتحديد حجم نوع البيانات الذى يتم إنشاء الأنواع الإفتراضية من int_t/uint_t فإن لم تقم سيتم إستخدام انواع بيانات بحجم يساوى مساحة حجم مسجل المعالج لضمان اقصى سرعة فى التنفيذ.
3- تقوم انت بتحديد الأنواع التى سيتم إستخدامها داخل الكود لحفظ حجم المصفوفة و موقع عنصر بها و قيمة العداد، فإن لم تقم سيتم إستخدام قيم إفتراضية تتلائم مع البيئة التى تعمل بها.
4- كما ذكرت يوجد حد أقصي للذاكرة التى يمكن للنوعين int_t/uint_t استخدامها و هى محدوده بأقصي قيمه لنوع يمكنك تغييره إن اردت.
5- يمكنك إيقاف و تشغيل العمليات على الأعداد العشرية و بذلك تضمن عدم استخدام اى دوال من المكتبة الإفتراضية باللغه و ذلك إن اردت ترجمه المكتبه لتعمل مع نظام لا يدعم float-point.
6- لا يوجد كود C أو كود أسكبلي من أى نوع فقط ++Pure C و هذا يعنى ان المترجم يعمل بأقصي طاقاته مع التحسينات و يعطيك افضل نتيجه.
7- لا يتم إستخدام المؤشرات و لا اى خصائص الوراثة و الكود الناتج يتم فلترته بشكل كبير، شكرا للـ Templates.
8- تم إستخدام أساليب برمجية تضمن سرعة و كفاءة الكود و مع تفعيل SIMD يتم إنتاج كود سريع جدا، جرب بنفسك و سترى.
9- توجد العديد من المزايا و لكن لا يوجد وقت للكتابة، يمكنك مراجعة صفحة المشروع للمزيد من المعلومات.
توثيق المكتبة
لازال جارى العمل عليه و سأقوم بتحديث هذا الموضوع مع كل تعديلات جديده داخل المشروع.
كيف يتم إستخدامها
سأفترض ان مسار المكتبة موجود PATH.
1- العمليات الحسابية الأساسية تتم كما فى الأنواع الأساسية:
#include <mathx.hpp>
using mathx::uint128_t;
int main()
{
uint128_t a = 1024, b = 0;
bool r;
/* Addition */
a = a + 500;
a += 100;
/* subtraction */
a = a - 13;
a -= 17;
/* multiplication */
a = a * 13;
a *= 17;
/* division */
a = a / 8;
a /= 2;
/* modulus */
a = a % 123456789;
a %= 3365478;
/* left shift */
a = a >> 10;
a >>= 3;
/* right shift */
a = a << 3;
a <<= 12;
/* bitwise and */
a = a & a;
a &= a;
/* bitwise or */
a = a | a;
a |= a;
/* bitwise xor */
a = a ^ a;
a ^= a;
/* bitwise negation */
a = ~a;
/* logic and */
r = a && b;
/* logic or */
r = a || b;
/* logic not */
r = !a;
/* logic equal-to */
r = a == b;
/* logic not-equal-to */
r = a != b;
/* logic less-than */
r = a < b;
/* logic less-than-or-equal */
r = a <= b;
/* logic greater-than */
r = a > b;
/* logic greater-than-or-equal */
r = a >= b;
}المعاملات التى يتم إستخدامها هنا فعليا تقوم بإستدعاء دوال تقوم بالعمليات التى نريدها و هذه الدوال مقسمه حسب نوع فمثلا الجمع و الطرح داخل فئة دوال الحسابات و الإزاحه فى فئة دوال البت و العمليات المنطقية فى فئة العمليات المنطقية، هذه الفئات هى قلب الأنواع الأساسية بـ MathX و اهمية وجودهم تكمن فى امكانية استبدالة مجموعة بأخرى بكود مختلف دون الحاجه لإعادة كتابة كل شي من جديد.
لنأخذ مثال على النوع unit128_t و الذى هو منبثق من uint_t و تعريف هذه الفئه يأخذ الشكل التالي:
template<cu_t bits_count, typename ut_t, typename udt_t,
template <typename> class range_t, template <typename> class bitwise_t,
template <typename> class logic_t, template <typename> class arithmetic_t,
template <typename> class meta_t>
struct uint_t
{
typedef uint_t<bits_count, ut_t, udt_t, range_t, bitwise_t, logic_t, arithmetic_t, meta_t> type;
typedef ut_t ut; // unsigned half type
typedef ut_t st; // defined to prevent compile-time error (implementation should never use this type)
typedef udt_t udt; // unsigned full type
typedef udt_t sdt; // defined to prevent compile-time error (implementation should never use this type)
typedef range_t<type> range; // range functions
typedef bitwise_t<type> bitwise; // bitwise functions
typedef logic_t<type> logic; // logic functions
typedef arithmetic_t<type> arithmetic; // arithmetic functions
typedef meta_t<type> meta; // metadata constants
ut comp[meta::array_count];
};داخل المجلد src/base ستجد تعريف فئات الأنواع الأساسية التى تقوم المكتبة بتصديرها و التى uint_t إحداها.
داخل الفئة uint_t تجد مجموعة من الـ typedef و التى تمثل كل مجموعة عمليات و هم 5 مجموعات كل منهم يحتوى على دوال تقوم بعمليات محدده، بعض الدوال لا يوجد لها مقابل داخل كود الفئه الأصلي فمثلا توجد الدالة is_neg داخل range و التى تعود لك بـ true إذا كانت القيمه الممرره للداله تحتوى قيمه سالبة و false إذا كانت تحتوى على قيمة موجبة.
كافة هذه الدوال يمكنك معرفتها بالإطلاع على محتوى الملف src/base/int_contract.hpp.
2- التحويل بين الأنواع المختلفه: المكتبة تسمح لك بالتحويل بين اى نوع وأخر فيمكنك تحويل bool إلى int128_t و من ثم تحويل ذلك النوع إلى uint512_t و فى النهاية تقوم بتحويل الناتج إلى int، أنظر الكود التالي:
#include <mathx.hpp>
using mathx::numeric_cast;
using mathx::int128_t;
using mathx::uint512_t;
int main()
{
bool a = true;
int128_t b = a;
uint512_t c = numeric_cast<int128_t>(b);
int d = numeric_cast<uint512_t>(c);
}الفئه numeric_cast بإختصار هى المسئولة عن عمليات التحويل الرقميه بين اى نوع وأخر و إستخدامها بسيط حيث يتم تمرير النوع المراد التحويل منه و القيمه المراد تحويلها و لابد من تحديد نوع القيمه الجديده فمثلا الكود التالي لن يتم ترجمته:
numeric_cast<uint512_t>(c);
مع كل مترجم ستظهر رسالة مختلفه و لكن أصل المشكل هو عدم معرفة المترجم النوع الذى ترغب فى تحويل القيمه المدخله إليه، و لإصلاح الخطأ قم بتحديد النوع بأى من الطرق التالية:
(int)numeric_cast<uint512_t>(c); static_cast<int>(numeric_cast<uint512_t>(c));
3- تحويل أنواع المكتبة من و إلي نص يحتاج منا ان نتحدث قليلا قبل النظر للكود
كما نعلم انه توجد العديد من الخيارات عندما نتحدث للتحويل من و إلى النص مثلا الأساس الذى تريد التحويل إليه أو منه، و نوع النص فيمكنك إستخدام الفئه string او مصفوفه من نوع wchar و إذا كان لديك فئة نصوص خاصه بك يمكنك ان ترغب فى التعامل معها و ايضا حالة الحروف المحول منها او إليها و العديد من الخصائص الاخرى.
كما ترى عملية التحويل من و إلى النصوص لها العديد من الخيارات و لهذا فبخلاف كل اجزاء المكتبة هذا الجزء تحديدا يحتاج منك إلى تركيز كبير، فافعل ما يجعلك تشعر بالراحه و أكمل معي.
توجد 3 عمليات أساسية و هم: تحويل رقم إلى نص و تحويل نص إلى رقم و معرفة المساحة التى يحتاجها رقم قبل ان يتم تحويله لنص، و سنتناول هذه العمليات بعد قليل.
إسم الفئه التى سنستخدمها للتعامل مع النصوص هو string_cast و شكلها كالتالي:
template<typename num_type, typename str_type, typename base_type>
struct string_cast
{
inline static cs_t length(const num_type& n);
inline static bool from(const str_type& s, num_type& n);
inline static bool to(str_type& s, const num_type& n);
inline static bool to(str_type& s, const num_type& n, bool upper);
};يتم تمرير للفئة string_cast ثلاثة معاملات و أولهم النوع الرقمي و هو فى حالتنا هذه اى مشتقات انواع مكتبة MathX مثل int128_t أو uint512_t او float4096_t و هكذا.
المعامل الثاني و هو نوع النص و توجد مجموعتين لأنواع النصوص يمكن إستخدامهم و هم:
type*, basic_string
حيث *type هو مؤشر لنوع بيانات اساسي فيمكن ان يكون *char أو *wchar_t او أى مؤشر لنوع بيانات ترغب فى استخدامه كمصفوفة نصوص.
و basic_string هى فئة النصوص الأساسية الموجوده داخل ++c و التى من مشتقاتها الفئتين string و wstring.
المعامل الثالث هو أهم معامل و هو الأساس، و الذى سيقوم بالإجابه على الأسئلة التالية:
1- ما هى الحروف التى تمثل هذا الاساس.
2- هل يستطيع الأساس تمثيل الإشاره.
3- فى حالة العدد السالب هل يتم إظهار الإشارة.
4- هل حرف معين من ضمن حروف هذا الاساس.
5- ما هى قيمة الحرف داخل هذا الأساس.
6- ما هو الحرف المقابل لعدد معين داخل الأساس.
هذه الأسئلة تقوم بإجابتها الفئات التى تمثل الأساس و التى تتيح لك انشاء مجموعه كبيره من الأسس و لكن توجد بعض الحالات التى لابد من كتابة كود جديد لها مثل الأعداد الرومانيه.
الأساس الإفتراضي لفئة string_cast هو الأساس العشرى.
فئة الأساس إسمها base_t و يتم تمرير لها عدة معاملات كل منهم له قيمه إفتراضية إلا المعامل الأول و قيمه الأساس و التى لابد منك تمريرها، أيضا إذا كان نوع بيانات النص المدخل غير مبني على النوع char فستحتاج لتمرير نوع الحرف داخل نوع النص كمعامل ثاني.
توجد 4 اسس تم تعريفهم لك و هم 2 و 8 و 10 و 16، قم بتمرير أيهم لـ base_t و سيتم التحويل من و إلى هذا الأساس بإستخدام دوال string_cast.
#include <mathx.hpp>
#include <string>
using std::string;
using std::cout;
using mathx::int128_t;
using mathx::string_cast;
using mathx::base_t;
int main()
{
int128_t n = ~0ull;
string s;
string_cast<int128_t, string>::to(s, n);
cout << "base10 implicit: " << s << "\n";
string_cast<int128_t, string, base_t<10> >::to(s, n);
cout << "base10 explicit: " << s << "\n";
string_cast<int128_t, string, base_t<8> >::to(s, n);
cout << "base8: " << s << "\n";
string_cast<int128_t, string, base_t<16> >::to(s, n);
cout << "base16: " << s << "\n";
string_cast<int128_t, string, base_t<2> >::to(s, n);
cout << "base2: " << s << "\n";
}و النتيجه:
base10 implicit: 18446744073709551615 base10 explicit: 18446744073709551615 base8: 377777777777777777777 base16: ffffffffffffffff base2: 1111111111111111111111111111111111111111111111111111111111111111
ماذا لو اردت استخدام النوع wchar_t بدلا من char:
string_cast<int128_t, wstring, base_t<10, wchar_t> >::to(s, n); wcout << "base10 explicit: " << s << "\n";
لنقوم الأن بتحويل النصوص التى حصلنا عليها مجددا إلى رقم:
#include <mathx.hpp>
#include <iomanip>
using std::string;
using std::cout;
using std::boolalpha;
using mathx::int128_t;
using mathx::string_cast;
using mathx::base_t;
int main()
{
int128_t n;
bool r;
r = string_cast<int128_t, char*>::from("18446744073709551615", n);
cout << "is conversion from base10 string OK: " << boolalpha << r << "\n";
r = string_cast<int128_t, char*, base_t<8> >::from("377777777777777777777", n);
cout << "is conversion from base8 string OK: " << boolalpha << r << "\n";
r = string_cast<int128_t, char*, base_t<2> >::from("1111111111111111111111111111111111111111111111111111111111111111", n);
cout << "is conversion from base2 string OK: " << boolalpha << r << "\n";
r = string_cast<int128_t, char*, base_t<16> >::from("ffffffffffffffff", n);
cout << "is conversion from base16 string OK: " << boolalpha << r << "\n";
}و النتيجه:
is conversion from base10 string OK: true is conversion from base8 string OK: true is conversion from base2 string OK: true is conversion from base16 string OK: true
لكن ماذا يحدث إذا حاولنا التحويل من نص إلى أساس لا يدعم احد حروف النص:
r = string_cast<int128_t, char*, base_t<10> >::from("ffffffffffffffff", n);
cout << "is conversion from base10 string OK: " << boolalpha << r << "\n";و النتيجه:
is conversion from base10 string OK: false
من باب التسلية قمت بكتابة الفئة alphanum_base لتمثل الأساس 36 و حروفه هى:
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
أنظر كيف يتم إستخدامها:
#include <mathx.hpp>
#include <string>
using std::string;
using std::cout;
using mathx::uint256_t;
using mathx::string_cast;
using mathx::imp::alphanum_base;
int main()
{
uint256_t n;
string s;
uint256_t::range::set_max(n);
cout << "max value of uint256_t in\n";
string_cast<uint256_t, string, alphanum_base<6> >::to(s, n);
cout << " base6: " << s << "\n\n";
string_cast<uint256_t, string, alphanum_base<19> >::to(s, n, true);
cout << " base19: " << s << "\n\n";
string_cast<uint256_t, string, alphanum_base<31> >::to(s, n);
cout << " base31: " << s << "\n\n";
}و النتيجه:
max value of uint256_t in base6: 1021410542201502023034020312354303525141003020114213135200030531345402305211301035040321031131454023 base19: 237IFHBBCE5DIAC835EHHG793C6BCDD6739HFFGBFCEFDEDD0FG72B1HD4D7F base31: a313gilnoeiiekt9559bqu7h8pbh49n65lt9ek54eo1c67n06b91
قم بالدخول على صفحة المشروع لأحدث نسخه من المشروع، أو أضغط هنا لتحميل كود الإصدار 0.1a1
أتمني أن تستمتع بإستخدامها كما أستمتع انا بتصميمها.
و الله ولي التوفيق
