diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..36976fb --- /dev/null +++ b/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +gdbgui = "*" +greenlet = "*" + +[dev-packages] + +[requires] +python_version = "3.11" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..c85a6d0 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,376 @@ +{ + "_meta": { + "hash": { + "sha256": "2900fb020fb4f72f576579bf9e7b16c829e817def0154fbd904c19c499a591f0" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.11" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "bidict": { + "hashes": [ + "sha256:4fa46f7ff96dc244abfc437383d987404ae861df797e2fd5b190e233c302be09", + "sha256:929d056e8d0d9b17ceda20ba5b24ac388e2a4d39802b87f9f4d3f45ecba070bf" + ], + "markers": "python_version >= '3.6'", + "version": "==0.21.2" + }, + "brotli": { + "hashes": [ + "sha256:02177603aaca36e1fd21b091cb742bb3b305a569e2402f1ca38af471777fb019", + "sha256:11d3283d89af7033236fa4e73ec2cbe743d4f6a81d41bd234f24bf63dde979df", + "sha256:12effe280b8ebfd389022aa65114e30407540ccb89b177d3fbc9a4f177c4bd5d", + "sha256:160c78292e98d21e73a4cc7f76a234390e516afcd982fa17e1422f7c6a9ce9c8", + "sha256:16d528a45c2e1909c2798f27f7bf0a3feec1dc9e50948e738b961618e38b6a7b", + "sha256:19598ecddd8a212aedb1ffa15763dd52a388518c4550e615aed88dc3753c0f0c", + "sha256:1c48472a6ba3b113452355b9af0a60da5c2ae60477f8feda8346f8fd48e3e87c", + "sha256:268fe94547ba25b58ebc724680609c8ee3e5a843202e9a381f6f9c5e8bdb5c70", + "sha256:269a5743a393c65db46a7bb982644c67ecba4b8d91b392403ad8a861ba6f495f", + "sha256:26d168aac4aaec9a4394221240e8a5436b5634adc3cd1cdf637f6645cecbf181", + "sha256:29d1d350178e5225397e28ea1b7aca3648fcbab546d20e7475805437bfb0a130", + "sha256:2aad0e0baa04517741c9bb5b07586c642302e5fb3e75319cb62087bd0995ab19", + "sha256:3148362937217b7072cf80a2dcc007f09bb5ecb96dae4617316638194113d5be", + "sha256:330e3f10cd01da535c70d09c4283ba2df5fb78e915bea0a28becad6e2ac010be", + "sha256:336b40348269f9b91268378de5ff44dc6fbaa2268194f85177b53463d313842a", + "sha256:3496fc835370da351d37cada4cf744039616a6db7d13c430035e901443a34daa", + "sha256:35a3edbe18e876e596553c4007a087f8bcfd538f19bc116917b3c7522fca0429", + "sha256:3b78a24b5fd13c03ee2b7b86290ed20efdc95da75a3557cc06811764d5ad1126", + "sha256:3b8b09a16a1950b9ef495a0f8b9d0a87599a9d1f179e2d4ac014b2ec831f87e7", + "sha256:3c1306004d49b84bd0c4f90457c6f57ad109f5cc6067a9664e12b7b79a9948ad", + "sha256:3ffaadcaeafe9d30a7e4e1e97ad727e4f5610b9fa2f7551998471e3736738679", + "sha256:40d15c79f42e0a2c72892bf407979febd9cf91f36f495ffb333d1d04cebb34e4", + "sha256:44bb8ff420c1d19d91d79d8c3574b8954288bdff0273bf788954064d260d7ab0", + "sha256:4688c1e42968ba52e57d8670ad2306fe92e0169c6f3af0089be75bbac0c64a3b", + "sha256:495ba7e49c2db22b046a53b469bbecea802efce200dffb69b93dd47397edc9b6", + "sha256:4d1b810aa0ed773f81dceda2cc7b403d01057458730e309856356d4ef4188438", + "sha256:503fa6af7da9f4b5780bb7e4cbe0c639b010f12be85d02c99452825dd0feef3f", + "sha256:56d027eace784738457437df7331965473f2c0da2c70e1a1f6fdbae5402e0389", + "sha256:5913a1177fc36e30fcf6dc868ce23b0453952c78c04c266d3149b3d39e1410d6", + "sha256:5b6ef7d9f9c38292df3690fe3e302b5b530999fa90014853dcd0d6902fb59f26", + "sha256:5bf37a08493232fbb0f8229f1824b366c2fc1d02d64e7e918af40acd15f3e337", + "sha256:5cb1e18167792d7d21e21365d7650b72d5081ed476123ff7b8cac7f45189c0c7", + "sha256:61a7ee1f13ab913897dac7da44a73c6d44d48a4adff42a5701e3239791c96e14", + "sha256:622a231b08899c864eb87e85f81c75e7b9ce05b001e59bbfbf43d4a71f5f32b2", + "sha256:68715970f16b6e92c574c30747c95cf8cf62804569647386ff032195dc89a430", + "sha256:6b2ae9f5f67f89aade1fab0f7fd8f2832501311c363a21579d02defa844d9296", + "sha256:6c772d6c0a79ac0f414a9f8947cc407e119b8598de7621f39cacadae3cf57d12", + "sha256:6d847b14f7ea89f6ad3c9e3901d1bc4835f6b390a9c71df999b0162d9bb1e20f", + "sha256:73fd30d4ce0ea48010564ccee1a26bfe39323fde05cb34b5863455629db61dc7", + "sha256:76ffebb907bec09ff511bb3acc077695e2c32bc2142819491579a695f77ffd4d", + "sha256:7bbff90b63328013e1e8cb50650ae0b9bac54ffb4be6104378490193cd60f85a", + "sha256:7cb81373984cc0e4682f31bc3d6be9026006d96eecd07ea49aafb06897746452", + "sha256:7ee83d3e3a024a9618e5be64648d6d11c37047ac48adff25f12fa4226cf23d1c", + "sha256:854c33dad5ba0fbd6ab69185fec8dab89e13cda6b7d191ba111987df74f38761", + "sha256:85f7912459c67eaab2fb854ed2bc1cc25772b300545fe7ed2dc03954da638649", + "sha256:87fdccbb6bb589095f413b1e05734ba492c962b4a45a13ff3408fa44ffe6479b", + "sha256:88c63a1b55f352b02c6ffd24b15ead9fc0e8bf781dbe070213039324922a2eea", + "sha256:8a674ac10e0a87b683f4fa2b6fa41090edfd686a6524bd8dedbd6138b309175c", + "sha256:8ed6a5b3d23ecc00ea02e1ed8e0ff9a08f4fc87a1f58a2530e71c0f48adf882f", + "sha256:93130612b837103e15ac3f9cbacb4613f9e348b58b3aad53721d92e57f96d46a", + "sha256:9744a863b489c79a73aba014df554b0e7a0fc44ef3f8a0ef2a52919c7d155031", + "sha256:9749a124280a0ada4187a6cfd1ffd35c350fb3af79c706589d98e088c5044267", + "sha256:97f715cf371b16ac88b8c19da00029804e20e25f30d80203417255d239f228b5", + "sha256:9bf919756d25e4114ace16a8ce91eb340eb57a08e2c6950c3cebcbe3dff2a5e7", + "sha256:9d12cf2851759b8de8ca5fde36a59c08210a97ffca0eb94c532ce7b17c6a3d1d", + "sha256:9ed4c92a0665002ff8ea852353aeb60d9141eb04109e88928026d3c8a9e5433c", + "sha256:a72661af47119a80d82fa583b554095308d6a4c356b2a554fdc2799bc19f2a43", + "sha256:afde17ae04d90fbe53afb628f7f2d4ca022797aa093e809de5c3cf276f61bbfa", + "sha256:b1375b5d17d6145c798661b67e4ae9d5496920d9265e2f00f1c2c0b5ae91fbde", + "sha256:b336c5e9cf03c7be40c47b5fd694c43c9f1358a80ba384a21969e0b4e66a9b17", + "sha256:b3523f51818e8f16599613edddb1ff924eeb4b53ab7e7197f85cbc321cdca32f", + "sha256:b43775532a5904bc938f9c15b77c613cb6ad6fb30990f3b0afaea82797a402d8", + "sha256:b663f1e02de5d0573610756398e44c130add0eb9a3fc912a09665332942a2efb", + "sha256:b83bb06a0192cccf1eb8d0a28672a1b79c74c3a8a5f2619625aeb6f28b3a82bb", + "sha256:ba72d37e2a924717990f4d7482e8ac88e2ef43fb95491eb6e0d124d77d2a150d", + "sha256:c2415d9d082152460f2bd4e382a1e85aed233abc92db5a3880da2257dc7daf7b", + "sha256:c83aa123d56f2e060644427a882a36b3c12db93727ad7a7b9efd7d7f3e9cc2c4", + "sha256:c8e521a0ce7cf690ca84b8cc2272ddaf9d8a50294fd086da67e517439614c755", + "sha256:cab1b5964b39607a66adbba01f1c12df2e55ac36c81ec6ed44f2fca44178bf1a", + "sha256:cb02ed34557afde2d2da68194d12f5719ee96cfb2eacc886352cb73e3808fc5d", + "sha256:cc0283a406774f465fb45ec7efb66857c09ffefbe49ec20b7882eff6d3c86d3a", + "sha256:cfc391f4429ee0a9370aa93d812a52e1fee0f37a81861f4fdd1f4fb28e8547c3", + "sha256:db844eb158a87ccab83e868a762ea8024ae27337fc7ddcbfcddd157f841fdfe7", + "sha256:defed7ea5f218a9f2336301e6fd379f55c655bea65ba2476346340a0ce6f74a1", + "sha256:e16eb9541f3dd1a3e92b89005e37b1257b157b7256df0e36bd7b33b50be73bcb", + "sha256:e1abbeef02962596548382e393f56e4c94acd286bd0c5afba756cffc33670e8a", + "sha256:e23281b9a08ec338469268f98f194658abfb13658ee98e2b7f85ee9dd06caa91", + "sha256:e2d9e1cbc1b25e22000328702b014227737756f4b5bf5c485ac1d8091ada078b", + "sha256:e48f4234f2469ed012a98f4b7874e7f7e173c167bed4934912a29e03167cf6b1", + "sha256:e4c4e92c14a57c9bd4cb4be678c25369bf7a092d55fd0866f759e425b9660806", + "sha256:ec1947eabbaf8e0531e8e899fc1d9876c179fc518989461f5d24e2223395a9e3", + "sha256:f909bbbc433048b499cb9db9e713b5d8d949e8c109a2a548502fb9aa8630f0b1" + ], + "version": "==1.0.9" + }, + "click": { + "hashes": [ + "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a", + "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6" + ], + "markers": "python_version >= '3.6'", + "version": "==8.0.1" + }, + "dnspython": { + "hashes": [ + "sha256:0f7569a4a6ff151958b64304071d370daa3243d15941a7beedf0c9fe5105603e", + "sha256:a851e51367fb93e9e1361732c1d60dab63eff98712e503ea7d92e6eccb109b4f" + ], + "markers": "python_version >= '3.6' and python_version < '4.0'", + "version": "==2.2.1" + }, + "eventlet": { + "hashes": [ + "sha256:80144f489c1bb273a51b6f96ff9785a382d2866b9bab1f5bd748385019f4141f", + "sha256:d10a8fcc9e33381905d9873303fde96ebe3541c03fb795055d2c7347dce0639c" + ], + "version": "==0.33.0" + }, + "flask": { + "hashes": [ + "sha256:1c4c257b1892aec1398784c63791cbaa43062f1f7aeb555c4da961b20ee68f55", + "sha256:a6209ca15eb63fc9385f38e452704113d679511d9574d09b2cf9183ae7d20dc9" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.1" + }, + "flask-compress": { + "hashes": [ + "sha256:28352387efbbe772cfb307570019f81957a13ff718d994a9125fa705efb73680", + "sha256:a6c2d1ff51771e9b39d7a612754f4cb4e8af20cebe16b02fd19d98d8dd6966e5" + ], + "version": "==1.10.1" + }, + "flask-socketio": { + "hashes": [ + "sha256:07e1899e3b4851978b2ac8642080156c6294f8d0fc5212b4e4bcca713830306a", + "sha256:1efdaacc7a26e94f2b197a80079b1058f6aa644a6094c0a322349e2b9c41f6b1" + ], + "markers": "python_version >= '3.6'", + "version": "==5.1.1" + }, + "gdbgui": { + "hashes": [ + "sha256:61c0f7a26ecdeb275d9b4d88b7afdf8d70ec5471b40ace3a7dd1a87f43cc2573", + "sha256:904f350d230969f268484976210d280b906b45b5828dd350ecdab1c49a5cda35" + ], + "index": "pypi", + "version": "==0.15.1.0" + }, + "greenlet": { + "hashes": [ + "sha256:02a807b2a58d5cdebb07050efe3d7deaf915468d112dfcf5e426d0564aa3aa4a", + "sha256:0b72b802496cccbd9b31acea72b6f87e7771ccfd7f7927437d592e5c92ed703c", + "sha256:0d3f83ffb18dc57243e0151331e3c383b05e5b6c5029ac29f754745c800f8ed9", + "sha256:10b5582744abd9858947d163843d323d0b67be9432db50f8bf83031032bc218d", + "sha256:123910c58234a8d40eaab595bc56a5ae49bdd90122dde5bdc012c20595a94c14", + "sha256:1482fba7fbed96ea7842b5a7fc11d61727e8be75a077e603e8ab49d24e234383", + "sha256:19834e3f91f485442adc1ee440171ec5d9a4840a1f7bd5ed97833544719ce10b", + "sha256:1d363666acc21d2c204dd8705c0e0457d7b2ee7a76cb16ffc099d6799744ac99", + "sha256:211ef8d174601b80e01436f4e6905aca341b15a566f35a10dd8d1e93f5dbb3b7", + "sha256:269d06fa0f9624455ce08ae0179430eea61085e3cf6457f05982b37fd2cefe17", + "sha256:2e7dcdfad252f2ca83c685b0fa9fba00e4d8f243b73839229d56ee3d9d219314", + "sha256:334ef6ed8337bd0b58bb0ae4f7f2dcc84c9f116e474bb4ec250a8bb9bd797a66", + "sha256:343675e0da2f3c69d3fb1e894ba0a1acf58f481f3b9372ce1eb465ef93cf6fed", + "sha256:37f60b3a42d8b5499be910d1267b24355c495064f271cfe74bf28b17b099133c", + "sha256:38ad562a104cd41e9d4644f46ea37167b93190c6d5e4048fcc4b80d34ecb278f", + "sha256:3c0d36f5adc6e6100aedbc976d7428a9f7194ea79911aa4bf471f44ee13a9464", + "sha256:3fd2b18432e7298fcbec3d39e1a0aa91ae9ea1c93356ec089421fabc3651572b", + "sha256:4a1a6244ff96343e9994e37e5b4839f09a0207d35ef6134dce5c20d260d0302c", + "sha256:4cd83fb8d8e17633ad534d9ac93719ef8937568d730ef07ac3a98cb520fd93e4", + "sha256:527cd90ba3d8d7ae7dceb06fda619895768a46a1b4e423bdb24c1969823b8362", + "sha256:56867a3b3cf26dc8a0beecdb4459c59f4c47cdd5424618c08515f682e1d46692", + "sha256:621fcb346141ae08cb95424ebfc5b014361621b8132c48e538e34c3c93ac7365", + "sha256:63acdc34c9cde42a6534518e32ce55c30f932b473c62c235a466469a710bfbf9", + "sha256:6512592cc49b2c6d9b19fbaa0312124cd4c4c8a90d28473f86f92685cc5fef8e", + "sha256:6672fdde0fd1a60b44fb1751a7779c6db487e42b0cc65e7caa6aa686874e79fb", + "sha256:6a5b2d4cdaf1c71057ff823a19d850ed5c6c2d3686cb71f73ae4d6382aaa7a06", + "sha256:6a68d670c8f89ff65c82b936275369e532772eebc027c3be68c6b87ad05ca695", + "sha256:6bb36985f606a7c49916eff74ab99399cdfd09241c375d5a820bb855dfb4af9f", + "sha256:73b2f1922a39d5d59cc0e597987300df3396b148a9bd10b76a058a2f2772fc04", + "sha256:7709fd7bb02b31908dc8fd35bfd0a29fc24681d5cc9ac1d64ad07f8d2b7db62f", + "sha256:8060b32d8586e912a7b7dac2d15b28dbbd63a174ab32f5bc6d107a1c4143f40b", + "sha256:80dcd3c938cbcac986c5c92779db8e8ce51a89a849c135172c88ecbdc8c056b7", + "sha256:813720bd57e193391dfe26f4871186cf460848b83df7e23e6bef698a7624b4c9", + "sha256:831d6f35037cf18ca5e80a737a27d822d87cd922521d18ed3dbc8a6967be50ce", + "sha256:871b0a8835f9e9d461b7fdaa1b57e3492dd45398e87324c047469ce2fc9f516c", + "sha256:952256c2bc5b4ee8df8dfc54fc4de330970bf5d79253c863fb5e6761f00dda35", + "sha256:96d9ea57292f636ec851a9bb961a5cc0f9976900e16e5d5647f19aa36ba6366b", + "sha256:9a812224a5fb17a538207e8cf8e86f517df2080c8ee0f8c1ed2bdaccd18f38f4", + "sha256:9adbd8ecf097e34ada8efde9b6fec4dd2a903b1e98037adf72d12993a1c80b51", + "sha256:9de687479faec7db5b198cc365bc34addd256b0028956501f4d4d5e9ca2e240a", + "sha256:a048293392d4e058298710a54dfaefcefdf49d287cd33fb1f7d63d55426e4355", + "sha256:aa15a2ec737cb609ed48902b45c5e4ff6044feb5dcdfcf6fa8482379190330d7", + "sha256:abe1ef3d780de56defd0c77c5ba95e152f4e4c4e12d7e11dd8447d338b85a625", + "sha256:ad6fb737e46b8bd63156b8f59ba6cdef46fe2b7db0c5804388a2d0519b8ddb99", + "sha256:b1660a15a446206c8545edc292ab5c48b91ff732f91b3d3b30d9a915d5ec4779", + "sha256:b505fcfc26f4148551826a96f7317e02c400665fa0883fe505d4fcaab1dabfdd", + "sha256:b822fab253ac0f330ee807e7485769e3ac85d5eef827ca224feaaefa462dc0d0", + "sha256:bdd696947cd695924aecb3870660b7545a19851f93b9d327ef8236bfc49be705", + "sha256:bdfaeecf8cc705d35d8e6de324bf58427d7eafb55f67050d8f28053a3d57118c", + "sha256:be557119bf467d37a8099d91fbf11b2de5eb1fd5fc5b91598407574848dc910f", + "sha256:c6b5ce7f40f0e2f8b88c28e6691ca6806814157ff05e794cdd161be928550f4c", + "sha256:c94e4e924d09b5a3e37b853fe5924a95eac058cb6f6fb437ebb588b7eda79870", + "sha256:cc3e2679ea13b4de79bdc44b25a0c4fcd5e94e21b8f290791744ac42d34a0353", + "sha256:d1e22c22f7826096ad503e9bb681b05b8c1f5a8138469b255eb91f26a76634f2", + "sha256:d5539f6da3418c3dc002739cb2bb8d169056aa66e0c83f6bacae0cd3ac26b423", + "sha256:d55db1db455c59b46f794346efce896e754b8942817f46a1bada2d29446e305a", + "sha256:e09dea87cc91aea5500262993cbd484b41edf8af74f976719dd83fe724644cd6", + "sha256:e52a712c38e5fb4fd68e00dc3caf00b60cb65634d50e32281a9d6431b33b4af1", + "sha256:e693e759e172fa1c2c90d35dea4acbdd1d609b6936115d3739148d5e4cd11947", + "sha256:ecf94aa539e97a8411b5ea52fc6ccd8371be9550c4041011a091eb8b3ca1d810", + "sha256:f351479a6914fd81a55c8e68963609f792d9b067fb8a60a042c585a621e0de4f", + "sha256:f47932c434a3c8d3c86d865443fadc1fbf574e9b11d6650b656e602b1797908a" + ], + "index": "pypi", + "version": "==3.0.0" + }, + "itsdangerous": { + "hashes": [ + "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c", + "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.1" + }, + "jinja2": { + "hashes": [ + "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4", + "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4" + ], + "markers": "python_version >= '3.6'", + "version": "==3.0.1" + }, + "markupsafe": { + "hashes": [ + "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298", + "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64", + "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b", + "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194", + "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567", + "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff", + "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724", + "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74", + "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646", + "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35", + "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6", + "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a", + "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6", + "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad", + "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26", + "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38", + "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac", + "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7", + "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6", + "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047", + "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75", + "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f", + "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b", + "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135", + "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8", + "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a", + "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a", + "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1", + "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9", + "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864", + "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914", + "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee", + "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f", + "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18", + "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8", + "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2", + "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d", + "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b", + "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b", + "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86", + "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6", + "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f", + "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb", + "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833", + "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28", + "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e", + "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415", + "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902", + "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f", + "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d", + "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9", + "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d", + "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145", + "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066", + "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c", + "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1", + "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a", + "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207", + "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f", + "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53", + "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd", + "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134", + "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85", + "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9", + "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5", + "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94", + "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509", + "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51", + "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.1" + }, + "pygdbmi": { + "hashes": [ + "sha256:308a8cc7a002e90e3588f5a480127d7f5d95ebd0ba9993aeeee985aa418e78be", + "sha256:ac2c4f296776e038133b53433988ea43e83887b54418e18cb7342be56aec0c34" + ], + "version": "==0.10.0.1" + }, + "pygments": { + "hashes": [ + "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380", + "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6" + ], + "markers": "python_version >= '3.5'", + "version": "==2.10.0" + }, + "python-engineio": { + "hashes": [ + "sha256:d510329b6d8ed5662547862f58bc73659ae62defa66b66d745ba021de112fa62", + "sha256:f3ef9a2c048d08990f294c5f8991f6f162c3b12ecbd368baa0d90441de907d1c" + ], + "markers": "python_version >= '3.6'", + "version": "==4.2.1" + }, + "python-socketio": { + "hashes": [ + "sha256:7ed57f6c024abdfeb9b25c74c0c00ffc18da47d903e8d72deecb87584370d1fc", + "sha256:ca807c9e1f168e96dea412d64dd834fb47c470d27fd83da0504aa4b248ba2544" + ], + "markers": "python_version >= '3.6'", + "version": "==5.4.0" + }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "version": "==1.16.0" + }, + "werkzeug": { + "hashes": [ + "sha256:1de1db30d010ff1af14a009224ec49ab2329ad2cde454c8a708130642d579c42", + "sha256:6c1ec500dcdba0baa27600f6a22f6333d8b662d22027ff9f6202e3367413caa8" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.1" + } + }, + "develop": {} +} diff --git a/include/tree.h b/include/tree.h index 5be8c7e..d32f273 100644 --- a/include/tree.h +++ b/include/tree.h @@ -1,5 +1,4 @@ /* - * Copyright 2023 Aisha Tammy * Copyright 2002 Niels Provos * All rights reserved. * @@ -31,8 +30,8 @@ #include /* - * This code is an implementation of the rank balanced tree with weak AVL conditions. - * The following paper describes the rank balanced trees in detail: + * This code is an implementation of the rank balanced tree with weak AVL + * conditions. The following paper describes the rank balanced trees in detail: * Haeupler, Sen and Tarjan, "Rank Balanced Trees", * ACM Transactions on Algorithms Volume 11 Issue 4 June 2015 * Article No.: 30pp 1–26 https://doi.org/10.1145/2689412 @@ -44,7 +43,8 @@ * Leaves have rank 0 and null nodes have rank -1. * * Weak AVL trees have the nice property that any insertion/deletion can cause - * at most two rotations, which is an improvement over the standard AVL and Red-Black trees. + * at most two rotations, which is an improvement over the standard AVL and + * Red-Black trees. * As a comparison matrix: * Tree type Weak AVL AVL Red-Black * worst case height 2Log(N) 1.44Log(N) 2Log(N) @@ -52,11 +52,11 @@ * max rotations after insert 2 O(Log(N)) 2 * max rotations after delete 2 2 3 * - * For each node we store the left and right pointers (and parent pointer depending on RB_SMALL). - * We assume that a pointer to a struct is aligned to multiple of 4 bytes, which leaves - * the last two bits free for our use. - * The last bit of each child is used to store the rank difference between the node and its child. - * The convention used here is the rank difference = 1 + last bit. + * For each node we store the left, right and parent pointers. + * We assume that a pointer to a struct is aligned to multiple of 4 bytes, which + * leaves the last two bits free for our use. The last two bits of the parent + * are used to store the rank difference between the node and its children. + * The convention used here is that the rank difference = 1 + child bit. */ #include @@ -77,71 +77,14 @@ #define _RB_LOWMASK ((uintptr_t)3U) #define _RB_PTR(elm) (__typeof(elm))((uintptr_t)(elm) & ~_RB_LOWMASK) -#define _RB_LDIR ((uintptr_t)0U) -#define _RB_RDIR ((uintptr_t)1U) -#define _RB_ODIR(dir) ((dir) ^ 1U) - -#ifndef RB_MAX_HEIGHT -#define RB_MAX_HEIGHT 127 -#endif - -#ifdef RB_SMALL +#define _RB_PDIR ((uintptr_t)0U) +#define _RB_LDIR ((uintptr_t)1U) +#define _RB_RDIR ((uintptr_t)2U) +#define _RB_ODIR(dir) ((dir) ^ 3U) #define RB_ENTRY(type) \ struct { \ - /* left, right */ \ - struct type *child[2]; \ -} - -#define RB_HEAD(name, type) \ -struct name { \ - struct type *root; \ - struct type *stack[RB_MAX_HEIGHT]; \ - size_t top; \ -} - -#define RB_INITIALIZER(root) \ -{ NULL, { NULL }, 0 } - -#define _RB_GET_PARENT(elm, oelm, field) do {} while (0) -#define _RB_SET_PARENT(elm, pelm, field) do {} while (0) - -#define _RB_STACK_SIZE(head, sz) do { \ -*sz = (head)->top; \ -} while (0) - -#define _RB_STACK_PUSH(head, elm) do { \ -(head)->stack[(head)->top++] = elm; \ -} while (0) - -#define _RB_STACK_DROP(head) do { \ -(head)->top -= 1; \ -} while (0) - -#define _RB_STACK_POP(head, oelm) do { \ -if ((head)->top > 0) \ - oelm = (head)->stack[--(head)->top]; \ -} while (0) - -#define _RB_STACK_TOP(head, oelm) do { \ -if ((head)->top > 0) \ - oelm = (head)->stack[(head)->top - 1]; \ -} while (0) - -#define _RB_STACK_CLEAR(head) do { \ -(head)->top = 0; \ -_RB_STACK_PUSH(head, NULL); \ -} while (0) - -#define _RB_STACK_SET(head, i, elm) do { \ -(head)->stack[i] = elm; \ -} while (0) - -#else - -#define RB_ENTRY(type) \ -struct { \ - /* left, right, parent */ \ + /* parent, left, right */ \ struct type *child[3]; \ } @@ -153,83 +96,68 @@ struct name { \ #define RB_INITIALIZER(root) \ { NULL } -#define _RB_PDIR 2 - -#define _RB_GET_PARENT(elm, pelm, field) do { \ -pelm = _RB_GET_CHILD(elm, _RB_PDIR, field); \ -} while (0) -#define _RB_SET_PARENT(elm, pelm, field) do { \ -_RB_SET_CHILD(elm, _RB_PDIR, pelm, field); \ +#define RB_INIT(head) do { \ +(head)->root = NULL; \ } while (0) -#define _RB_STACK_SIZE(head, sz) do {} while (0) -#define _RB_STACK_PUSH(head, elm) do {} while (0) -#define _RB_STACK_DROP(head) do {} while (0) -#define _RB_STACK_POP(head, elm) do {} while (0) -#define _RB_STACK_TOP(head, elm) do {} while (0) -#define _RB_STACK_CLEAR(head) do {} while (0) -#define _RB_STACK_SET(head, i, elm) do {} while (0) - -#endif - -#define RB_INIT(head) do { \ -(head)->root = NULL; \ -_RB_STACK_CLEAR(head); \ -} while (0) +#define RB_ROOT(head) (head)->root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) /* * element macros */ #define _RB_GET_CHILD(elm, dir, field) (elm)->field.child[dir] -#define _RB_SET_CHILD(elm, dir, celm, field) do { \ -_RB_GET_CHILD(elm, dir, field) = (celm); \ +#define _RB_SET_CHILD(elm, dir, celm, field) do { \ +_RB_GET_CHILD(elm, dir, field) = (celm); \ } while (0) -#define _RB_REPLACE_CHILD(elm, dir, oelm, nelm, field) do { \ -_RB_GET_CHILD(elm, dir, field) = (__typeof(elm))(((uintptr_t)_RB_GET_CHILD(elm, dir, field)) ^ ((uintptr_t)oelm) ^ ((uintptr_t)nelm)); \ -} while (0) -#define _RB_SWAP_CHILD_OR_ROOT(head, elm, oelm, nelm, field) do { \ -if (elm == NULL) \ - RB_ROOT(head) = nelm; \ -else \ - _RB_REPLACE_CHILD(elm, (RB_LEFT(elm, field) == (oelm) ? _RB_LDIR : _RB_RDIR), oelm, nelm, field); \ +#define _RB_UP(elm, field) _RB_GET_CHILD(elm, _RB_PDIR, field) +#define _RB_REPLACE_PARENT(elm, pelm, field) _RB_SET_CHILD(elm, _RB_PDIR, pelm, field) +#define _RB_COPY_PARENT(elm, nelm, field) _RB_REPLACE_PARENT(nelm, _RB_UP(elm, field), field) +#define _RB_SET_PARENT(elm, pelm, field) do { \ +_RB_UP(elm, field) = (__typeof(elm))(((uintptr_t)pelm) | \ + (((uintptr_t)_RB_UP(elm, field)) & _RB_LOWMASK)); \ } while (0) -#define _RB_GET_RDIFF(elm, dir, field) (((uintptr_t)_RB_GET_CHILD(elm, dir, field)) & 1U) -#define _RB_FLIP_RDIFF(elm, dir, field) do { \ -_RB_GET_CHILD(elm, dir, field) = (__typeof(elm))(((uintptr_t)_RB_GET_CHILD(elm, dir, field)) ^ 1U); \ -} while (0) -#define _RB_SET_RDIFF0(elm, dir, field) do { \ -_RB_GET_CHILD(elm, dir, field) = (__typeof(elm))(((uintptr_t)_RB_GET_CHILD(elm, dir, field)) & ~_RB_LOWMASK); \ -} while (0) -#define _RB_SET_RDIFF1(elm, dir, field) do { \ -_RB_GET_CHILD(elm, dir, field) = (__typeof(elm))(((uintptr_t)_RB_GET_CHILD(elm, dir, field)) | 1U); \ -} while (0) +#define RB_LEFT(elm, field) _RB_GET_CHILD(elm, _RB_LDIR, field) +#define RB_RIGHT(elm, field) _RB_GET_CHILD(elm, _RB_RDIR, field) +#define RB_PARENT(elm, field) _RB_PTR(_RB_GET_CHILD(elm, _RB_PDIR, field)) -#define RB_ROOT(head) (head)->root -#define RB_EMPTY(head) (RB_ROOT(head) == NULL) -#define RB_LEFT(elm, field) _RB_PTR(_RB_GET_CHILD(elm, _RB_LDIR, field)) -#define RB_RIGHT(elm, field) _RB_PTR(_RB_GET_CHILD(elm, _RB_RDIR, field)) + +#define _RB_GET_RDIFF(elm, dir, field) (((uintptr_t)_RB_UP(elm, field)) & dir) +#define _RB_GET_RDIFF2(elm, field) (((uintptr_t)_RB_UP(elm, field)) & _RB_LOWMASK) +#define _RB_FLIP_RDIFF(elm, dir, field) \ +_RB_REPLACE_PARENT(elm, ((__typeof(elm))(((uintptr_t)_RB_UP(elm, field)) ^ dir)), field) +#define _RB_FLIP_RDIFF2(elm, field) \ +_RB_REPLACE_PARENT(elm, ((__typeof(elm))(((uintptr_t)_RB_UP(elm, field)) ^ _RB_LDIR ^ _RB_RDIR)), field) +#define _RB_SET_RDIFF0(elm, dir, field) \ +_RB_REPLACE_PARENT(elm, ((__typeof(elm))(((uintptr_t)_RB_UP(elm, field)) & ~dir)), field) +#define _RB_SET_RDIFF1(elm, dir, field) \ +_RB_REPLACE_PARENT(elm, ((__typeof(elm))(((uintptr_t)_RB_UP(elm, field)) | dir)), field) +#define _RB_SET_RDIFF11(elm, field) \ +_RB_REPLACE_PARENT(elm, ((__typeof(elm))(((uintptr_t)_RB_UP(elm, field)) | _RB_LDIR | _RB_RDIR)), field) +#define _RB_SET_RDIFF00(elm, field) \ +_RB_REPLACE_PARENT(elm, RB_PARENT(elm, field), field) /* - * RB_AUGMENT should only return true when the update changes the node data, + * RB_AUGMENT_CHECK should only return true when the update changes the node data, * so that updating can be stopped short of the root when it returns false. */ +#ifndef RB_AUGMENT_CHECK #ifndef RB_AUGMENT -#define _RB_AUGMENT(x) (0) +#define RB_AUGMENT_CHECK(x) (0) #else -#define _RB_AUGMENT(x) (RB_AUGMENT(x)) +#define RB_AUGMENT_CHECK(x) (RB_AUGMENT(x), 1) +#endif #endif -#define _RB_AUGMENT_WALK(head, elm, field) do { \ - __typeof(elm) tmp_up = (elm); \ - while (tmp_up != NULL && _RB_AUGMENT(tmp_up)) { \ - _RB_GET_PARENT(tmp_up, tmp_up, field); \ - _RB_STACK_POP(head, tmp_up); \ - } \ -} while (0) +#define _RB_AUGMENT_WALK(elm, match, field) do { \ +if (match == elm) \ + match = NULL; \ +} while (RB_AUGMENT_CHECK(elm) && \ + (elm = RB_PARENT(elm, field)) != NULL) /* @@ -239,446 +167,193 @@ _RB_GET_CHILD(elm, dir, field) = (__typeof(elm))(((uintptr_t)_RB_GET_CHILD(elm, * / \ / \ * gc1 gc2 c1 gc1 */ -#define _RB_ROTATE(elm, celm, dir, field) do { \ -_RB_SET_CHILD(elm, _RB_ODIR(dir), _RB_GET_CHILD(celm, dir, field), field); \ -if (_RB_PTR(_RB_GET_CHILD(elm, _RB_ODIR(dir), field)) != NULL) \ - _RB_SET_PARENT(_RB_PTR(_RB_GET_CHILD(elm, _RB_ODIR(dir), field)), elm, field); \ -_RB_SET_CHILD(celm, dir, elm, field); \ -_RB_SET_PARENT(elm, celm, field); \ +#define _RB_ROTATE(elm, celm, dir, field) do { \ +if ((_RB_GET_CHILD(elm, _RB_ODIR(dir), field) = _RB_GET_CHILD(celm, dir, field)) != NULL) \ + _RB_SET_PARENT(_RB_GET_CHILD(celm, dir, field), elm, field); \ +_RB_SET_CHILD(celm, dir, elm, field); \ +_RB_SET_PARENT(elm, celm, field); \ +} while (0) + +#define _RB_SWAP_CHILD_OR_ROOT(head, elm, oelm, nelm, field) do { \ +if (elm == NULL) \ + RB_ROOT(head) = nelm; \ +else \ + _RB_SET_CHILD(elm, (RB_LEFT(elm, field) == (oelm) ? _RB_LDIR : _RB_RDIR), nelm, field); \ } while (0) -/* returns -2 if the subtree is not rank balanced else returns the rank of the node */ -#define _RB_GENERATE_RANK(name, type, field, cmp, attr) \ -attr int \ -name##_RB_RANK(const struct type *elm) \ -{ \ - int lrank, rrank; \ - if (elm == NULL) \ - return (-1); \ - lrank = name##_RB_RANK(RB_LEFT(elm, field)); \ - if (lrank == -2) \ - return (-2); \ - rrank = name##_RB_RANK(RB_RIGHT(elm, field)); \ - if (rrank == -2) \ - return (-2); \ - lrank += (_RB_GET_RDIFF(elm, _RB_LDIR, field) == 1) ? 2 : 1; \ - rrank += (_RB_GET_RDIFF(elm, _RB_RDIR, field) == 1) ? 2 : 1; \ - if (lrank != rrank) \ - return (-2); \ - return (lrank); \ +#define _RB_GENERATE_RANK(name, type, field, cmp, attr) \ +attr int \ +name##_RB_RANK(const struct type *elm) \ +{ \ + int lrank, rrank; \ + if (elm == NULL) \ + return (-1); \ + lrank = name##_RB_RANK(RB_LEFT(elm, field)); \ + if (lrank == -2) \ + return (-2); \ + rrank = name##_RB_RANK(RB_RIGHT(elm, field)); \ + if (rrank == -2) \ + return (-2); \ + lrank += (_RB_GET_RDIFF(elm, _RB_LDIR, field) == 0) ? 1 : 2; \ + rrank += (_RB_GET_RDIFF(elm, _RB_RDIR, field) == 0) ? 1 : 2; \ + if (lrank != rrank) \ + return (-2); \ + return (lrank); \ } -/* When doing a balancing of the tree, lets check when we are looking at the edge - * 'elm' to its 'parent'. We assume that 'elm' has already been promoted. - * Now there are two possibilities: - * 1) if 'elm' has rank difference 1 with 'parent', or it is the root node, we are done - * 2) if 'elm' has rank difference 0 with 'parent', we have a few cases - * - * 2.1) the sibling of 'elm' has rank difference 1 with 'parent' then we promote the - * 'parent'. And continue recursively from parent. - * - * gpar gpar - * / /(0/1) - * 1/2 parent - * / 1/ \ - * elm --0-- parent --> elm 2 - * /\ \ /\ \ - * -- 1 -- sibling - * \ /\ - * sibling -- - * /\ - * -- - * - * 2.2) the sibling of 'elm' has rank difference 2 with 'parent', then we need to do - * rotations, based on the child of 'elm' that has rank difference 1 with 'elm' - * (there will always be one such child as 'elm' had to be promoted due to it) - * - * 2.2a) the rdiff 1 child of 'elm', 'c', is in the same direction as 'elm' is wrt - * to 'parent'. We demote the parent and do a single rotation in the opposite - * direction and we are done. - * - * gpar gpar - * / / - * 1/2 1/2 - * / / - * elm --0-- parent --> elm - * / \ \ / \ - * 1 2 2 1 1 - * / \ \ / \ - * c d sibling c parent - * /\ /\ /\ /\ / \ - * -- -- -- -- 1 1 - * / \ - * d sibling - * /\ /\ - * -- -- - * - * 2.2b) the rdiff 1 child of 'elm', 'c', is in the opposite direction as 'elm' is wrt - * to 'parent'. We do a double rotation (with rank changes) and we are done. - * - * gpar gpar - * / / - * 1/2 1/2 - * / / - * elm --0-- parent --> c - * / \ \ 1/ \1 - * 2 1 2 elm parent - * / \ \ 1/ \ / \1 - * d c sibling d c1 c2 sibling - * /\ / \ /\ /\ /\ /\ /\ - * -- c1 c2 -- -- -- -- -- - */ -#define _RB_GENERATE_INSERT(name, type, field, cmp, attr) \ - \ -attr struct type * \ -name##_RB_INSERT_BALANCE(struct name *head, struct type *parent, \ - struct type *elm) \ -{ \ - struct type *child, *gpar; \ - uintptr_t elmdir, sibdir; \ - \ - child = NULL; \ - gpar = NULL; \ - do { \ - /* elm has not been promoted yet */ \ - _RB_ASSERT(parent != NULL); \ - _RB_ASSERT(elm != NULL); \ - elmdir = RB_LEFT(parent, field) == elm ? _RB_LDIR : _RB_RDIR; \ - if (_RB_GET_RDIFF(parent, elmdir, field)) { \ - /* case (1) */ \ - _RB_FLIP_RDIFF(parent, elmdir, field); \ - _RB_STACK_PUSH(head, parent); \ - return (elm); \ - } \ - _RB_STACK_POP(head, gpar); \ - _RB_GET_PARENT(parent, gpar, field); \ - /* case (2) */ \ - sibdir = _RB_ODIR(elmdir); \ - _RB_FLIP_RDIFF(parent, sibdir, field); \ - if (_RB_GET_RDIFF(parent, sibdir, field)) { \ - /* case (2.1) */ \ - (void)_RB_AUGMENT(elm); \ - elm = parent; \ - continue; \ - } \ - _RB_SET_RDIFF0(elm, elmdir, field); \ - /* case (2.2) */ \ - if (_RB_GET_RDIFF(elm, sibdir, field) == 0) { \ - /* case (2.2b) */ \ - child = _RB_PTR(_RB_GET_CHILD(elm, sibdir, field)); \ - _RB_ROTATE(elm, child, elmdir, field); \ - } else { \ - /* case (2.2a) */ \ - child = elm; \ - _RB_FLIP_RDIFF(elm, sibdir, field); \ - } \ - _RB_ROTATE(parent, child, sibdir, field); \ - _RB_SET_PARENT(child, gpar, field); \ - _RB_SWAP_CHILD_OR_ROOT(head, gpar, parent, child, field); \ - (void)_RB_AUGMENT(parent); \ - if (elm != child) \ - (void)_RB_AUGMENT(elm); \ - _RB_STACK_PUSH(head, gpar); \ - return (child); \ - } while ((parent = gpar) != NULL); \ - _RB_STACK_PUSH(head, NULL); \ - return (elm); \ -} \ - \ -/* Inserts a node into the RB tree */ \ -attr struct type * \ -name##_RB_INSERT_FINISH(struct name *head, struct type *parent, \ - uintptr_t insdir, struct type *elm) \ -{ \ - struct type *tmp = elm; \ - _RB_SET_PARENT(elm, parent, field); \ - if (_RB_GET_CHILD(parent, insdir, field)) \ - _RB_SET_CHILD(parent, insdir, elm, field); \ - else { \ - _RB_SET_CHILD(parent, insdir, elm, field); \ - tmp = name##_RB_INSERT_BALANCE(head, parent, elm); \ - _RB_STACK_POP(head, parent); \ - _RB_GET_PARENT(tmp, parent, field); \ - } \ - (void)_RB_AUGMENT(tmp); \ - _RB_AUGMENT_WALK(head, parent, field); \ - return (NULL); \ -} \ - \ -/* Inserts a node into the RB tree */ \ -attr struct type * \ -name##_RB_INSERT(struct name *head, struct type *elm) \ -{ \ - struct type *parent, *tmp; \ - __typeof(cmp(NULL, NULL)) comp; \ - uintptr_t insdir; \ - \ - _RB_STACK_CLEAR(head); \ - _RB_SET_CHILD(elm, _RB_LDIR, NULL, field); \ - _RB_SET_CHILD(elm, _RB_RDIR, NULL, field); \ - tmp = RB_ROOT(head); \ - if (tmp == NULL) { \ - RB_ROOT(head) = elm; \ - _RB_SET_PARENT(elm, NULL, field); \ - return (NULL); \ - } \ - while (tmp) { \ - parent = tmp; \ - comp = cmp(elm, tmp); \ - if (comp < 0) { \ - tmp = RB_LEFT(tmp, field); \ - insdir = _RB_LDIR; \ - } \ - else if (comp > 0) { \ - tmp = RB_RIGHT(tmp, field); \ - insdir = _RB_RDIR; \ - } \ - else \ - return (parent); \ - _RB_STACK_PUSH(head, parent); \ - } \ - /* the stack contains all the nodes upto and including parent */ \ - _RB_STACK_POP(head, parent); \ - return (name##_RB_INSERT_FINISH(head, parent, insdir, elm)); \ +#define _RB_GENERATE_MINMAX(name, type, field, cmp, attr) \ + \ +attr struct type * \ +name##_RB_MINMAX(struct name *head, int dir) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + tmp = _RB_GET_CHILD(tmp, dir, field); \ + } \ + return (parent); \ } -#ifdef RB_SMALL -#define _RB_GENERATE_INSERT_ITERATE(name, type, field, cmp, attr) -#else -#define _RB_GENERATE_INSERT_ITERATE(name, type, field, cmp, attr) \ - \ -attr struct type * \ -name##_RB_INSERT_NEXT(struct name *head, struct type *elm, struct type *next) \ -{ \ - struct type *tmp; \ - uintptr_t insdir = _RB_RDIR; \ - _RB_SET_CHILD(next, _RB_LDIR, NULL, field); \ - _RB_SET_CHILD(next, _RB_RDIR, NULL, field); \ - _RB_ASSERT((cmp)(elm, next) < 0); \ - if (name##_RB_NEXT(elm) != NULL) \ - _RB_ASSERT((cmp)(next, name##_RB_NEXT(elm)) < 0); \ - \ - tmp = RB_RIGHT(elm, field); \ - while (tmp) { \ - elm = tmp; \ - tmp = RB_LEFT(tmp, field); \ - insdir = _RB_LDIR; \ - } \ - return name##_RB_INSERT_FINISH(head, elm, insdir, next); \ -} \ - \ -attr struct type * \ -name##_RB_INSERT_PREV(struct name *head, struct type *elm, struct type *prev) \ -{ \ - struct type *tmp; \ - uintptr_t insdir = _RB_LDIR; \ - _RB_SET_CHILD(prev, _RB_LDIR, NULL, field); \ - _RB_SET_CHILD(prev, _RB_RDIR, NULL, field); \ - _RB_ASSERT((cmp)(elm, prev) > 0); \ - if (name##_RB_PREV(elm) != NULL) \ - _RB_ASSERT((cmp)(prev, name##_RB_PREV(elm)) > 0); \ - \ - tmp = RB_RIGHT(elm, field); \ - while (tmp) { \ - elm = tmp; \ - tmp = RB_LEFT(tmp, field); \ - insdir = _RB_RDIR; \ - } \ - return name##_RB_INSERT_FINISH(head, elm, insdir, prev); \ -} -#endif -#ifdef RB_SMALL -#define _RB_GENERATE_FINDC(name, type, field, cmp, attr) \ - \ -attr struct type * \ -name##_RB_FINDC(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - __typeof(cmp(NULL, NULL)) comp; \ - _RB_STACK_CLEAR(head); \ - while (tmp) { \ - _RB_STACK_PUSH(head, tmp); \ - comp = cmp(elm, tmp); \ - if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (NULL); \ -} \ - \ -attr struct type * \ -name##_RB_NFINDC(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *res = NULL; \ - __typeof(cmp(NULL, NULL)) comp; \ - _RB_STACK_CLEAR(head); \ - while (tmp) { \ - _RB_STACK_PUSH(head, tmp); \ - comp = cmp(elm, tmp); \ - if (comp < 0) { \ - res = tmp; \ - tmp = RB_LEFT(tmp, field); \ - } \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (res); \ -} \ - \ -attr struct type * \ -name##_RB_PFINDC(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *res = NULL; \ - __typeof(cmp(NULL, NULL)) comp; \ - _RB_STACK_CLEAR(head); \ - while (tmp) { \ - _RB_STACK_PUSH(head, tmp); \ - comp = cmp(elm, tmp); \ - if (comp > 0) { \ - res = tmp; \ - tmp = RB_RIGHT(tmp, field); \ - } \ - else if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (res); \ -} -#else -#define _RB_GENERATE_FINDC(name, type, field, cmp, attr) \ - \ -attr struct type * \ -name##_RB_FINDC(struct name *head, struct type *elm) \ -{ \ - return (elm); \ -} \ - \ -attr struct type * \ -name##_RB_NFINDC(struct name *head, struct type *elm) \ -{ \ - return (elm); \ -} \ - \ -attr struct type * \ -name##_RB_PFINDC(struct name *head, struct type *elm) \ -{ \ - return (elm); \ +#define _RB_GENERATE_ITERATE(name, type, field, cmp, attr) \ + \ +attr struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + struct type *parent = NULL; \ + \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + parent = RB_PARENT(elm, field); \ + while (parent && elm == RB_RIGHT(parent, field)) { \ + elm = parent; \ + parent = RB_PARENT(parent, field); \ + } \ + elm = parent; \ + } \ + return (elm); \ +} \ + \ +attr struct type * \ +name##_RB_PREV(struct type *elm) \ +{ \ + struct type *parent = NULL; \ + \ + if (RB_LEFT(elm, field)) { \ + elm = RB_LEFT(elm, field); \ + while (RB_RIGHT(elm, field)) \ + elm = RB_RIGHT(elm, field); \ + } else { \ + parent = RB_PARENT(elm, field); \ + while (parent && elm == RB_LEFT(parent, field)) { \ + elm = parent; \ + parent = RB_PARENT(parent, field); \ + } \ + elm = parent; \ + } \ + return (elm); \ } -#endif -#define _RB_GENERATE_FIND(name, type, field, cmp, attr) \ - \ -attr struct type * \ -name##_RB_FIND(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - __typeof(cmp(NULL, NULL)) comp; \ - while (tmp) { \ - comp = cmp(elm, tmp); \ - if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (NULL); \ -} \ - \ -attr struct type * \ -name##_RB_NFIND(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *res = NULL; \ - __typeof(cmp(NULL, NULL)) comp; \ - while (tmp) { \ - comp = cmp(elm, tmp); \ - if (comp < 0) { \ - res = tmp; \ - tmp = RB_LEFT(tmp, field); \ - } \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (res); \ -} \ - \ -attr struct type * \ -name##_RB_PFIND(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *res = NULL; \ - __typeof(cmp(NULL, NULL)) comp; \ - while (tmp) { \ - comp = cmp(elm, tmp); \ - if (comp > 0) { \ - res = tmp; \ - tmp = RB_RIGHT(tmp, field); \ - } \ - else if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (res); \ -} -#define _RB_GENERATE_MINMAX(name, type, field, cmp, attr) \ - \ -attr struct type * \ -name##_RB_MINMAX(struct name *head, int dir) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *parent = NULL; \ - while (tmp) { \ - parent = tmp; \ - tmp = _RB_PTR(_RB_GET_CHILD(tmp, dir, field)); \ - } \ - return (parent); \ +#define _RB_GENERATE_FIND(name, type, field, cmp, attr) \ + \ +attr struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + __typeof(cmp(NULL, NULL)) comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} \ + \ +attr struct type * \ +name##_RB_NFIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *res = NULL; \ + __typeof(cmp(NULL, NULL)) comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) { \ + res = tmp; \ + tmp = RB_LEFT(tmp, field); \ + } \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (res); \ +} \ + \ +attr struct type * \ +name##_RB_PFIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *res = NULL; \ + __typeof(cmp(NULL, NULL)) comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp > 0) { \ + res = tmp; \ + tmp = RB_RIGHT(tmp, field); \ + } \ + else if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (res); \ } /* - * When doing a balancing of the tree after a removal, lets check when we are looking - * at the edge 'elm' to its 'parent'. + * When doing a balancing of the tree after a removal, lets check + * when we are looking at the edge 'elm' to its 'parent'. * For now, assume that 'elm' has already been demoted. * Now there are two possibilities: - * 1) if 'elm' has rank difference 2 with 'parent', or it is the root node, we are done - * 2) if 'elm' has rank difference 3 with 'parent', we have a few cases + * 1) if 'elm' has rank difference 2 with 'parent', or it is + * the root node, we are done. + * 2) if 'elm' has rank difference 3 with 'parent', we have a + * few cases: * - * 2.1) the sibling of 'elm' has rank difference 2 with 'parent' then we demote the - * 'parent'. And continue recursively from parent. + * 2.1) the sibling of 'elm' has rank difference 2 with 'parent' + * then we demote the 'parent'. And continue recursively from + * parent. * * gpar gpar * / / * 1/2 2/3 * / / - * parent --> parent - * / \ / \ - * 3 2 2 1 - * / \ / \ - * elm sibling elm sibling - * /\ /\ /\ /\ - * -- -- -- -- - * - * 2.2) the sibling of 'elm' has rank difference 1 with 'parent', then we need to do - * rotations, based on the children of the sibling of elm. + * parent --> / + * / \ parent + * 3 2 / \ 1 + * / \ 2 \ + * / sibling / sibling + * elm /\ elm /\ + * /\ -- /\ -- + * -- -- + * + * 2.2) the sibling of 'elm' has rank difference 1 with 'parent', then + * we need to do rotations, based on the children of the + * sibling of elm. * - * 2.2a) Both children of sibling have rdiff 2. Then we demote both parent and sibling - * and continue recursively from parent. + * 2.2a) Both children of sibling have rdiff 2. Then we demote both + * parent and sibling and continue recursively from parent. * * gpar gpar * / / @@ -693,23 +368,25 @@ name##_RB_MINMAX(struct name *head, int dir) \ * -- c d -- c d * * - * 2.2b) the rdiff 1 child of 'sibling', 'c', is in the same direction as 'sibling' is wrt - * to 'parent'. We do a single rotation (with rank changes) and we are done. + * 2.2b) the rdiff 1 child of 'sibling', 'c', is in the same + * direction as 'sibling' is wrt to 'parent'. We do a single + * rotation (with rank changes) and we are done. * - * gpar gpar gpar - * / / / - * 1/2 1/2 if 1/2 - * / / parent->c == 2 / - * parent --> sibling --> sibling - * / \ 1/ \ 2/ \ - * 3 1 parent 2 parent 2 - * / \ 2/ \ \ 1/ \1 \ - * elm sibling elm c d elm c d - * /\ / \1 /\ /\ - * -- c d -- -- + * gpar gpar gpar + * / / / + * 1/2 1/2 if 1/2 + * / / parent->c == 2 / + * parent --> sibling --> sibling + * / \ 1/ \ 2/ \ + * 3 1 parent 2 parent 2 + * / \ 2/ \ \ 1/ \1 \ + * elm sibling elm c d elm c d + * /\ / \1 /\ /\ + * -- c d -- -- * - * 2.2c) the rdiff 1 child of 'sibling', 'c', is in the opposite direction as 'sibling' is wrt - * to 'parent'. We do a double rotation (with rank changes) and we are done. + * 2.2c) the rdiff 1 child of 'sibling', 'c', is in the opposite + * direction as 'sibling' is wrt to 'parent'. We do a double + * rotation (with rank changes) and we are done. * * gpar gpar * / / @@ -726,320 +403,379 @@ name##_RB_MINMAX(struct name *head, int dir) \ * c1 c2 * */ -#define _RB_GENERATE_REMOVE(name, type, field, cmp, attr) \ - \ -attr struct type * \ -name##_RB_REMOVE_BALANCE(struct name *head, struct type *parent, \ - struct type *elm) \ -{ \ - struct type *gpar, *sibling; \ - uintptr_t elmdir, sibdir, ssdiff, sodiff; \ - int extend; \ - \ - _RB_ASSERT(parent != NULL); \ - gpar = NULL; \ - sibling = NULL; \ - if (RB_RIGHT(parent, field) == NULL && RB_LEFT(parent, field) == NULL) {\ - _RB_SET_CHILD(parent, _RB_LDIR, NULL, field); \ - _RB_SET_CHILD(parent, _RB_RDIR, NULL, field); \ - elm = parent; \ - (void)_RB_AUGMENT(elm); \ - _RB_STACK_POP(head, parent); \ - _RB_GET_PARENT(parent, parent, field); \ - if (parent == NULL) { \ - return (NULL); \ - } \ - } \ - do { \ - _RB_ASSERT(parent != NULL); \ - _RB_STACK_POP(head, gpar); \ - _RB_GET_PARENT(parent, gpar, field); \ +#define _RB_GENERATE_REMOVE(name, type, field, cmp, attr) \ + \ +attr struct type * \ +name##_RB_REMOVE_BALANCE(struct name *head, struct type *parent, \ + struct type *elm) \ +{ \ + struct type *gpar, *sibling; \ + uintptr_t elmdir, sibdir, ssdiff, sodiff; \ + \ + gpar = NULL; \ + sibling = NULL; \ + if (RB_RIGHT(parent, field) == NULL && RB_LEFT(parent, field) == NULL) { \ + _RB_SET_RDIFF00(parent, field); \ + elm = parent; \ + if ((parent = RB_PARENT(elm, field)) == NULL) { \ + return (NULL); \ + } \ + } \ + do { \ + _RB_ASSERT(parent != NULL); \ + gpar = RB_PARENT(parent, field); \ elmdir = RB_LEFT(parent, field) == elm ? _RB_LDIR : _RB_RDIR; \ - if (_RB_GET_RDIFF(parent, elmdir, field) == 0) { \ - /* case (1) */ \ - _RB_FLIP_RDIFF(parent, elmdir, field); \ - _RB_STACK_PUSH(head, gpar); \ - return (parent); \ - } \ - /* case 2 */ \ - sibdir = _RB_ODIR(elmdir); \ - if (_RB_GET_RDIFF(parent, sibdir, field)) { \ - /* case 2.1 */ \ - _RB_FLIP_RDIFF(parent, sibdir, field); \ - (void)_RB_AUGMENT(parent); \ - continue; \ - } \ - /* case 2.2 */ \ - sibling = _RB_PTR(_RB_GET_CHILD(parent, sibdir, field)); \ - _RB_ASSERT(sibling != NULL); \ - ssdiff = _RB_GET_RDIFF(sibling, elmdir, field); \ - sodiff = _RB_GET_RDIFF(sibling, sibdir, field); \ - if (ssdiff && sodiff) { \ - /* case 2.2a */ \ - _RB_FLIP_RDIFF(sibling, elmdir, field); \ - _RB_FLIP_RDIFF(sibling, sibdir, field); \ - (void)_RB_AUGMENT(parent); \ - continue; \ - } \ - extend = 0; \ - if (sodiff) { \ - /* case 2.2c */ \ - _RB_FLIP_RDIFF(sibling, sibdir, field); \ - _RB_FLIP_RDIFF(parent, elmdir, field); \ - elm = _RB_PTR(_RB_GET_CHILD(sibling, elmdir, field)); \ - _RB_ROTATE(sibling, elm, sibdir, field); \ - _RB_SET_RDIFF1(elm, sibdir, field); \ - extend = 1; \ - } else { \ - /* case 2.2b */ \ - _RB_FLIP_RDIFF(sibling, sibdir, field); \ - if (ssdiff) { \ - _RB_FLIP_RDIFF(sibling, elmdir, field); \ - _RB_FLIP_RDIFF(parent, elmdir, field); \ - extend = 1; \ - } \ - _RB_FLIP_RDIFF(parent, sibdir, field); \ - elm = sibling; \ - } \ - _RB_ROTATE(parent, elm, elmdir, field); \ - _RB_SET_PARENT(elm, gpar, field); \ - _RB_SWAP_CHILD_OR_ROOT(head, gpar, parent, elm, field); \ - if (extend) { \ - _RB_SET_RDIFF1(elm, elmdir, field); \ - } \ - (void)_RB_AUGMENT(parent); \ - if (elm != sibling) \ - (void)_RB_AUGMENT(sibling); \ - _RB_STACK_PUSH(head, gpar); \ - return (elm); \ - } while ((elm = parent, (parent = gpar) != NULL)); \ - _RB_STACK_PUSH(head, NULL); \ - return (elm); \ -} \ - \ -attr struct type * \ -name##_RB_REMOVE_START(struct name *head, struct type *elm) \ -{ \ - struct type *parent, *opar, *child, *rmin, *cptr; \ - size_t sz; \ - \ - parent = NULL; \ - opar = NULL; \ - _RB_STACK_TOP(head, opar); \ - _RB_GET_PARENT(elm, opar, field); \ - \ - /* first find the element to swap with oelm */ \ - child = _RB_GET_CHILD(elm, _RB_LDIR, field); \ - cptr = _RB_PTR(child); \ - rmin = RB_RIGHT(elm, field); \ - if (rmin == NULL || cptr == NULL) { \ - rmin = child = (rmin == NULL ? cptr : rmin); \ - parent = opar; \ - _RB_STACK_DROP(head); \ - } \ - else { \ - _RB_STACK_PUSH(head, elm); \ - _RB_STACK_SIZE(head, &sz); \ - parent = rmin; \ - while (RB_LEFT(rmin, field)) { \ - _RB_STACK_PUSH(head, rmin); \ - rmin = RB_LEFT(rmin, field); \ - } \ - _RB_SET_CHILD(rmin, _RB_LDIR, child, field); \ - _RB_SET_PARENT(cptr, rmin, field); \ - child = _RB_GET_CHILD(rmin, _RB_RDIR, field); \ - if (parent != rmin) { \ - _RB_SET_PARENT(parent, rmin, field); \ - _RB_SET_CHILD(rmin, _RB_RDIR, _RB_GET_CHILD(elm, _RB_RDIR, field), field); \ - _RB_GET_PARENT(rmin, parent, field); \ - _RB_STACK_POP(head, parent); \ - _RB_REPLACE_CHILD(parent, _RB_LDIR, child, rmin, field);\ - _RB_STACK_SET(head, sz - 1, rmin); \ - } else { \ - _RB_STACK_SET(head, sz - 1, NULL); \ - _RB_STACK_DROP(head); \ - if (_RB_GET_RDIFF(elm, _RB_RDIR, field)) \ - _RB_SET_RDIFF1(rmin, _RB_RDIR, field); \ - } \ - _RB_SET_PARENT(rmin, opar, field); \ - } \ - _RB_SWAP_CHILD_OR_ROOT(head, opar, elm, rmin, field); \ - if (child != NULL) { \ - _RB_SET_PARENT(child, parent, field); \ - } \ - if (parent != NULL) { \ - parent = name##_RB_REMOVE_BALANCE(head, parent, child); \ - _RB_AUGMENT_WALK(head, parent, field); \ - } \ - return (elm); \ -} \ - \ -attr struct type * \ -name##_RB_REMOVE(struct name *head, struct type *elm) \ -{ \ - struct type *telm = elm; \ - \ - telm = name##_RB_FINDC(head, elm); \ - if (telm == NULL) \ - return (NULL); \ - _RB_STACK_POP(head, telm); \ - _RB_ASSERT((cmp(telm, elm)) == 0); \ - return (name##_RB_REMOVE_START(head, telm)); \ + if (_RB_GET_RDIFF(parent, elmdir, field) == 0) { \ + /* case (1) */ \ + _RB_FLIP_RDIFF(parent, elmdir, field); \ + return (NULL); \ + } \ + /* case 2 */ \ + sibdir = _RB_ODIR(elmdir); \ + if (_RB_GET_RDIFF(parent, sibdir, field)) { \ + /* case 2.1 */ \ + _RB_FLIP_RDIFF(parent, sibdir, field); \ + continue; \ + } \ + /* case 2.2 */ \ + sibling = _RB_GET_CHILD(parent, sibdir, field); \ + _RB_ASSERT(sibling != NULL); \ + ssdiff = _RB_GET_RDIFF(sibling, elmdir, field); \ + sodiff = _RB_GET_RDIFF(sibling, sibdir, field); \ + _RB_FLIP_RDIFF(sibling, sibdir, field); \ + if (ssdiff && sodiff) { \ + /* case 2.2a */ \ + _RB_FLIP_RDIFF(sibling, elmdir, field); \ + continue; \ + } \ + if (sodiff) { \ + /* case 2.2c */ \ + elm = _RB_GET_CHILD(sibling, elmdir, field); \ + _RB_ROTATE(sibling, elm, sibdir, field); \ + _RB_FLIP_RDIFF(parent, elmdir, field); \ + if (_RB_GET_RDIFF(elm, elmdir, field)) \ + _RB_FLIP_RDIFF(parent, sibdir, field); \ + if (_RB_GET_RDIFF(elm, sibdir, field)) \ + _RB_FLIP_RDIFF(sibling, elmdir, field); \ + _RB_SET_RDIFF11(elm, field); \ + } else { \ + /* case 2.2b */ \ + if (ssdiff) { \ + _RB_SET_RDIFF11(sibling, field); \ + _RB_SET_RDIFF00(parent, field); \ + } \ + elm = sibling; \ + } \ + _RB_ROTATE(parent, elm, elmdir, field); \ + _RB_SET_PARENT(elm, gpar, field); \ + _RB_SWAP_CHILD_OR_ROOT(head, gpar, parent, elm, field); \ + if (elm != sibling) \ + (void)RB_AUGMENT_CHECK(sibling); \ + return (elm); \ + } while ((elm = parent, (parent = gpar) != NULL)); \ + return (elm); \ +} \ + \ +attr struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *opar, *child, *rmin; \ + \ + /* first find the element to swap with elm */ \ + child = RB_LEFT(elm, field); \ + rmin = RB_RIGHT(elm, field); \ + if (rmin == NULL || child == NULL) { \ + rmin = child = (rmin == NULL ? child : rmin); \ + parent = opar = RB_PARENT(elm, field); \ + } \ + else { \ + parent = rmin; \ + while (RB_LEFT(rmin, field)) { \ + rmin = RB_LEFT(rmin, field); \ + } \ + _RB_SET_PARENT(child, rmin, field); \ + _RB_SET_CHILD(rmin, _RB_LDIR, child, field); \ + child = RB_RIGHT(rmin, field); \ + if (parent != rmin) { \ + _RB_SET_PARENT(parent, rmin, field); \ + _RB_SET_CHILD(rmin, _RB_RDIR, parent, field); \ + parent = RB_PARENT(rmin, field); \ + _RB_SET_CHILD(parent, _RB_LDIR, child, field); \ + } \ + _RB_COPY_PARENT(elm, rmin, field); \ + opar = RB_PARENT(elm, field); \ + } \ + _RB_SWAP_CHILD_OR_ROOT(head, opar, elm, rmin, field); \ + if (child != NULL) { \ + _RB_REPLACE_PARENT(child, parent, field); \ + } \ + if (parent != NULL) { \ + opar = name##_RB_REMOVE_BALANCE(head, parent, child); \ + if (parent == rmin && RB_LEFT(parent, field) == NULL) { \ + opar = NULL; \ + parent = RB_PARENT(parent, field); \ + } \ + _RB_AUGMENT_WALK(parent, opar, field); \ + if (opar != NULL) { \ + (void)RB_AUGMENT_CHECK(opar); \ + (void)RB_AUGMENT_CHECK(RB_PARENT(opar, field)); \ + } \ + } \ + return (elm); \ } -#ifdef RB_SMALL -#define _RB_GENERATE_REMOVEC(name, type, field, cmp, attr) \ - \ -attr struct type * \ -name##_RB_REMOVEC(struct name *head, struct type *elm) \ -{ \ - struct type *telm = elm; \ - \ - _RB_STACK_POP(head, telm); \ - _RB_ASSERT((cmp(telm, elm)) == 0); \ - return (name##_RB_REMOVE_START(head, telm)); \ -} -#else -#define _RB_GENERATE_REMOVEC(name, type, field, cmp, attr) \ - \ -attr struct type * \ -name##_RB_REMOVEC(struct name *head, struct type *elm) \ -{ \ - return (NULL); \ -} -#endif -#ifndef RB_SMALL -#define _RB_GENERATE_ITERATE(name, type, field, cmp, attr) \ +/* + * When doing a balancing of the tree, lets check when we are looking + * at the edge 'elm' to its 'parent'. + * We assume that 'elm' has already been promoted. + * Now there are two possibilities: + * 1) if 'elm' has rank difference 1 with 'parent', or it is the root + * node, we are done. + * 2) if 'elm' has rank difference 0 with 'parent', we have a few cases: + * + * 2.1) the sibling of 'elm' has rank difference 1 with 'parent' then + * we promote the 'parent'. And continue recursively from parent. + * + * gpar gpar + * / /(0/1) + * 1/2 parent + * / 1/ \ + * elm --0-- parent --> elm 2 + * /\ \ /\ \ + * -- 1 -- sibling + * \ /\ + * sibling -- + * /\ + * -- + * + * 2.2) the sibling of 'elm' has rank difference 2 with 'parent', + * then we need to do rotations based on the child of 'elm' + * that has rank difference 1 with 'elm'. + * there will always be one such child as 'elm' had to be promoted. + * + * 2.2a) the rdiff 1 child of 'elm', 'c', is in the same direction + * as 'elm' is wrt to 'parent'. We demote the parent and do + * a single rotation in the opposite direction and we are done. + * + * gpar gpar + * / / + * 1/2 1/2 + * / / + * elm --0-- parent --> elm + * / \ \ / \ + * 1 2 2 1 1 + * / \ \ / \ + * c d sibling c parent + * /\ /\ /\ /\ / \ + * -- -- -- -- 1 1 + * / \ + * d sibling + * /\ /\ + * -- -- + * + * 2.2b) the rdiff 1 child of 'elm', 'c', is in the opposite + * direction as 'elm' is wrt to 'parent'. We do a double + * rotation (with rank changes) and we are done. + * + * gpar gpar + * / / + * 1/2 1/2 + * / / + * elm --0-- parent --> c + * / \ \ 1/ \1 + * 2 1 2 elm parent + * / \ \ 1/ \ / \1 + * d c sibling d c1 c2 sibling + * /\ / \ /\ /\ /\ /\ /\ + * -- c1 c2 -- -- -- -- -- + */ +#define _RB_GENERATE_INSERT(name, type, field, cmp, attr) \ \ attr struct type * \ -name##_RB_NEXT(struct type *elm) \ +name##_RB_INSERT_BALANCE(struct name *head, struct type *parent, \ + struct type *elm) \ { \ - struct type *parent = NULL; \ + struct type *child, *child_up, *gpar; \ + uintptr_t elmdir, sibdir; \ \ - if (RB_RIGHT(elm, field)) { \ - elm = RB_RIGHT(elm, field); \ - while (RB_LEFT(elm, field)) \ - elm = RB_LEFT(elm, field); \ - } else { \ - _RB_GET_PARENT(elm, parent, field); \ - while (parent && elm == RB_RIGHT(parent, field)) { \ + child = NULL; \ + gpar = NULL; \ + do { \ + /* elm has not been promoted yet */ \ + elmdir = RB_LEFT(parent, field) == elm ? _RB_LDIR : _RB_RDIR; \ + if (_RB_GET_RDIFF(parent, elmdir, field)) { \ + /* case (1) */ \ + _RB_FLIP_RDIFF(parent, elmdir, field); \ + return (elm); \ + } \ + /* case (2) */ \ + gpar = RB_PARENT(parent, field); \ + sibdir = _RB_ODIR(elmdir); \ + _RB_FLIP_RDIFF(parent, sibdir, field); \ + if (_RB_GET_RDIFF(parent, sibdir, field)) { \ + /* case (2.1) */ \ + child = elm; \ elm = parent; \ - _RB_GET_PARENT(parent, parent, field); \ + continue; \ } \ - elm = parent; \ - } \ - return (elm); \ + /* we can only reach this point if we are in the \ + * second or greater iteration of the while loop \ + * which means that 'child' has been populated \ + */ \ + _RB_SET_RDIFF00(parent, field); \ + /* case (2.2) */ \ + if (_RB_GET_RDIFF(elm, sibdir, field) == 0) { \ + /* case (2.2b) */ \ + _RB_ROTATE(elm, child, elmdir, field); \ + if (_RB_GET_RDIFF(child, sibdir, field)) \ + _RB_FLIP_RDIFF(parent, elmdir, field); \ + if (_RB_GET_RDIFF(child, elmdir, field)) \ + _RB_FLIP_RDIFF2(elm, field); \ + else \ + _RB_FLIP_RDIFF(elm, elmdir, field); \ + if (_RB_GET_RDIFF2(child, field) == 0) \ + elm = child; \ + } else { \ + /* case (2.2a) */ \ + child = elm; \ + } \ + _RB_ROTATE(parent, child, sibdir, field); \ + _RB_REPLACE_PARENT(child, gpar, field); \ + _RB_SWAP_CHILD_OR_ROOT(head, gpar, parent, child, field); \ + if (elm != child) \ + (void)RB_AUGMENT_CHECK(elm); \ + (void)RB_AUGMENT_CHECK(parent); \ + return (child); \ + } while ((parent = gpar) != NULL); \ + return (NULL); \ } \ \ +/* Inserts a node into the RB tree */ \ attr struct type * \ -name##_RB_PREV(struct type *elm) \ +name##_RB_INSERT_FINISH(struct name *head, struct type *parent, \ + struct type **tmpp, struct type *elm) \ { \ - struct type *parent = NULL; \ + struct type *tmp = elm; \ + _RB_SET_CHILD(elm, _RB_LDIR, NULL, field); \ + _RB_SET_CHILD(elm, _RB_RDIR, NULL, field); \ + _RB_REPLACE_PARENT(elm, parent, field); \ + *tmpp = elm; \ + if (parent != NULL) \ + tmp = name##_RB_INSERT_BALANCE(head, parent, elm); \ + _RB_AUGMENT_WALK(elm, tmp, field); \ + if (tmp != NULL) \ + (void)RB_AUGMENT_CHECK(tmp); \ + return (NULL); \ +} \ \ - if (RB_LEFT(elm, field)) { \ - elm = RB_LEFT(elm, field); \ - while (RB_RIGHT(elm, field)) \ - elm = RB_RIGHT(elm, field); \ - } else { \ - _RB_GET_PARENT(elm, parent, field); \ - while (parent && elm == RB_LEFT(parent, field)) { \ - elm = parent; \ - _RB_GET_PARENT(parent, parent, field); \ +/* Inserts a node into the RB tree */ \ +attr struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent=NULL; \ + struct type **tmpp=&RB_ROOT(head); \ + __typeof(cmp(NULL, NULL)) comp; \ + \ + while ((tmp = *tmpp) != NULL) { \ + parent = tmp; \ + comp = cmp(elm, tmp); \ + if (comp < 0) { \ + tmpp = &RB_LEFT(tmp, field); \ } \ - elm = parent; \ + else if (comp > 0) { \ + tmpp = &RB_RIGHT(tmp, field); \ + } \ + else \ + return (parent); \ } \ - return (elm); \ + return (name##_RB_INSERT_FINISH(head, parent, tmpp, elm)); \ +} \ + \ +attr struct type * \ +name##_RB_INSERT_NEXT(struct name *head, struct type *elm, struct type *next) \ +{ \ + struct type *tmp; \ + struct type **tmpp; \ + _RB_ASSERT((cmp)(elm, next) < 0); \ + if (name##_RB_NEXT(elm) != NULL) \ + _RB_ASSERT((cmp)(next, name##_RB_NEXT(elm)) < 0); \ + tmpp = &RB_RIGHT(elm, field); \ + while ((tmp = *tmpp) != NULL) { \ + elm = tmp; \ + tmpp = &RB_LEFT(tmp, field); \ + } \ + return name##_RB_INSERT_FINISH(head, elm, tmpp, next); \ +} \ + \ +attr struct type * \ +name##_RB_INSERT_PREV(struct name *head, struct type *elm, struct type *prev) \ +{ \ + struct type *tmp; \ + struct type **tmpp; \ + _RB_ASSERT((cmp)(elm, prev) > 0); \ + if (name##_RB_PREV(elm) != NULL) \ + _RB_ASSERT((cmp)(prev, name##_RB_PREV(elm)) > 0); \ + \ + tmpp = &RB_LEFT(elm, field); \ + while ((tmp = *tmpp) != NULL) { \ + elm = tmp; \ + tmpp = &RB_RIGHT(tmp, field); \ + } \ + return name##_RB_INSERT_FINISH(head, elm, tmpp, prev); \ } -#else -#define _RB_GENERATE_ITERATE(name, type, field, cmp, attr) -#endif -#define RB_GENERATE(name, type, field, cmp) \ +#define RB_GENERATE(name, type, field, cmp) \ _RB_GENERATE_INTERNAL(name, type, field, cmp,) -#define RB_GENERATE_STATIC(name, type, field, cmp) \ +#define RB_GENERATE_STATIC(name, type, field, cmp) \ _RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) -#define _RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ - _RB_GENERATE_RANK(name, type, field, cmp, attr) \ - _RB_GENERATE_FIND(name, type, field, cmp, attr) \ - _RB_GENERATE_FINDC(name, type, field, cmp, attr) \ - _RB_GENERATE_INSERT(name, type, field, cmp, attr) \ - _RB_GENERATE_INSERT_ITERATE(name, type, field, cmp, attr) \ - _RB_GENERATE_REMOVE(name, type, field, cmp, attr) \ - _RB_GENERATE_REMOVEC(name, type, field, cmp, attr) \ - _RB_GENERATE_ITERATE(name, type, field, cmp, attr) \ - _RB_GENERATE_MINMAX(name, type, field, cmp, attr) +#define _RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ + _RB_GENERATE_RANK(name, type, field, cmp, attr) \ + _RB_GENERATE_MINMAX(name, type, field, cmp, attr) \ + _RB_GENERATE_ITERATE(name, type, field, cmp, attr) \ + _RB_GENERATE_FIND(name, type, field, cmp, attr) \ + _RB_GENERATE_REMOVE(name, type, field, cmp, attr) \ + _RB_GENERATE_INSERT(name, type, field, cmp, attr) -#define RB_PROTOTYPE(name, type, field, cmp) \ +#define RB_PROTOTYPE(name, type, field, cmp) \ _RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) -#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ +#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ _RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static) -#define _RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ - _RB_PROTOTYPE_INTERNAL_COMMON(name, type, field, cmp, attr) \ - _RB_PROTOTYPE_INTERNAL_ITERATE(name, type, field, cmp, attr) \ - _RB_PROTOTYPE_INTERNAL_CACHE(name, type, field, cmp, attr) - -#define _RB_PROTOTYPE_INTERNAL_COMMON(name, type, field, cmp, attr) \ -attr int name##_RB_RANK(const struct type *); \ -attr struct type *name##_RB_FIND(struct name *, struct type *); \ -attr struct type *name##_RB_NFIND(struct name *, struct type *); \ -attr struct type *name##_RB_PFIND(struct name *, struct type *); \ -attr struct type *name##_RB_INSERT(struct name *, struct type *); \ +#define _RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ +attr int name##_RB_RANK(const struct type *); \ +attr struct type *name##_RB_MINMAX(struct name *, int); \ +attr struct type *name##_RB_NEXT(struct type *); \ +attr struct type *name##_RB_PREV(struct type *); \ +attr struct type *name##_RB_FIND(struct name *, struct type *); \ +attr struct type *name##_RB_NFIND(struct name *, struct type *); \ +attr struct type *name##_RB_PFIND(struct name *, struct type *); \ attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ -attr struct type *name##_RB_MINMAX(struct name *, int); \ - -#ifdef RB_SMALL -#define _RB_PROTOTYPE_INTERNAL_ITERATE(name, type, field, cmp, attr) -#else -#define _RB_PROTOTYPE_INTERNAL_ITERATE(name, type, field, cmp, attr) \ -attr struct type *name##_RB_NEXT(struct type *); \ -attr struct type *name##_RB_PREV(struct type *); \ +attr struct type *name##_RB_INSERT(struct name *, struct type *); \ attr struct type *name##_RB_INSERT_NEXT(struct name *, struct type *, struct type *); \ attr struct type *name##_RB_INSERT_PREV(struct name *, struct type *, struct type *); -#endif - -#ifdef RB_SMALL -#define _RB_PROTOTYPE_INTERNAL_CACHE(name, type, field, cmp, attr) \ -attr struct type *name##_RB_FINDC(struct name *, struct type *); \ -attr struct type *name##_RB_NFINDC(struct name *, struct type *); \ -attr struct type *name##_RB_PFINDC(struct name *, struct type *); \ -attr struct type *name##_RB_REMOVEC(struct name *, struct type *); -#else -#define _RB_PROTOTYPE_INTERNAL_CACHE(name, type, field, cmp, attr) -#endif #define RB_RANK(name, head) name##_RB_RANK(head) -#define RB_FIND(name, head, elm) name##_RB_FIND(head, elm) -#define RB_NFIND(name, head, elm) name##_RB_NFIND(head, elm) -#define RB_PFIND(name, head, elm) name##_RB_PFIND(head, elm) -#define RB_INSERT(name, head, elm) name##_RB_INSERT(head, elm) -#define RB_REMOVE(name, head, elm) name##_RB_REMOVE(head, elm) #define RB_MIN(name, head) name##_RB_MINMAX(head, _RB_LDIR) #define RB_MAX(name, head) name##_RB_MINMAX(head, _RB_RDIR) - -#ifdef RB_SMALL -#define RB_FINDC(name, head, elm) name##_RB_FINDC(head, elm) -#define RB_NFINDC(name, head, elm) name##_RB_NFINDC(head, elm) -#define RB_PFINDC(name, head, elm) name##_RB_PFINDC(head, elm) -#define RB_REMOVEC(name, head, elm) name##_RB_REMOVEC(head, elm) -#endif - -#ifndef RB_SMALL #define RB_NEXT(name, head, elm) name##_RB_NEXT(elm) #define RB_PREV(name, head, elm) name##_RB_PREV(elm) +#define RB_FIND(name, head, elm) name##_RB_FIND(head, elm) +#define RB_NFIND(name, head, elm) name##_RB_NFIND(head, elm) +#define RB_PFIND(name, head, elm) name##_RB_PFIND(head, elm) +#define RB_REMOVE(name, head, elm) name##_RB_REMOVE(head, elm) +#define RB_INSERT(name, head, elm) name##_RB_INSERT(head, elm) #define RB_INSERT_NEXT(name, head, elm, next) name##_RB_INSERT_NEXT(head, elm, next) #define RB_INSERT_PREV(name, head, elm, prev) name##_RB_INSERT_PREV(head, elm, prev) -#endif -#ifndef RB_SMALL #define RB_FOREACH(x, name, head) \ for ((x) = RB_MIN(name, head); \ (x) != NULL; \ @@ -1069,6 +805,5 @@ attr struct type *name##_RB_REMOVEC(struct name *, struct type *); for ((x) = RB_MAX(name, head); \ ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ (x) = (y)) -#endif #endif /* _SYS_TREE_H_ */ diff --git a/meson.build b/meson.build index 8365449..e26cbe5 100644 --- a/meson.build +++ b/meson.build @@ -6,11 +6,6 @@ project('rbtree', 'c', ] ) -c = meson.get_compiler('c') - -add_global_arguments(['-Wno-unused-function', '-Wno-format'], - language: 'c') - incdir = include_directories('include') freebsd = include_directories('freebsd') diff --git a/tests/meson.build b/tests/meson.build index 6cc7ded..3cf7f0e 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -3,28 +3,18 @@ test_sources = [ ] foreach ts : test_sources - t_2ptr = executable('native-2ptr-' + ts, ts + '.c', c_args : ['-DRB_SMALL'], include_directories : incdir) t_3ptr = executable('native-3ptr-' + ts, ts + '.c', include_directories : incdir) - t_2ptr_aug = executable('native-2ptr-augment-' + ts, ts + '.c', c_args : ['-DRB_SMALL', '-DDOAUGMENT'], include_directories : incdir) t_3ptr_aug = executable('native-3ptr-augment-' + ts, ts + '.c', c_args : ['-DDOAUGMENT'], include_directories : incdir) t_fbsd = executable('freebsd-' + ts, ts + '.c', include_directories : freebsd) t_fbsd_aug = executable('freebsd-augment-' + ts, ts + '.c', c_args : ['-DDOAUGMENT'], include_directories : freebsd) t_obsd = executable('openbsd-' + ts, ts + '.c', include_directories : openbsd) - test('native-2ptr-' + ts, t_2ptr) + t_obsd_aug = executable('openbsd-augment-' + ts, ts + '.c', c_args : ['-DDOAUGMENT'], include_directories : openbsd) test('native-3ptr-' + ts, t_3ptr) - test('native-2ptr-augment-' + ts, t_2ptr_aug) test('native-3ptr-augment-' + ts, t_3ptr_aug) benchmark('freebsd-' + ts, t_fbsd) benchmark('freebsd-augment-' + ts, t_fbsd_aug) benchmark('openbsd-' + ts, t_obsd) - benchmark('native-2ptr-' + ts, t_2ptr) + benchmark('openbsd-augment-' + ts, t_obsd_aug) benchmark('native-3ptr-' + ts, t_3ptr) - benchmark('native-2ptr-augment-' + ts, t_2ptr_aug) benchmark('native-3ptr-augment-' + ts, t_3ptr_aug) endforeach - -test_subr_2ptr = executable('test_subr_2ptr', ['test_subr.c', 'subr_tree.c'], c_args : ['-DRBT_SMALL'], include_directories : incdir) -test('native-subr-2ptr', test_subr_2ptr) - -test_subr_3ptr = executable('test_subr_3ptr', ['test_subr.c', 'subr_tree.c'], include_directories : incdir) -test('native-subr-3ptr', test_subr_3ptr) diff --git a/tests/test_regress.c b/tests/test_regress.c index 95bf079..9f243cc 100644 --- a/tests/test_regress.c +++ b/tests/test_regress.c @@ -30,19 +30,19 @@ struct timespec start, end, diff, rstart, rend, rdiff, rtot = {0, 0}; } while (0) #endif -//#define RB_SMALL //#define RB_TEST_RANK //#define RB_TEST_DIAGNOSTIC //#define _RB_DIAGNOSTIC #ifdef DOAUGMENT #define RB_AUGMENT(elm) tree_augment(elm) +#define RB_AUGMENT_CHECK(elm) tree_augment(elm) #endif #include "tree.h" #define TDEBUGF(fmt, ...) fprintf(stderr, "%s:%d:%s(): " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__) - +//#define TDEBUGF(fmt, ...) do {} while (0) #ifdef __OpenBSD__ #define SEED_RANDOM srandom_deterministic @@ -51,7 +51,8 @@ struct timespec start, end, diff, rstart, rend, rdiff, rtot = {0, 0}; #endif int ITER=150000; -int RANK_TEST_ITERATIONS=10000; +int RANK_TEST_ITERATIONS=1; +long long augment_count = 0; #define MAX(a, b) ((a) > (b) ? (a) : (b)) @@ -101,7 +102,10 @@ int main() { struct node *tmp, *ins, *nodes; - int i, r, rank, *perm, *nums; + int i, r, *perm, *nums; +#ifdef RB_TEST_RANK + int rank; +#endif nodes = calloc((ITER + 5), sizeof(struct node)); perm = calloc(ITER, sizeof(int)); @@ -120,6 +124,7 @@ main() perm[r] = i; nums[i] = i; } + /* fprintf(stderr, "{"); for(int i = 0; i < ITER; i++) { @@ -150,6 +155,9 @@ main() clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); TDEBUGF("done random insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("total augment count: %lld", augment_count); + TDEBUGF("current rank = %d and size = %d", RB_RANK(tree, RB_ROOT(&root)), RB_ROOT(&root)->size); + augment_count = 0; #ifdef DOAUGMENT ins = RB_ROOT(&root); @@ -161,7 +169,7 @@ main() ins = RB_MIN(tree, &root); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done getting min in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done getting min in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); assert(0 == ins->key); TDEBUGF("getting max"); @@ -169,7 +177,7 @@ main() ins = RB_MAX(tree, &root); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done getting max in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done getting max in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); assert(ITER + 5 == ins->key); ins = RB_ROOT(&root); @@ -203,13 +211,15 @@ main() clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); TDEBUGF("done root removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("total augment count: %lld", augment_count); + augment_count = 0; TDEBUGF("starting sequential insertions"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -234,7 +244,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing find and remove in sequential order"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -255,7 +265,7 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); ins = RB_ROOT(&root); if (ins == NULL) @@ -268,7 +278,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing find and remove in random order"); @@ -293,7 +303,7 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); ins = RB_ROOT(&root); if (ins == NULL) @@ -306,7 +316,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing nfind and remove"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -329,15 +339,14 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#ifdef RB_NEXT TDEBUGF("starting sequential insertions"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree with RB_NEXT"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -351,7 +360,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree with RB_PREV"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -365,7 +374,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -384,15 +393,14 @@ main() clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); TDEBUGF("done root removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#endif -#ifdef RB_PFIND +#ifdef RB_PFIND_NOT_DEFINED TDEBUGF("starting sequential insertions"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing pfind and remove"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -415,119 +423,17 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#endif - -#ifdef RB_FINDC - TDEBUGF("starting sequential insertions"); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); - mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); - timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); - - TDEBUGF("doing findc and removec"); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); - tmp = malloc(sizeof(struct node)); - for(i = 0; i < ITER; i++) { - tmp->key = i; - ins = RB_FINDC(tree, &root, tmp); - if (ins == NULL) - errx(1, "RB_FINDC failed"); - if (RB_REMOVEC(tree, &root, ins) == NULL) - errx(1, "RB_REMOVEC failed: %d", i); -#ifdef RB_TEST_RANK - if (i % RANK_TEST_ITERATIONS == 0) { - rank = RB_RANK(tree, RB_ROOT(&root)); - if (rank == -2) - errx(1, "rank error"); - } -#endif - } - free(tmp); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); - timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); - - ins = RB_ROOT(&root); - if (ins == NULL) - errx(1, "RB_ROOT error"); - if (RB_REMOVE(tree, &root, ins) != ins) - errx(1, "RB_REMOVE failed"); -#endif - -#ifdef RB_NFINDC - TDEBUGF("starting sequential insertions"); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); - mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); - timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); - - TDEBUGF("doing nfindc and removec"); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); - tmp = malloc(sizeof(struct node)); - for(i = 0; i < ITER + 1; i++) { - tmp->key = i; - ins = RB_NFINDC(tree, &root, tmp); - if (ins == NULL) - errx(1, "RB_NFINDC failed"); - if (RB_REMOVEC(tree, &root, ins) == NULL) - errx(1, "RB_REMOVEC failed: %d", i); -#ifdef RB_TEST_RANK - if (i % RANK_TEST_ITERATIONS == 0) { - rank = RB_RANK(tree, RB_ROOT(&root)); - if (rank == -2) - errx(1, "rank error"); - } -#endif - } - free(tmp); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); - timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif -#ifdef RB_PFINDC - TDEBUGF("starting sequential insertions"); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); - mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); - timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); - - TDEBUGF("doing pfindc and removec"); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); - tmp = malloc(sizeof(struct node)); - for(i = 0; i < ITER + 1; i++) { - tmp->key = ITER + 6; - ins = RB_PFINDC(tree, &root, tmp); - if (ins == NULL) - errx(1, "RB_PFINDC failed"); - if (RB_REMOVEC(tree, &root, ins) == NULL) - errx(1, "RB_REMOVEC failed: %d", i); -#ifdef RB_TEST_RANK - if (i % RANK_TEST_ITERATIONS == 0) { - rank = RB_RANK(tree, RB_ROOT(&root)); - if (rank == -2) - errx(1, "rank error"); - } -#endif - } - free(tmp); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); - timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#endif TDEBUGF("starting sequential insertions"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#ifdef RB_FOREACH TDEBUGF("iterating over tree with RB_FOREACH"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); i = 0; @@ -540,10 +446,8 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#endif + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#ifdef RB_FOREACH_REVERSE TDEBUGF("iterating over tree with RB_FOREACH_REVERSE"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); i = ITER + 5; @@ -556,8 +460,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#endif + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -577,13 +480,12 @@ main() timespecsub(&end, &start, &diff); TDEBUGF("done root removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#ifdef RB_FOREACH_SAFE TDEBUGF("starting sequential insertions"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree and clearing with RB_FOREACH_SAFE"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -598,16 +500,14 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#endif + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#ifdef RB_FOREACH_REVERSE_SAFE TDEBUGF("starting sequential insertions"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree and clearing with RB_FOREACH_REVERSE_SAFE"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -622,8 +522,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); -#endif + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #ifdef RB_INSERT_NEXT TDEBUGF("starting sequential insertions using INSERT_NEXT"); @@ -653,7 +552,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done insertions in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done insertions in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree and clearing with RB_FOREACH_REVERSE_SAFE"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -662,7 +561,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif #ifdef RB_INSERT_PREV @@ -693,7 +592,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done insertions in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done insertions in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree and clearing with RB_FOREACH_REVERSE_SAFE"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -702,7 +601,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif TDEBUGF("doing 50%% insertions, 50%% lookups"); @@ -710,7 +609,7 @@ main() mix_operations(perm, ITER, nodes, ITER, ITER / 2, ITER / 2, 1); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done operations in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done operations in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -730,7 +629,7 @@ main() mix_operations(perm, ITER, nodes, ITER, ITER / 5, 4 * (ITER / 5), 1); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done operations in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done operations in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -750,7 +649,7 @@ main() mix_operations(perm, ITER, nodes, ITER, ITER / 10, 9 * (ITER / 10), 1); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done operations in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done operations in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -770,7 +669,7 @@ main() mix_operations(perm, ITER, nodes, ITER, 5 * (ITER / 100), 95 * (ITER / 100), 1); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done operations in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done operations in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -790,7 +689,7 @@ main() mix_operations(perm, ITER, nodes, ITER, 2 * (ITER / 100), 98 * (ITER / 100), 1); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done operations in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done operations in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -805,6 +704,8 @@ main() timespecsub(&end, &start, &diff); TDEBUGF("done root removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("total augment count: %lld", augment_count); + free(nodes); free(perm); free(nums); @@ -841,6 +742,7 @@ static int tree_augment(struct node *elm) { size_t newsize = 1, newheight = 0; + augment_count++; if ((RB_LEFT(elm, node_link))) { newsize += (RB_LEFT(elm, node_link))->size; newheight = MAX((RB_LEFT(elm, node_link))->height, newheight); @@ -863,7 +765,10 @@ tree_augment(struct node *elm) void mix_operations(int *perm, int psize, struct node *nodes, int nsize, int insertions, int reads, int do_reads) { - int i, rank; + int i; +#ifdef RB_TEST_RANK + int rank; +#endif struct node *tmp, *ins; struct node it; assert(psize == nsize); @@ -879,7 +784,7 @@ mix_operations(int *perm, int psize, struct node *nodes, int nsize, int insertio //TDEBUGF("inserting %d", tmp->key); if (RB_INSERT(tree, &root, tmp) != NULL) errx(1, "RB_INSERT failed"); - print_tree(&root); + //print_tree(&root); #if DOAUGMENT //TDEBUGF("size = %zu", RB_ROOT(&root)->size); assert(RB_ROOT(&root)->size == i + 1); diff --git a/tests/test_subr.c b/tests/test_subr.c index cbba652..5813f6b 100644 --- a/tests/test_subr.c +++ b/tests/test_subr.c @@ -144,7 +144,7 @@ main() ins = rb_min(&root); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done getting min in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done getting min in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); assert(0 == ins->key); TDEBUGF("getting max"); @@ -152,7 +152,7 @@ main() ins = rb_max(&root); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done getting max in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done getting max in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); assert(ITER + 5 == ins->key); ins = rb_root(&root); @@ -188,7 +188,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -213,7 +213,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing find and remove in sequential order"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -234,7 +234,7 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); ins = rb_root(&root); if (ins == NULL) @@ -249,7 +249,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); //print_tree(&root); @@ -281,7 +281,7 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); ins = rb_root(&root); if (ins == NULL) @@ -294,7 +294,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing nfind and remove"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -317,7 +317,7 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #ifdef rb_next TDEBUGF("starting sequential insertions"); @@ -325,7 +325,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree with rb_next"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -339,7 +339,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree with rb_prev"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -353,7 +353,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -380,7 +380,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing pfind and remove"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -403,7 +403,7 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif #ifdef rb_findc @@ -412,7 +412,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing findc and removec"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -435,7 +435,7 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); ins = rb_root(&root); if (ins == NULL) @@ -450,7 +450,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing nfindc and removec"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -473,7 +473,7 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif #ifdef rb_pfindC @@ -482,7 +482,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing pfindc and removec"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -505,7 +505,7 @@ main() free(tmp); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done removals in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done removals in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif TDEBUGF("starting sequential insertions"); @@ -513,7 +513,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #ifdef RBT_FOREACH TDEBUGF("iterating over tree with RBT_FOREACH"); @@ -528,7 +528,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif #ifdef RBT_FOREACH_REVERSE @@ -544,7 +544,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif TDEBUGF("doing root removals"); @@ -571,7 +571,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree and clearing with RBT_FOREACH_SAFE"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -586,7 +586,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif #ifdef RBT_FOREACH_REVERSE_SAFE @@ -595,7 +595,7 @@ main() mix_operations(nums, ITER, nodes, ITER, ITER, 0, 0); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done sequential insertions in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done sequential insertions in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree and clearing with RBT_FOREACH_REVERSE_SAFE"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -610,7 +610,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif #ifdef rb_insert_next @@ -641,7 +641,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done insertions in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done insertions in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree and clearing with RBT_FOREACH_REVERSE_SAFE"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -650,7 +650,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif #ifdef rb_insert_prev @@ -681,7 +681,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done insertions in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done insertions in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("iterating over tree and clearing with RBT_FOREACH_REVERSE_SAFE"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -690,7 +690,7 @@ main() } clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done iterations in %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done iterations in %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); #endif TDEBUGF("doing 50%% insertions, 50%% lookups"); @@ -698,7 +698,7 @@ main() mix_operations(perm, ITER, nodes, ITER, ITER / 2, ITER / 2, 1); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done operations in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done operations in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -718,7 +718,7 @@ main() mix_operations(perm, ITER, nodes, ITER, ITER / 5, 4 * (ITER / 5), 1); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done operations in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done operations in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -738,7 +738,7 @@ main() mix_operations(perm, ITER, nodes, ITER, ITER / 10, 9 * (ITER / 10), 1); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done operations in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done operations in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -758,7 +758,7 @@ main() mix_operations(perm, ITER, nodes, ITER, 5 * (ITER / 100), 95 * (ITER / 100), 1); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done operations in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done operations in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start); @@ -778,7 +778,7 @@ main() mix_operations(perm, ITER, nodes, ITER, 2 * (ITER / 100), 98 * (ITER / 100), 1); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); timespecsub(&end, &start, &diff); - TDEBUGF("done operations in: %lld.%09ld s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); + TDEBUGF("done operations in: %llu.%09llu s", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_nsec); TDEBUGF("doing root removals"); clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start);